Sql server 带有百分号(%)的抛出会产生奇怪的错误消息
在SSMS1中执行以下T-SQL语句会给出一条错误消息,其中正好包含一个空格2: 但是,如果通过将%加倍来转义,则会收到预期的错误消息:Sql server 带有百分号(%)的抛出会产生奇怪的错误消息,sql-server,tsql,throw,Sql Server,Tsql,Throw,在SSMS1中执行以下T-SQL语句会给出一条错误消息,其中正好包含一个空格2: 但是,如果通过将%加倍来转义,则会收到预期的错误消息: THROW 50000, 'abc%%de', 0; Msg 50000, Level 16, State 0, Line 1 abc%de 我还注意到,当%后跟空格时,它只是被跳过: THROW 50000, 'abc% de', 0; Msg 50000, Level 16, State 0, Line 1 abc de 出于某种原因,THROW以
THROW 50000, 'abc%%de', 0;
Msg 50000, Level 16, State 0, Line 1
abc%de
我还注意到,当%后跟空格时,它只是被跳过:
THROW 50000, 'abc% de', 0;
Msg 50000, Level 16, State 0, Line 1
abc de
出于某种原因,THROW以一种特殊的方式解释了%
1我也尝试过ADO.NET,效果相当
2这里看不清楚,但我仔细检查了一下:错误消息确实不是空字符串,而是一个空格。抛出状态的文档:
DECLARE @errors TABLE(CharNumber INT, CharValue CHAR(1), ErrorText NVARCHAR(4000));
DECLARE @i INT = 0;
WHILE (@i <= 255)
BEGIN
DECLARE @c CHAR(1) = CHAR(@i);
DECLARE @m VARCHAR(50) = 'abc%' + @c + 'de';
BEGIN TRY
THROW 50000, @m, 0;
END TRY
BEGIN CATCH
INSERT INTO @errors
SELECT @i, @c, ERROR_MESSAGE();
END CATCH
SET @i = @i + 1;
END
SELECT * FROM @errors WHERE ErrorText > '' ORDER BY CharNumber
CharNumber CharValue ErrorText
32 abc de
33 ! abc!de
37 % abc%de
46 . abc.de
48 0 abcde
110 n abc
nde --<- This adds a new line.
消息参数不接受printf样式的格式
这应该可以解释为什么它无法打印文本
RAISERROR文档(msg_str)中有关于SQL Server中printf样式格式化的更多信息:
这将测试0-255之间的字符,以检查它们是否返回某些内容:
DECLARE @errors TABLE(CharNumber INT, CharValue CHAR(1), ErrorText NVARCHAR(4000));
DECLARE @i INT = 0;
WHILE (@i <= 255)
BEGIN
DECLARE @c CHAR(1) = CHAR(@i);
DECLARE @m VARCHAR(50) = 'abc%' + @c + 'de';
BEGIN TRY
THROW 50000, @m, 0;
END TRY
BEGIN CATCH
INSERT INTO @errors
SELECT @i, @c, ERROR_MESSAGE();
END CATCH
SET @i = @i + 1;
END
SELECT * FROM @errors WHERE ErrorText > '' ORDER BY CharNumber
CharNumber CharValue ErrorText
32 abc de
33 ! abc!de
37 % abc%de
46 . abc.de
48 0 abcde
110 n abc
nde --<- This adds a new line.
DECLARE@errors表(CharNumber INT,CharValue CHAR(1),ErrorText NVARCHAR(4000));
声明@i INT=0;
WHILE(@i''按字符编号排序
输出:
DECLARE @errors TABLE(CharNumber INT, CharValue CHAR(1), ErrorText NVARCHAR(4000));
DECLARE @i INT = 0;
WHILE (@i <= 255)
BEGIN
DECLARE @c CHAR(1) = CHAR(@i);
DECLARE @m VARCHAR(50) = 'abc%' + @c + 'de';
BEGIN TRY
THROW 50000, @m, 0;
END TRY
BEGIN CATCH
INSERT INTO @errors
SELECT @i, @c, ERROR_MESSAGE();
END CATCH
SET @i = @i + 1;
END
SELECT * FROM @errors WHERE ErrorText > '' ORDER BY CharNumber
CharNumber CharValue ErrorText
32 abc de
33 ! abc!de
37 % abc%de
46 . abc.de
48 0 abcde
110 n abc
nde --<- This adds a new line.
CharNumber CharValue ErrorText
32 abc de
33!abc!de
37%abc%de
46.abc.de
48 0 abcde
110N美国广播公司
nde——这个答案可能很有趣:我猜它要么连接到formatmessage函数,要么是引入throw时raiserror遗留下来的东西。它看起来不像是故意的行为。@JodyT:但这没有真正意义,不是吗?它应该是formatmessage函数(在此上下文中未调用)执行(可能错误)那么,替换。其他一些有趣的尝试是%r
和%n
。我有一篇关于这一点的博文,写了一半;感谢完成的动机。我完成后会发布一个链接。-仍在等待我在Microsoft的联系人提供一些见解,了解THROW在幕后到底做了什么。我听说了d从Microsoft返回,并更新了我的博客文章。从本质上说,这是由带有RAISERROR的部分共享代码路径引起的,您应该习惯这种行为。他们不会修复它,但他们已同意在抛出文档中添加注释,以指示%字符存在问题。是的,我知道“不接受printf样式的格式”,那么为什么它会在流行之后“接受”它呢?好吧,这一定是微软有意识地做出的设计选择。因为他们在文档中清楚地说明了“prinf格式”不接受。这可能是因为他们希望我们以不同的方式使用它,也可能是SQL Server的内部技术难题。但是,由于他们不接受它,他们必须清空消息(或抛出另一个错误,这可能会让人困惑)。如果他们写了“不支持”我原以为它会打印您的邮件。%%works之所以有效,是因为您告诉函数不使用“printf格式”,这应该被接受。那么为什么abc%de
会产生abc de
?更一般地说:“不接受”可能意味着“忽略”或“错误”显然,THROW不会忽略它,有时返回一个空格字符串,有时返回另一个字符串来报告错误是一个非常奇怪的“设计选择”事实上,与使用NULL或空字符串或类似于指定的无效消息的内容相比,这似乎是一个错误。呵呵,您确实有一些优点。我们可能不得不将“不接受”解释为“如果您使用它,它可能会以某种方式失败”:我测试了0-255之间的所有字符,发现有六个字符不会返回空白:32(空格),33(!),37(%),46(.),48(0),110(n)。我将更新我的答案。