К сожалению, по какой-то причине вы не можете выполнить встроенное преобразование в этом контексте и RAISERRORне поддерживает напрямую float, опять же, по любой причине.
Для полноты этого ответа вот соответствующий фрагмент из MSDN , который, я уверен, вы уже видели (примечание: это один и тот же текст во всех версиях документации с 2005 по 2012 годы):
Каждый параметр подстановки может быть локальной переменной или любым из этих типов данных: tinyint , smallint , int , char , varchar , nchar , nvarchar , двоичный или 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)
Таким образом, общий результат заключается в том, что вы не получаете возможность форматирования для чисел с плавающей запятой (сверните свое собственное), но вы получаете возможность выводить их (также десятичную / числовую!), Сохраняя возможность форматирования для других типов.