Niestety, z jakiegokolwiek powodu, nie można wykonać bezpośredniej konwersji w tym kontekście i ponownie RAISERRORnie obsługuje bezpośrednio float, z jakiegokolwiek powodu.
Aby uzyskać kompletność tej odpowiedzi, oto odpowiedni fragment z MSDN , który na pewno już widziałeś (uwaga: to ten sam tekst we wszystkich wersjach dokumentacji od 2005 do 2012 roku):
Każdy parametr podstawienia może być zmienną lokalną lub dowolnym z tych typów danych: tinyint , smallint , int , char , varchar , nchar , nvarchar , binary lub varbinary .
Jedynym rozsądnym rozwiązaniem, jakie mogę wymyślić, byłoby napisanie procedury składowanej, aby zakończyć RAISERRORpołączenie. Oto punkt wyjścia:
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
Niestety, nie ma łatwego sposobu na skalowanie tego dla dowolnej liczby parametrów ... Prawdopodobnie można to zrobić za pomocą zawiniętego zagnieżdżonego dynamicznego SQL, co byłoby przyjemne w debugowaniu. Zostawię to jako ćwiczenie dla czytelnika.
Kiedyś sql_variantna założeniu, że ze względu na kod jednorodności, ta sama procedura będzie używane wszędzie, nawet dla typów wartości, które są obsługiwane bezpośrednio RAISERROR. Można to również utworzyć jako tymczasową procedurę składowaną, jeśli jest to właściwe.
Oto jak wyglądałaby ta procedura:
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;
Wynik:
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)
Tak więc wynik netto jest taki, że nie masz możliwości formatowania dla liczb zmiennoprzecinkowych (rzuć własne), ale zyskujesz zdolność do ich wyprowadzania (również dziesiętne / numeryczne!), Zachowując jednocześnie zdolność formatowania dla innych typów.