RAISERROR ile FLOAT kullanma


11

Ben kullanıyorum RAISERROR()bazı temel Birim Test işlevselliği (aynı sağlamak için burada ) ama kullanmaya zorlandıklarını am FLOATshata iletisinde. Ben bir dize şamandıra döküm biliyorum, ama RAISERRORher tek birim test kullanıyorum , her test için başka bir kod satırı eklemek istemiyorum. (Birim testlerim zaten yeterince garip!) Parametre listesinde satır içi döküm / dönüştürme yapmanın bir yolu var mı RAISERROR? Yoksa bu eksikliğin başka bir yolu var mı?

Güncelleme: Sonuçta ne yapabilseydim şu:

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

Ne yazık ki, RAISERROR% f veya genel olarak yüzer. Bunun yerine bunu yapmak zorundayım:

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

... düzinelerce Ünite Testi boyunca dağıldığında sadece karışıklık gibi görünüyor. Bu yüzden böyle bir şeye kaynatmak istiyorum:

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

Ama bu bana bir Incorrect syntax near 'CAST'mesaj getiriyor. Bunun neden yasadışı olduğunu anlamıyorum, ama öyle. Burada kullanabileceğim başka bir "tek astar" var mı?


Daha fazla açıklayabilir misiniz lütfen?
NoChance

Yanıtlar:


12

Ne yazık ki, ne sebeple olursa olsun, bu bağlamda satır içi bir dönüştürme yapamazsınız ve herhangi bir nedenle tekrar RAISERRORdoğrudan desteklemez float.

Bu cevabın eksiksiz olması için, MSDN'den daha önce gördüğünüz ilgili snippet'i aşağıda bulabilirsiniz (not: 2005'ten 2012'ye kadar belgelerin tüm sürümlerinde aynı metindir):

Her bir ikame parametresi yerel bir değişken veya şu veri türlerinden herhangi biri olabilir: tinyint , smallint , int , char , varchar , nchar , nvarchar , ikili veya varbinary .


Düşünebileceğim tek makul çözüm, RAISERRORçağrıyı sarmak için saklı bir yordam yazmak olacaktır . İşte bir başlangıç ​​noktası:

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

Ne yazık ki, bunu rastgele sayıda parametre için ölçeklemenin kolay bir yolu yok ... Muhtemelen hata ayıklamak için eğlenceli olan kıvrımlı iç içe dinamik SQL kullanılarak yapılabilir. Bunu okuyucu için bir egzersiz olarak bırakacağım.

Kullandığım sql_variantbile değer türleri için, kod tekdüzelik nedenlerden dolayı aynı prosedür her yerde kullanılabilir olacağı varsayımına olan doğrudan desteklenen RAISERROR. Ayrıca, bu uygunsa geçici bir saklı yordam olarak oluşturulabilir .

Bu prosedürü kullanmak şöyle görünecektir:

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;

Çıktı:

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)

Böylece net sonuç şamandıralar için biçimlendirme yeteneğine sahip olmamanız (kendiniz yuvarlamanız), ancak diğer türler için biçimlendirme yeteneğini korurken bunları çıktılama yeteneğini (ondalık / sayısal!) Elde etmenizdir.


Vay be, bu harika! Böyle bir şey yapmayı düşünmüştüm, ama farkında sql_variantdeğildim, bu yüzden argüman listesine sıkışmıştım ve bunun mümkün olmadığını varsaymıştım. Bugün bana çok faydalı bir şey öğrettin. Çok teşekkür ederim!
kmote

@kmote: Sorun değil; yardımcı olduğuma sevindim.
Jon Seigel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.