함수와 저장 프로 시저


88

결과로 테이블을 반환해야하는 T-SQL 코드를 구현해야한다고 가정 해 보겠습니다. 테이블 반환 함수 또는 행 집합을 반환하는 저장 프로 시저를 구현할 수 있습니다. 무엇을 사용해야합니까?

요컨대 내가 알고 싶은 것은 다음과 같습니다.

함수와 저장 프로 시저의 주요 차이점은 무엇입니까? 둘 중 하나를 사용할 때 고려해야 할 사항은 무엇입니까?


1
이 완벽한 해답이 될 것으로 보인다 stackoverflow.com/a/1179778/365188
Ozair Kafray

답변:


51

이 코드 조각의 결과를 다른 테이블과 결합하려는 경우 분명히 테이블 반환 함수를 사용하면 단일 SELECT 문으로 결과를 구성 할 수 있습니다.

일반적으로 계층 (View <TV Function <Stored Proc)이 있습니다. 각각에서 더 많은 작업을 수행 할 수 있지만 출력을 구성하는 능력과 기능이 증가함에 따라 최적화 프로그램이 실제로 참여하는 능력은 감소합니다.

따라서 원하는 결과를 표현할 수 있도록 최소한으로 사용하십시오.


50

함수는 결정적이어야하며 데이터베이스를 변경하는 데 사용할 수 없지만 저장 프로 시저를 사용하면 삽입 및 업데이트 등을 수행 할 수 있습니다.

크고 복잡한 쿼리에 대해 큰 확장 성 문제를 야기하므로 함수 사용을 제한해야합니다. 쿼리 옵티 마이저를위한 일종의 "블랙 박스"가되며 함수를 사용하는 것과 단순히 코드를 쿼리에 삽입하는 것 사이의 성능면에서 엄청난 차이를 볼 수 있습니다.

그러나 그들은 매우 특정한 경우에 테이블 값 반환에 확실히 유용합니다.

쉼표로 구분 된 목록을 구문 분석해야하는 경우 배열을 프로 시저에 전달하는 것을 시뮬레이션하기 위해 함수가 목록을 테이블로 변환 할 수 있습니다. 이것은 Sql Server 2005의 일반적인 관행입니다. 아직 테이블을 저장 프로 시저에 전달할 수 없기 때문입니다 (2008에서는 가능합니다).


1
하지만 XML을 저장 프로 시저로 보낼 수 있습니다 : stackoverflow.com/questions/144550/…
cllpse

2
잘못되었습니다. 대부분의 SQL 서버 함수는 MS-SQL 서버의 getdate와 같이 비 결정적입니다. ODBC 함수 만이 표준 함수입니다 (= 훨씬 빠름 + 인덱싱 가능) ... 그러나 매우 정확합니다. 성능상의 이유로 가능한 한 쿼리에서 함수 사용을 제한해야합니다.
Stefan Steiger

45

문서에서 :

저장 프로 시저가 다음 기준을 충족하는 경우 테이블 반환 함수로 다시 작성하기에 적합한 후보입니다.

  • 논리는 단일 SELECT 문으로 표현할 수 있지만 매개 변수가 필요하기 때문에 뷰가 아니라 저장 프로 시저입니다.

  • 저장 프로시 저는 테이블 변수를 제외하고 업데이트 작업을 수행하지 않습니다.

  • 동적 EXECUTE 문이 필요하지 않습니다.

  • 저장 프로시 저는 하나의 결과 집합을 반환합니다.

  • 저장 프로 시저의 주요 목적은 임시 테이블에로드 될 중간 결과를 빌드 한 다음 SELECT 문에서 쿼리하는 것입니다.


12

저장 프로 시저와 함수간에 몇 가지 흥미로운 차이점을 작성하겠습니다.

  • 선택 쿼리에서는 함수를 사용할 수 있지만 선택 쿼리에서는 저장 프로 시저를 사용할 수 없습니다.
  • 함수에서는 비 결정적 함수를 사용할 수 없지만 저장 프로 시저에서는 비 결정적 함수를 사용할 수 있습니다. 이제 질문이 나오면 비 결정적 함수가 무엇인지 .. Ans는 다음과 같습니다.

    비 결정적 함수는 getdate ()와 같이 서로 다른 시간에 동일한 입력 값에 대해 서로 다른 출력을 반환하는 함수입니다. 실행될 때마다 항상 다른 값을 반환합니다.

    예외:-

    SQL 2000 이전 버전의 SQL Server에서는 사용자 정의 함수에서 getdate () 함수를 사용할 수 없지만 2005 버전 이상에서는 사용자 정의 함수 내에서 getdate () 함수를 사용할 수 있습니다.

    Newid ()는 비 결정적 함수의 또 다른 예이지만 사용자 정의 함수에서는 사용할 수 없지만 저장 프로 시저에서는 사용할 수 있습니다.

  • 저장 프로 시저 내에서 DML (삽입, 업데이트, 삭제) 문을 사용할 수 있지만 물리적 테이블 또는 영구 테이블의 함수에는 DML 문을 사용할 수 없습니다. 함수에서 DML 작업을 수행하려면 영구 테이블이 아닌 테이블 변수에 대해 수행 할 수 있습니다.

  • 함수 내에서 오류 처리를 사용할 수 없지만 저장 프로 시저에서 오류 처리를 할 수 있습니다.


MySQL 함수에서 DML 작업이 어떻게 지원됩니까?
Joey Pinto

@JoeyPinto. myNONsql은 SQL 불만이 아니기 때문입니다. 물론 추가 기능은 있지만 기본 사항은 아닙니다.
PerformanceDBA

8
  1. 프로시 저는 0 또는 n 개의 값을 반환 할 수있는 반면 함수는 필수 인 하나의 값을 반환 할 수 있습니다.

  2. 프로시 저는 입력 / 출력 매개 변수를 가질 수 있지만 함수는 입력 매개 변수 만 가질 수 있습니다.

  3. 프로시 저는 선택 문과 DML 문을 허용하는 반면 함수는 선택문 만 허용합니다.

  4. 함수는 프로 시저에서 호출 할 수 있지만 프로시 저는 함수에서 호출 할 수 없습니다.

  5. 예외는 프로 시저에서 try-catch 블록으로 처리 할 수 ​​있지만 try-catch 블록은 함수에서 사용할 수 없습니다.

  6. 우리는 절차 상 거래 관리를 할 수 있지만 기능은 할 수 없습니다.

  7. 프로시 저는 select 문에서 사용할 수 없지만 function은 select 문에 포함 할 수 있습니다.

  8. UDF (사용자 정의 함수)는 WHERE/ HAVING/ SELECT섹션 의 SQL 문에서 사용할 수 있지만 저장 프로시 저는 사용할 수 없습니다.

  9. 테이블을 반환하는 UDF는 다른 행 집합으로 처리 될 수 있습니다. 이것은 JOIN다른 테이블과 함께 s 에서 사용할 수 있습니다 .

  10. 인라인 UDF는 매개 변수를 사용하는 뷰로 간주 될 수 있으며 JOINs 및 기타 행 집합 작업에 사용할 수 있습니다 .


6

함수가있는 경우이를 SQL 문의 일부로 사용할 수 있습니다. 예를 들면 다음과 같습니다.

SELECT function_name(field1) FROM table

저장 프로 시저에 대해서는 이러한 방식으로 작동하지 않습니다.


1
나는 그가 테이블 값을 반환하는 함수에 대해 이야기하고 있다고 생각합니다.
wcm

1
글쎄, 나는 일반적으로 이야기하고 있습니다. 그러나 내 특정 경우에는 현재 저장 프로 시저 또는 테이블 반환 함수 사이에 있습니다.
Auron

5

테이블 값 함수와 저장 프로 시저 모두에서 실행되는 동일한 코드 (긴 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

필자는이 기술을 여러 기능에 사용했으며 때로는이 유형의 "선택적"매개 변수 목록이 길기도합니다.


4

내가 반환하는 것은 영향이없는 단일 테이블 일 때 개인적으로 테이블 값 함수를 사용합니다. 기본적으로 매개 변수화 된 뷰처럼 취급합니다.

여러 레코드 집합을 반환해야하거나 테이블에 업데이트 된 값이있을 경우 저장 프로 시저를 사용합니다.

내 2 센트


4

위에서 언급했듯이 함수는 읽기 / 구성 / 자체 문서화가 더 많지만 일반적으로 성능이 떨어지며 다음과 같은 조인에서 함수를 사용하면 성능이 크게 떨어질 수 있습니다.

SELECT *
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2
    ON (tvf1.JoinId = tvf2.JoinId)

종종, 당신은 tvf가 제거 할 수있는 코드의 중복을 받아 들여야합니다 (허용 할 수없는 성능 비용으로).

내가 아직 언급하지 않은 또 다른 요점은 다중 문 tvf 내부에서 데이터베이스 상태 변경 임시 테이블을 사용할 수 없다는 것입니다. 임시 테이블과 가장 기능적으로 동등한 메커니즘은 메모리 테이블 변수에서 상태가 변경되지 않는 것이며 대규모 데이터 세트의 경우 임시 테이블이 테이블 변수보다 성능이 더 뛰어납니다. (다른 대안에는 동적 테이블 및 공통 테이블 값 표현식이 포함되지만 어느 정도 복잡성 수준에서는 좋은 옵션 IMO가 아닙니다.)


1

나는 둘 다 성능 테스트를 할 것입니다. sp 접근법 또는 파생 테이블이 함수보다 훨씬 빠를 가능성이 높으며 그렇다면 해당 접근법을 사용해야합니다. 일반적으로 나는 기능이 성능을 저하시킬 수 있기 때문에 기능을 피합니다.


1

다른 프로 시저에서 테이블 반환 결과를 사용하려면 TableValued 함수를 사용하는 것이 좋습니다. 결과가 클라이언트에 대한 것이라면 저장된 proc이 일반적으로 더 나은 방법입니다.


-1

저장 프로시 저는 더 빠르게 실행되고 SQL 주입에서 저장되는 미리 컴파일 된 쿼리입니다. 0 또는 N 값을 반환 할 수 있습니다. 저장 프로 시저 내에서 DML 작업을 수행 할 수 있습니다. 프로 시저 내에서 함수를 사용할 수 있고 선택 쿼리에서 함수를 사용할 수 있습니다. 함수는 함수에서 불가능한 값 및 DML 연산을 반환하는 데 사용됩니다. 함수는 두 가지 유형의 스칼라 및 테이블 값입니다. 스칼라 함수는 테이블 행을 반환하는 데 사용되는 단일 값 테이블 반환 함수를 반환합니다.


이것은 많은 수의 답변이있는 매우 오래된 질문이며, 많은 답변 (수락 된 답변 포함)이 높게 찬성되었습니다. 이러한 스레드에 다른 답변을 추가하기 전에 "다른 답변을 작성해야하는 기존 답변이 모두 부족한 것은 무엇입니까?"라고
APC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.