결과로 테이블을 반환해야하는 T-SQL 코드를 구현해야한다고 가정 해 보겠습니다. 테이블 반환 함수 또는 행 집합을 반환하는 저장 프로 시저를 구현할 수 있습니다. 무엇을 사용해야합니까?
요컨대 내가 알고 싶은 것은 다음과 같습니다.
함수와 저장 프로 시저의 주요 차이점은 무엇입니까? 둘 중 하나를 사용할 때 고려해야 할 사항은 무엇입니까?
답변:
이 코드 조각의 결과를 다른 테이블과 결합하려는 경우 분명히 테이블 반환 함수를 사용하면 단일 SELECT 문으로 결과를 구성 할 수 있습니다.
일반적으로 계층 (View <TV Function <Stored Proc)이 있습니다. 각각에서 더 많은 작업을 수행 할 수 있지만 출력을 구성하는 능력과 기능이 증가함에 따라 최적화 프로그램이 실제로 참여하는 능력은 감소합니다.
따라서 원하는 결과를 표현할 수 있도록 최소한으로 사용하십시오.
함수는 결정적이어야하며 데이터베이스를 변경하는 데 사용할 수 없지만 저장 프로 시저를 사용하면 삽입 및 업데이트 등을 수행 할 수 있습니다.
크고 복잡한 쿼리에 대해 큰 확장 성 문제를 야기하므로 함수 사용을 제한해야합니다. 쿼리 옵티 마이저를위한 일종의 "블랙 박스"가되며 함수를 사용하는 것과 단순히 코드를 쿼리에 삽입하는 것 사이의 성능면에서 엄청난 차이를 볼 수 있습니다.
그러나 그들은 매우 특정한 경우에 테이블 값 반환에 확실히 유용합니다.
쉼표로 구분 된 목록을 구문 분석해야하는 경우 배열을 프로 시저에 전달하는 것을 시뮬레이션하기 위해 함수가 목록을 테이블로 변환 할 수 있습니다. 이것은 Sql Server 2005의 일반적인 관행입니다. 아직 테이블을 저장 프로 시저에 전달할 수 없기 때문입니다 (2008에서는 가능합니다).
문서에서 :
저장 프로 시저가 다음 기준을 충족하는 경우 테이블 반환 함수로 다시 작성하기에 적합한 후보입니다.
논리는 단일 SELECT 문으로 표현할 수 있지만 매개 변수가 필요하기 때문에 뷰가 아니라 저장 프로 시저입니다.
저장 프로시 저는 테이블 변수를 제외하고 업데이트 작업을 수행하지 않습니다.
동적 EXECUTE 문이 필요하지 않습니다.
저장 프로시 저는 하나의 결과 집합을 반환합니다.
저장 프로 시저의 주요 목적은 임시 테이블에로드 될 중간 결과를 빌드 한 다음 SELECT 문에서 쿼리하는 것입니다.
저장 프로 시저와 함수간에 몇 가지 흥미로운 차이점을 작성하겠습니다.
함수에서는 비 결정적 함수를 사용할 수 없지만 저장 프로 시저에서는 비 결정적 함수를 사용할 수 있습니다. 이제 질문이 나오면 비 결정적 함수가 무엇인지 .. Ans는 다음과 같습니다.
비 결정적 함수는 getdate ()와 같이 서로 다른 시간에 동일한 입력 값에 대해 서로 다른 출력을 반환하는 함수입니다. 실행될 때마다 항상 다른 값을 반환합니다.
예외:-
SQL 2000 이전 버전의 SQL Server에서는 사용자 정의 함수에서 getdate () 함수를 사용할 수 없지만 2005 버전 이상에서는 사용자 정의 함수 내에서 getdate () 함수를 사용할 수 있습니다.
Newid ()는 비 결정적 함수의 또 다른 예이지만 사용자 정의 함수에서는 사용할 수 없지만 저장 프로 시저에서는 사용할 수 있습니다.
저장 프로 시저 내에서 DML (삽입, 업데이트, 삭제) 문을 사용할 수 있지만 물리적 테이블 또는 영구 테이블의 함수에는 DML 문을 사용할 수 없습니다. 함수에서 DML 작업을 수행하려면 영구 테이블이 아닌 테이블 변수에 대해 수행 할 수 있습니다.
함수 내에서 오류 처리를 사용할 수 없지만 저장 프로 시저에서 오류 처리를 할 수 있습니다.
프로시 저는 0 또는 n 개의 값을 반환 할 수있는 반면 함수는 필수 인 하나의 값을 반환 할 수 있습니다.
프로시 저는 입력 / 출력 매개 변수를 가질 수 있지만 함수는 입력 매개 변수 만 가질 수 있습니다.
프로시 저는 선택 문과 DML 문을 허용하는 반면 함수는 선택문 만 허용합니다.
함수는 프로 시저에서 호출 할 수 있지만 프로시 저는 함수에서 호출 할 수 없습니다.
예외는 프로 시저에서 try-catch 블록으로 처리 할 수 있지만 try-catch 블록은 함수에서 사용할 수 없습니다.
우리는 절차 상 거래 관리를 할 수 있지만 기능은 할 수 없습니다.
프로시 저는 select 문에서 사용할 수 없지만 function은 select 문에 포함 할 수 있습니다.
UDF (사용자 정의 함수)는 WHERE
/ HAVING
/ SELECT
섹션 의 SQL 문에서 사용할 수 있지만 저장 프로시 저는 사용할 수 없습니다.
테이블을 반환하는 UDF는 다른 행 집합으로 처리 될 수 있습니다. 이것은 JOIN
다른 테이블과 함께 s 에서 사용할 수 있습니다 .
인라인 UDF는 매개 변수를 사용하는 뷰로 간주 될 수 있으며 JOIN
s 및 기타 행 집합 작업에 사용할 수 있습니다 .
테이블 값 함수와 저장 프로 시저 모두에서 실행되는 동일한 코드 (긴 SELECT 문)와 곧은 EXEC / SELECT를 사용하여 오래 실행되는 논리 비트로 몇 가지 테스트를 실행했으며 각각 동일하게 수행했습니다.
내 생각에는 항상 저장 프로 시저 대신 테이블 반환 함수를 사용하여 결과 집합을 반환합니다. 이는 이후에 조인되는 쿼리에서 논리를 훨씬 쉽고 읽기 쉽게 만들고 동일한 논리를 재사용 할 수있게 해주기 때문입니다. 너무 많은 성능 저하를 방지하기 위해 종종 "선택적"매개 변수 (즉, NULL을 전달할 수 있음)를 사용하여 함수가 결과 집합을 더 빠르게 반환 할 수 있도록합니다. 예 :
CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int)
AS
RETURN
SELECT DISTINCT SiteID, PersonID
FROM dbo.SiteViewPermissions
WHERE (@optPersonID IS NULL OR @optPersonID = PersonID)
AND (@optSiteID IS NULL OR @optSiteID = SiteID)
AND @RegionID = RegionID
이렇게하면 다양한 상황에서이 기능을 사용할 수 있으며 성능이 크게 저하되지 않습니다. 나중에 필터링하는 것보다 이것이 더 효율적이라고 생각합니다.
SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1
필자는이 기술을 여러 기능에 사용했으며 때로는이 유형의 "선택적"매개 변수 목록이 길기도합니다.
위에서 언급했듯이 함수는 읽기 / 구성 / 자체 문서화가 더 많지만 일반적으로 성능이 떨어지며 다음과 같은 조인에서 함수를 사용하면 성능이 크게 떨어질 수 있습니다.
SELECT *
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2
ON (tvf1.JoinId = tvf2.JoinId)
종종, 당신은 tvf가 제거 할 수있는 코드의 중복을 받아 들여야합니다 (허용 할 수없는 성능 비용으로).
내가 아직 언급하지 않은 또 다른 요점은 다중 문 tvf 내부에서 데이터베이스 상태 변경 임시 테이블을 사용할 수 없다는 것입니다. 임시 테이블과 가장 기능적으로 동등한 메커니즘은 메모리 테이블 변수에서 상태가 변경되지 않는 것이며 대규모 데이터 세트의 경우 임시 테이블이 테이블 변수보다 성능이 더 뛰어납니다. (다른 대안에는 동적 테이블 및 공통 테이블 값 표현식이 포함되지만 어느 정도 복잡성 수준에서는 좋은 옵션 IMO가 아닙니다.)
저장 프로시 저는 더 빠르게 실행되고 SQL 주입에서 저장되는 미리 컴파일 된 쿼리입니다. 0 또는 N 값을 반환 할 수 있습니다. 저장 프로 시저 내에서 DML 작업을 수행 할 수 있습니다. 프로 시저 내에서 함수를 사용할 수 있고 선택 쿼리에서 함수를 사용할 수 있습니다. 함수는 함수에서 불가능한 값 및 DML 연산을 반환하는 데 사용됩니다. 함수는 두 가지 유형의 스칼라 및 테이블 값입니다. 스칼라 함수는 테이블 행을 반환하는 데 사용되는 단일 값 테이블 반환 함수를 반환합니다.