不能。formatmessage 不查 sys.messages,仅按格式字符串替换占位符;需先查 sys.messages 获取 message_text,再传入 formatmessage,并严格匹配占位符类型与数量。

FORMATMESSAGE 能不能直接用错误号生成消息?
不能。SQL Server 的 FORMATMESSAGE 不接收错误号(如 50000)作为参数去自动查系统错误表,它只负责按格式字符串替换占位符,类似 C 的 sprintf。你看到的“错误号对应消息”其实是 RAISERROR 或 THROW 在抛出时才查 sys.messages;FORMATMESSAGE 本身不查表、不依赖错误号。
想动态拼通知内容,得先从 sys.messages 查原始消息
如果你要基于错误号(比如自定义错误 50001)生成带变量的提示语,必须手动查 sys.messages 拿出 message_text,再喂给 FORMATMESSAGE。注意三点:
-
sys.messages中的message_text含有%d、%s等 C 风格占位符,不是 T-SQL 的{0}格式 - 必须指定语言 ID(
language_id = 1033表示英语,中文是2052),否则可能查不到或返回空 - 自定义错误需先用
sp_addmessage注册过,否则不在sys.messages里
示例:查错误号 50001 的英文消息并填充用户名
DECLARE @msg NVARCHAR(2048); SELECT @msg = message_text FROM sys.messages WHERE message_id = 50001 AND language_id = 1033; <p>SELECT FORMATMESSAGE(@msg, N'张三'); -- 假设原消息是 'User %s login failed.'</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/ai/1049" title="Voicemaker"><img src="https://img.php.cn/upload/ai_manual/001/503/042/68b6cb53d5359546.png" alt="Voicemaker" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/ai/1049" title="Voicemaker" class="overflowclass">Voicemaker</a> <p class="overflowclass">Voicemaker是一款提供多语言文本转语音和 SSML 控制的在线 AI 语音生成工具。</p> </div> <a rel="nofollow" href="/ai/1049" title="Voicemaker" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
FORMATMESSAGE 参数顺序和类型必须严格匹配占位符
传参顺序错一位、类型不兼容(比如用 INT 填 %s),就会报错 Msg 1001, Level 15 或返回 NULL。常见坑:
-
%d/%i只接受整数(INT,BIGINT),传VARCHAR会失败 -
%s接字符串,但若传NULL,整个结果变NULL(不会转成空串) - 占位符数量和后续参数数量必须相等,多一个少一个都报错
- SQL Server 2019+ 支持
FORMATMESSAGE(N'Hello {0}', N'World')这种 .NET 风格,但仅限于字符串字面量,不支持变量传入格式串
生产环境发通知,别只靠 FORMATMESSAGE 拼字符串
单纯拼接容易漏上下文,比如没包含时间、SPID、数据库名。更稳妥的做法是把 FORMATMESSAGE 当作模板引擎的一环,配合其他元数据组装:
- 用
GETDATE()+@@SPID+DB_NAME()补充运行时信息 - 对用户输入做
REPLACE(..., '''', '''''')防 SQL 注入(如果模板来自不可信来源) - 加
TRY...CATCH捕获FORMATMESSAGE自身失败(如参数类型错),避免通知逻辑中断
真正难的不是拼字符串,而是确保每次取到的消息文本和当前语言、版本、注册状态一致——尤其跨服务器迁移后,sp_addmessage 很容易被遗漏。










