RAISERROR के साथ FLOATs का उपयोग करना


11

मैं RAISERROR()कुछ बुनियादी यूनिट परीक्षण कार्यक्षमता प्रदान करने के लिए उपयोग कर रहा हूं (जैसा कि यहां ), लेकिन मैं FLOATsत्रुटि संदेश में उपयोग करने में असमर्थता से निराश हूं । मुझे पता है कि मैं फ्लोट को एक स्ट्रिंग में डाल सकता हूं, लेकिन मैं RAISERRORहर एक यूनिट टेस्ट में उपयोग कर रहा हूं, मैं हर टेस्ट के लिए कोड की एक और लाइन नहीं जोड़ना चाहता। (मेरी इकाई परीक्षण पहले से ही काफी खराब हैं!) क्या इनलाइन कास्ट करने / RAISERRORपैरामीटर सूची में परिवर्तित करने का कोई तरीका है ? या इस कमी के आसपास एक और तरीका है?

अद्यतन: तो आखिरकार मैं चाहता हूं कि मैं यह कर सकता हूं:

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

दुर्भाग्य से, RAISERRORसामान्य रूप से% f या तैरता नहीं है। इसलिए मुझे इसके बजाय यह करना होगा:

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 तक प्रलेखन के सभी संस्करणों में एक ही पाठ है):

प्रत्येक प्रतिस्थापन पैरामीटर स्थानीय चर या इन डेटा प्रकारों में से कोई भी हो सकता है: स्मॉलिंट , स्मॉलिंट , इंट , चार , वर्चर , एनकर , नावरच , बाइनरी या वर्बिनरी


एकमात्र उचित समाधान जो मैं सोच सकता हूं कि 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_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)

तो शुद्ध परिणाम यह है कि आपको फ़्लोट्स के लिए फ़ॉर्मेटिंग की क्षमता नहीं मिलती है (अपने खुद के रोल करें), लेकिन आप अन्य प्रकारों के लिए फ़ॉर्मेटिंग क्षमता बनाए रखते हुए उन्हें (दशमलव / संख्यात्मक) भी आउटपुट करने की क्षमता प्राप्त करते हैं।


वाह, यह सिर्फ शानदार है! मैंने ऐसा कुछ करने पर विचार किया था, लेकिन इससे अनजान था sql_variant, इसलिए मैं तर्क सूची में फंस गया और यह मान लिया कि यह संभव नहीं था। आपने आज मुझे बहुत उपयोगी कुछ सिखाया है। आपका बहुत बहुत धन्यवाद!
kmote

@kmote: कोई समस्या नहीं; मैं खुशी से मदद कर सकता है।
जॉन सिगेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.