RAISERRORでのFLOATの使用


11

私は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'メッセージを送ります。それが違法である理由はわかりませんが、違法です。代わりにここで使用できる別の「ワンライナー」はありますか?


詳しく説明していただけますか?
NoChance

回答:


12

残念ながら、何らかの理由で、そのコンテキストでインライン変換を行うことはできません。また、何らかの理由でをRAISERROR直接サポートすることはできませんfloat

この回答を完全にするために、MSDNの関連スニペットを以下に示します。これは、すでに見たことがあると思います(注:2005年から2012年までのドキュメントのすべてのバージョンで同じテキストです)。

各置換パラメーターは、ローカル変数、またはtinyintsmallintintcharvarcharncharnvarcharbinary、または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進数/数値も!)を出力することができます。


うわー、それは素晴らしいです!私はこのようなことをすることを考えていましたが、に気づかなかったsql_variantので、引数リストに行き詰まり、それは不可能だと思いました。今日はとても便利なことを教えてくれました。どうもありがとうございました!
kmote 2012

@kmote:問題ありません。お役に立てて嬉しいです。
Jon Seigel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.