필터 매개 변수를 사용하거나 사용하지 않을 수있는 많은 작업이 포함 된 저장 프로 시저를 작성하고 있습니다. 필터링을 수행하는 것은 자체적으로 비용이 많이 들고 필터링되는 테이블이 큽니다. 방금 내부 필터 함수를 변경하려고 시도 했으므로 잘못된 매개 변수를 사용하여 호출하면 오류가 발생합니다. 개발자가 이러한 방식으로 사용하지 않도록 경고합니다.Sql Server UDF는 null이있는 변수가 전달 될 때와 달리 null이 전달 될 때와 다르게 동작합니다.
하지만 내 외부 테스트 함수를 NULL로 호출하면 내부 함수를 호출하지 않고 오류를 던지지 않고 예상대로 작동합니다. VALUE 값이 NULL 인 변수로 외부 테스트 함수를 호출하면 null 매개 변수를 사용하여 필터 함수를 호출하고 값이 null이 아닐 때 코드가 함수를 호출한다고 만 생각하더라도 오류가 발생합니다.
여기 무슨 일 이니?
훨씬 간단한 예 :
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MyTable]') AND type in (N'U')) DROP TABLE MyTable
GO
CREATE TABLE MyTable (Pk int, Field int)
GO
INSERT INTO MyTable VALUES (1, 1)
INSERT INTO MyTable VALUES (2, 4)
INSERT INTO MyTable VALUES (3, 9)
INSERT INTO MyTable VALUES (4, 16)
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[FilterRows]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) DROP FUNCTION FilterRows
GO
CREATE FUNCTION FilterRows(@searchParameter int)
RETURNS @Pks TABLE
(
Pk int
)
AS
BEGIN
IF (@searchParameter IS null)
BEGIN
-- This is bad news. We don't want to be here with a null search, as the only thing we can do is return every row in the whole table
-- RAISERROR ('Avoid calling FilterRows with no search parameter', 16, 1)
-- we can't raise errors in functions!
-- Make it divide by zero instead then
INSERT INTO @Pks SELECT Pk FROM MyTable WHERE 1/0 = 1
END
ELSE
BEGIN
INSERT INTO @Pks SELECT Pk FROM MyTable WHERE Field > @searchParameter
END
RETURN
END
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[OuterFunction]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) DROP FUNCTION OuterFunction
GO
CREATE FUNCTION OuterFunction(@searchParameter int)
RETURNS TABLE AS
RETURN
SELECT *
FROM
MyTable
WHERE
(@SearchParameter IS NULL) OR (@searchParameter IS NOT NULL AND Pk IN (SELECT Pk FROM dbo.FilterRows(@searchParameter)))
GO
SELECT * FROM dbo.OuterFunction(2) -- Returns filtered values
SELECT * FROM dbo.OuterFunction(null) -- returns everything, doesn't call FilterRows
DECLARE @x int = null
SELECT * FROM dbo.OuterFunction(@x) -- WTF! Throws error!
"선택적 필터"는 옵티마이 저가 * 첫 번째 호출에 대해 생성 된 실행 계획을 캐시하므로 설계상의 실수입니다. 단락의 대신에 당신은 더 나쁜 성과로 끝낼 것이다. 그런 것들에 대한 필요성은 ORM과 LINQ를 사용하여 필요한 필터만으로 쿼리를 생성합니다. ad-hoc 쿼리 또는 이와 동등한 저장 프로 시저를 실행하는지 여부에 관계없이 성능은 동일합니다. –
PS 필터링은 비용이 많이 드는 것과 반대입니다. 결과가 줄어 듭니다. 그렇지 않은 경우 쿼리에 문제가 있습니다. 적절한 색인이있는 경우 조건이 많을수록 * 더 빨리 실행됩니다."단락"시도는 * 느린 * 실행으로 이어집니다. 왜냐하면 그들은 무엇을 발견하기 위해 모든 것을 처리해야하기 때문입니다 ... –
간결한 질문을하기 위해 상황을 의도적으로 단순화했습니다. 내가하고있는 일을하기에 좋은 이유가 있으며 쿼리 분석기의 작동 방식을 알고 있습니다. 내가 묻는 질문은 UDF의 예기치 않은 동작에 관한 것입니다. 나는 달성하려고 애 쓰고있는 것이 잘못을 저지르는 것이라고 단골 손님에게 묻고 싶지 않다. –