Desafortunadamente, por cualquier razón, no puede hacer una conversión en línea en ese contexto, y RAISERRORno admite directamente float, de nuevo, por cualquier razón.
Para completar esta respuesta, aquí está el fragmento relevante de MSDN , que estoy seguro de que ya has visto (nota: es el mismo texto en todas las versiones de la documentación de 2005 a 2012):
Cada parámetro de sustitución puede ser una variable local o cualquiera de estos tipos de datos: tinyint , smallint , int , char , varchar , nchar , nvarchar , binary o varbinary .
La única solución razonable que se me ocurre sería escribir un procedimiento almacenado para finalizar la RAISERRORllamada. Aquí hay un punto de partida:
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
Lamentablemente, no hay una manera fácil de escalar esto para un número arbitrario de parámetros ... Probablemente podría hacerse usando SQL dinámico anidado enrevesado, lo que sería divertido de depurar. Lo dejaré como ejercicio para el lector.
He utilizado sql_varianten el supuesto de que, por razones de uniformidad de código, el mismo procedimiento se utiliza en todas partes, incluso para los tipos de valores que están soportados directamente por RAISERROR. Además, esto podría crearse como un procedimiento almacenado temporal si es apropiado.
Así es como se vería este procedimiento:
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;
Salida:
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)
Por lo tanto, el resultado neto es que no obtienes la capacidad de formateo de flotantes (tira la tuya propia), pero sí obtienes la capacidad de generarlos (¡decimal / numérico también!) Mientras conservas la capacidad de formateo para los otros tipos.