함수와 저장 프로 시저


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.