복붙노트

[SQL] 어떻게 SQL Server 사용자 정의 함수에서 오류를보고하는 방법

SQL

어떻게 SQL Server 사용자 정의 함수에서 오류를보고하는 방법

내가 그 기능은 일반적인 방법으로 오류를 발생시킬 수 없습니다 알고 2008 년 나는 SQL Server에서 사용자 정의 함수를 쓰고 있어요 - 당신이 RAISERROR 문 SQL 리턴을 포함하려고하면 :

Msg 443, Level 16, State 14, Procedure ..., Line ...
Invalid use of a side-effecting operator 'RAISERROR' within a function.

그러나 사실은 함수는 경우, 함수가 반환 할 수있는 의미있는 값이 없습니다 무효가 될 수있는 몇 가지 입력을 소요하고있다. 그럼 어떻게해야합니까?

나는 물론, NULL을 반환 할 수 있지만,이 문제를 해결하는 기능을 사용하는 개발자가 어렵다. 또한 같은 제로 또는 무언가에 의해 분열을 일으킬 수 있습니다 -이 오류 메시지가 있지만 오해의 소지를 생성합니다. 난 내 자신의 오류 메시지가 어떻게 든보고 할 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.당신은 의미있는 오류를 던져 CAST를 사용할 수 있습니다 :

    당신은 의미있는 오류를 던져 CAST를 사용할 수 있습니다 :

    create function dbo.throwError()
    returns nvarchar(max)
    as
    begin
        return cast('Error happened here.' as int);
    end
    

    다음 SQL Server는 몇 가지 도움말 정보를 표시합니다 :

    Msg 245, Level 16, State 1, Line 1
    Conversion failed when converting the varchar value 'Error happened here.' to data type int.
    
  2. ==============================

    2.일반적인 트릭에서 오류가 발생하고 기능을 평가하고 현재의 문을 중단합니다 0이에 의해 나누기를 강제하는 것입니다. 개발자 또는 지원 사람이 조사하고 문제를 해결하는 방법이 문제에 대해 알고있는 경우 매우 쉽게 0 오류에 의한 분할이 다른, 관련이없는 문제의 증상으로 이해 될 때입니다.

    일반적인 트릭에서 오류가 발생하고 기능을 평가하고 현재의 문을 중단합니다 0이에 의해 나누기를 강제하는 것입니다. 개발자 또는 지원 사람이 조사하고 문제를 해결하는 방법이 문제에 대해 알고있는 경우 매우 쉽게 0 오류에 의한 분할이 다른, 관련이없는 문제의 증상으로 이해 될 때입니다.

    보기의 모든 지점에서이 모습 나쁜 것처럼, 순간 SQL 함수의 불행하게도 디자인은 더 나은 선택을 할 수 있습니다. 사용 RAISERROR 절대적으로 기능을 허용해야한다.

  3. ==============================

    3.블라디미르 코롤 레프의 대답에 이어, 관용구 조건부 오류가 던져

    블라디미르 코롤 레프의 대답에 이어, 관용구 조건부 오류가 던져

    CREATE FUNCTION [dbo].[Throw]
    (
        @error NVARCHAR(MAX)
    )
    RETURNS BIT
    AS
    BEGIN
        RETURN CAST(@error AS INT)
    END
    GO
    
    DECLARE @error NVARCHAR(MAX)
    DECLARE @bit BIT
    
    IF `error condition` SET @error = 'My Error'
    ELSE SET @error = '0'
    
    SET @bit = [dbo].[Throw](@error)    
    
  4. ==============================

    4.내가 가장 깨끗한 방법은 단지 잘못된 인수가 전달되는 경우 함수가 NULL을 반환 할 수 있음을 동의하는 것입니다 생각합니다. 한은이 명확이 괜찮을 것 같네요 다음 설명되어 있습니까?

    내가 가장 깨끗한 방법은 단지 잘못된 인수가 전달되는 경우 함수가 NULL을 반환 할 수 있음을 동의하는 것입니다 생각합니다. 한은이 명확이 괜찮을 것 같네요 다음 설명되어 있습니까?

    -- =============================================
    -- Author: AM
    -- Create date: 03/02/2010
    -- Description: Returns the appropriate exchange rate
    -- based on the input parameters.
    -- If the rate cannot be found, returns NULL
    -- (RAISEERROR can't be used in UDFs)
    -- =============================================
    ALTER FUNCTION [dbo].[GetExchangeRate] 
    (
        @CurrencyFrom char(3),
        @CurrencyTo char(3),
        @OnDate date
    )
    RETURNS decimal(18,4)
    AS
    BEGIN
    
      DECLARE @ClosingRate as decimal(18,4)
    
        SELECT TOP 1
            @ClosingRate=ClosingRate
        FROM
            [FactCurrencyRate]
        WHERE
            FromCurrencyCode=@CurrencyFrom AND
            ToCurrencyCode=@CurrencyTo AND
            DateID=dbo.DateToIntegerKey(@OnDate)
    
        RETURN @ClosingRate 
    
    END
    GO
    
  5. ==============================

    5.RAISEERROR 또는 @@ ERROR는 UDF를 사용할 수 없습니다. 당신은 strored 프로 시저에 UDF를 설정 할 수 있나요?

    RAISEERROR 또는 @@ ERROR는 UDF를 사용할 수 없습니다. 당신은 strored 프로 시저에 UDF를 설정 할 수 있나요?

    SQL Server의 ERLAND Sommarskog의 기사 오류 처리에서 - 배경 :

  6. ==============================

    6.상단의 대답은 일반적으로 가장 좋지만 인라인 테이블 반환 함수에 대한 작업을하지 않습니다.

    상단의 대답은 일반적으로 가장 좋지만 인라인 테이블 반환 함수에 대한 작업을하지 않습니다.

    MikeTeeVee 상단의 대답에 자신의 의견이에 대한 해결책을 준,하지만 내 상황을 위해 잘 작동하지 않았다 MAX 같은 집계 함수의 사용이 필요합니다.

    나는 당신이 선택 * 대신 총 같은 것을 반환 뭔가 UDF 가치 인라인 테이블을 필요로하는 경우에 대한 대체 솔루션으로 주위를 엉망. 이 특정 사건을 해결하는 샘플 코드는 다음과 같습니다. 누군가가 이미 지적했듯이 ... "이름 : Jeez의 wotta 해킹": 나는이 사건에 대한 더 나은 솔루션을 환영합니다!

    create table foo (
        ID nvarchar(255),
        Data nvarchar(255)
    )
    go
    
    insert into foo (ID, Data) values ('Green Eggs', 'Ham')
    go
    
    create function dbo.GetFoo(@aID nvarchar(255)) returns table as return (
        select *, 0 as CausesError from foo where ID = @aID
    
        --error checking code is embedded within this union
        --when the ID exists, this second selection is empty due to where clause at end
        --when ID doesn't exist, invalid cast with case statement conditionally causes an error
        --case statement is very hack-y, but this was the only way I could get the code to compile
        --for an inline TVF
        --simpler approaches were caught at compile time by SQL Server
        union
    
        select top 1 *, case
                            when ((select top 1 ID from foo where ID = @aID) = @aID) then 0
                            else 'Error in GetFoo() - ID "' + IsNull(@aID, 'null') + '" does not exist'
                        end
        from foo where (not exists (select ID from foo where ID = @aID))
    )
    go
    
    --this does not cause an error
    select * from dbo.GetFoo('Green Eggs')
    go
    
    --this does cause an error
    select * from dbo.GetFoo('Yellow Eggs')
    go
    
    drop function dbo.GetFoo
    go
    
    drop table foo
    go
    
  7. ==============================

    7.당신이 "RETURN [무효 캐스트]"종류의 물건을 사용할 수 없기 때문에 몇 사람들은, 테이블 반환 함수의 오류를 제기에 대해 질문했다. 단지뿐만 아니라 변수 작품 잘못된 캐스트를 할당.

    당신이 "RETURN [무효 캐스트]"종류의 물건을 사용할 수 없기 때문에 몇 사람들은, 테이블 반환 함수의 오류를 제기에 대해 질문했다. 단지뿐만 아니라 변수 작품 잘못된 캐스트를 할당.

    CREATE FUNCTION fn()
    RETURNS @T TABLE (Col CHAR)  
    AS
    BEGIN
    
    DECLARE @i INT = CAST('booooom!' AS INT)  
    
    RETURN
    
    END
    

    이 결과 :

  8. ==============================

    8.나는 테이블 반환 함수에 대한 davec의 대답에서 언급 할 수 있지만, 내 소견이 쉽게 솔루션입니다 :

    나는 테이블 반환 함수에 대한 davec의 대답에서 언급 할 수 있지만, 내 소견이 쉽게 솔루션입니다 :

    CREATE FUNCTION dbo.ufn_test (@a TINYINT)
    RETURNS @returns TABLE(Column1 VARCHAR(10), Value1 TINYINT)
    BEGIN
        IF @a>50 -- if @a > 50 - raise an error
        BEGIN
          INSERT INTO @returns (Column1, Value1)
          VALUES('error','@a is bigger than 50!') -- reminder Value1 should be TINYINT
        END
    
        INSERT INTO @returns (Column1, Value1)
        VALUES('Something',@a)
        RETURN;
    END
    
    SELECT Column1, Value1 FROM dbo.ufn_test(1) -- this is okay
    SELECT Column1, Value1 FROM dbo.ufn_test(51) -- this will raise an error
    
  9. ==============================

    9.한 가지 방법 (해킹) 함수 / 저장 프로 시저 수행하는 잘못된 행동을하는 것입니다. 예를 들어, 의사 SQL을 다음

    한 가지 방법 (해킹) 함수 / 저장 프로 시저 수행하는 잘못된 행동을하는 것입니다. 예를 들어, 의사 SQL을 다음

    create procedure throw_error ( in err_msg varchar(255))
    begin
    insert into tbl_throw_error (id, msg) values (null, err_msg);
    insert into tbl_throw_error (id, msg) values (null, err_msg);
    end;
    

    어디 테이블 tbl_throw_error에 열 ERR_MSG에 고유 제한 조건이있다. 이러한 부작용은 (적어도 MySQL을)는 애플리케이션 레벨 예외 객체들로 돌아 오면 ERR_MSG 값이 예외의 설명으로 사용된다는 것이다.

    당신은 SQL 서버와 비슷한,하지만 가치가 샷을 할 수 있을지 모르겠어요.

  10. from https://stackoverflow.com/questions/1485034/how-to-report-an-error-from-a-sql-server-user-defined-function by cc-by-sa and MIT license