RAISERROR와 함께 FLOAT 사용 캐스트 / 변환 을 수행하는 방법이

RAISERROR()기본 단위 테스트 기능을 제공하기 위해 사용 하고 있지만 ( 여기 참조 ) FLOATs오류 메시지 에 사용할 수 없기 때문에 실망 합니다. 플로트를 문자열로 캐스팅 할 수 있다는 것을 알고 있지만 RAISERROR모든 단일 단위 테스트에서 사용 하고 있습니다. 모든 테스트마다 다른 코드 줄을 추가하고 싶지 않습니다. (내 단위 테스트는 이미 충분합니다!) 매개 변수 목록 내에서 인라인 캐스트 / 변환 을 수행하는 방법이 RAISERROR있습니까? 아니면이 결함에 대한 다른 방법이 있습니까?

업데이트 :
궁극적으로 내가 할 수있는 일은 이것입니다.

RAISERROR('Unit Test FAILED! %f', 11, 0, @floatParm)

불행히도, RAISERROR일반적으로 % f 또는 float를 처리하지 않습니다. 그래서 나는 이것을 대신해야합니다 :

DECLARE @str VARCHAR(40) = CAST(@floatParm AS VARCHAR(40))
RAISERROR('Unit Test FAILED! %s', 11, 0, @str)

… 수십 개의 단위 테스트로 흩어져있을 때 혼란스러워 보입니다. 그래서 나는 이것을 다음과 같이 끓이고 싶습니다.

RAISERROR('Unit Test FAILED! %s', 11, 0, CAST(@floatParm AS VARCHAR(40))

그러나 그것은 나에게 Incorrect syntax near 'CAST'메시지 를 얻는다 . 왜 이것이 불법인지 이해하지 못합니다. 대신 여기에 사용할 수있는 또 하나의 “라이너”가 있습니까?



답변

불행히도 어떤 이유로 든 해당 컨텍스트에서 인라인 변환을 수행 할 수 없으며 어떤 이유로 든 다시 RAISERROR직접 지원하지 않습니다 float.

이 답변의 완성을 위해 MSDN 의 관련 스 니펫이 있습니다.이 기사 는 이미 보았습니다 (참고 : 2005 년부터 2012 년까지 모든 버전의 문서에서 동일한 텍스트입니다).

각 대체 매개 변수는 로컬 변수이거나 tinyint , smallint , int , char , varchar , nchar , nvarchar , binary 또는 varbinary 데이터 유형 중 하나 일 수 있습니다 .


내가 생각할 수있는 유일한 합리적인 해결책은 RAISERROR호출 을 래핑하기 위해 저장 프로 시저를 작성하는 것 입니다. 시작점은 다음과 같습니다.

CREATE PROCEDURE [dbo].[MyRaiserror]
(
    @message nvarchar(2048),
    @severity tinyint,
    @state tinyint,
    @arg0 sql_variant = NULL
)
AS
BEGIN

    DECLARE @msg nvarchar(MAX) = REPLACE(@message, '%f', '%s');
    DECLARE @sql nvarchar(MAX) = N'RAISERROR(@msg, @severity, @state';

    DECLARE @int0 int, @char0 nvarchar(MAX), @bin0 varbinary(MAX);

    IF (@arg0 IS NOT NULL)
    BEGIN
        SET @sql += N', ';

        IF (SQL_VARIANT_PROPERTY(@arg0, 'BaseType') IN ('tinyint', 'smallint', 'int'))
        BEGIN
            SET @int0 = CONVERT(int, @arg0);
            SET @sql += N'@int0';
        END
        ELSE IF (SQL_VARIANT_PROPERTY(@arg0, 'BaseType') IN ('binary', 'varbinary'))
        BEGIN
            SET @bin0 = CONVERT(varbinary(MAX), @arg0);
            SET @sql += N'@bin0';
        END
        ELSE
        BEGIN
            SET @char0 = CONVERT(nvarchar(MAX), @arg0);
            SET @sql += N'@char0';
        END
    END

    SET @sql += N');';

    EXEC sp_executesql
        @sql,
        N'@msg nvarchar(2048), @severity tinyint, @state tinyint, @int0 int, @bin0 varbinary(MAX), @char0 nvarchar(MAX)',
        @msg, @severity, @state, @int0, @bin0, @char0;

END

안타깝게도 임의의 수의 매개 변수에 대해이를 쉽게 확장 할 수있는 방법은 없습니다 … 아마도 복잡한 중첩 동적 SQL을 사용하여 디버깅 할 수 있습니다. 나는 그것을 독자들을위한 연습으로 남겨 둘 것이다.

내가 사용 sql_variant도 값 유형, 코드 균일 이유로, 동일한 절차가 모든 곳에서 사용되는 것을 전제로 하는 직접 지원 RAISERROR. 또한 적절한 경우 임시 저장 프로 시저 로 만들 수도 있습니다 .

이 절차를 사용하는 모습은 다음과 같습니다.

DECLARE @f float = 0.02345;
DECLARE @i int = 234;
DECLARE @s varchar(20) = 'asdfasdf';
DECLARE @b binary(4) = 0xA0B1C2D3;
DECLARE @d decimal(18, 9) = 152.2323;
DECLARE @n int = NULL;

EXEC [dbo].[MyRaiserror] N'Error message with no params.', 10, 1;
EXEC [dbo].[MyRaiserror] N'Float value = %f', 10, 1, @f;
EXEC [dbo].[MyRaiserror] N'Int value = %i', 10, 1, @i;
EXEC [dbo].[MyRaiserror] N'Character value = %s', 10, 1, @s;
EXEC [dbo].[MyRaiserror] N'Binary value = %#x', 10, 1, @b;
EXEC [dbo].[MyRaiserror] N'Decimal value = %f', 10, 1, @d;
EXEC [dbo].[MyRaiserror] N'Null value = %i', 10, 1, @n;

산출:

Error message with no params.
Float value = 0.02345
Int value = 234
Character value = asdfasdf
Binary value = 0xa0b1c2d3
Decimal value = 152.232300000
Null value = (null)

따라서 결과는 부동 소수점에 대한 서식 기능을 얻지 못하고 (자신의 롤을 굴림) 다른 유형의 서식 기능을 유지하면서 10 진수 / 숫자를 출력하는 기능을 얻습니다.