我正在使用RAISERROR()提供一些基本的单元测试功能(如这里),但我对无法FLOATs在错误消息中使用感到沮丧。我知道我可以将浮点数转换为字符串,但我RAISERROR在每个单元测试中都使用,我不想为每个测试添加另一行代码。(我的单元测试已经够啰嗦了!)有没有办法在参数列表中执行内联强制转换/转换RAISERROR?或者有其他方法可以解决这个缺陷吗?
更新: 所以最终我希望我能做的是:
RAISERROR('Unit Test FAILED! %f', 11, 0, @floatParm)
Run Code Online (Sandbox Code Playgroud)
不幸的是,RAISERROR一般不处理 %f 或浮点数。所以我必须这样做:
DECLARE @str VARCHAR(40) = CAST(@floatParm AS VARCHAR(40))
RAISERROR('Unit Test FAILED! %s', 11, 0, @str)
Run Code Online (Sandbox Code Playgroud)
...当它分散在数十个单元测试中时,它看起来就像一团糟。所以我想把它归结为这样的:
RAISERROR('Unit Test FAILED! %s', 11, 0, CAST(@floatParm AS VARCHAR(40))
Run Code Online (Sandbox Code Playgroud)
但这给了我一个Incorrect syntax near 'CAST'信息。我不明白为什么这是非法的,但确实如此。我可以在这里使用另一个“一个班轮”吗?
Jon*_*gel 12
不幸的是,无论出于何种原因,您都无法在该上下文中进行内联转换,并且无论出于何种原因,RAISERROR也不直接支持float。
为了这个答案的完整性,这里是来自MSDN的相关片段,我相信你已经看到了(注意:它在 2005 年到 2012 年的所有版本的文档中都是相同的文本):
每个替换参数可以是局部变量或以下任何数据类型:tinyint、smallint、int、char、varchar、nchar、nvarchar、binary或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
Run Code Online (Sandbox Code Playgroud)
可悲的是,没有简单的方法可以针对任意数量的参数进行缩放……这可能可以使用复杂的嵌套动态 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;
Run Code Online (Sandbox Code Playgroud)
输出:
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)
Run Code Online (Sandbox Code Playgroud)
所以最终的结果是你没有获得浮点数的格式化能力(自己动手),但你确实获得了输出它们的能力(十进制/数字,太!)同时保留其他类型的格式化能力。
| 归档时间: |
|
| 查看次数: |
6837 次 |
| 最近记录: |