【问题标题】:SQL Server printfSQL Server 打印文件
【发布时间】:2011-07-05 15:51:51
【问题描述】:

Sql Server 中有类似 printf 的函数吗?我想要与 RAISERROR 函数相同的功能,但我不想抛出错误或打印消息,而是想将其写入 varchar,因为我的 ERP 不允许我处理错误消息.

这是 SQL Server 2000。

RAISERROR 的实际工作示例:

declare @name varchar(10)
set @name = 'George'

RAISERROR ('Hello %s.', 10, 1, 'George')

打印Hello George

我在寻找什么:

declare @name varchar(10), @message varchar(50)
set @name = 'George'

SET @message = printf('Hello %s.', 'George')
return @message

这将返回Hello George

【问题讨论】:

  • 大多数工具不会将RAISERROR 返回的严重程度为 10 或更低的消息视为实际错误 - 你的呢?
  • 不,它没有,但它仍然不会让我处理消息,即把它放入一个变量中而不是显示给用户。
  • 您是否测试过它允许您访问PRINT 消息?如果是这样,严重性为 0 的RAISERROR 应该是相同的 AFAIK。根据 erland sommarskog PRINT is just a shortcut for RAISERROR with level 0.
  • 我不想打印它。我想将它的值写入一个变量。我将编辑问题以使其更清楚。

标签: sql-server sql-server-2000


【解决方案1】:

PRINT 只是RAISERROR,严重性为 0。所以你可以使用。

declare @name varchar(10)
set @name = 'George'

RAISERROR ('Hello %s.', 0, 1, 'George') WITH NOWAIT

编辑以将其存储到一个变量中,您可以使用xp_sprintf 扩展存储过程。

declare @name varchar(10)
set @name = 'George'

DECLARE @ret varchar(500)
exec master..xp_sprintf @ret OUTPUT, 'Hello %s.', @name
PRINT @ret

【讨论】:

  • 我不知道xp_sprintf,它几乎满足了我的需求,除了Currently, only the %s format argument is supported。无赖
【解决方案2】:

如果您的格式字符串数量有限,并且能够将它们添加到系统消息中(通过sp_addmessage),您可以使用FORMATMESSAGE

与 RAISERROR 语句一样,FORMATMESSAGE 通过用提供的参数值替换消息中的占位符变量来编辑消息。有关错误消息中允许的占位符和编辑过程的更多信息,请参阅 RAISERROR。


以下将是 SQL Server 2005 或更高版本的有效答案,但不幸的是,OP 正在为 SQL Server 2000 寻求解决方案:


这很丑陋,而且是对 Try/Catch 和 RAISERROR 的滥用:

declare @message varchar(50)

begin try
    RAISERROR('Hello %s',16,1,'george')
end try
begin catch
    set @message = ERROR_MESSAGE()
end catch

print @message

【讨论】:

  • IIRC,在 Sql Server 2005 中引入了 try catch。但那会很棒。
  • @DonkeyMaster - 你是对的,对不起。我认为没有办法拦截 2000 年的错误消息,RAISERROR 是我所知道的 SQL Server 中唯一具有这些 printf 样式格式选项的函数。
  • @DonkeyMaster - 我想我找到了最适合 2000 年的版本,但它确实需要更改服务器的状态,因此只有在所需的格式字符串数量很小且固定的情况下才有效。
  • @Damien - xp_sprintf 在 2000 年 AFAIK 上完成这项工作。
  • @Martin - 但这仅支持 (%s) 字符串参数,而不是更全面的 RAISERROR/FORMATMESSAGE 替换。
【解决方案3】:

自 SQL Server 2016 起formatmessageraiserror 已得到扩展,使它们几乎可以像 C 的 printf 函数一样工作。第一个参数(以前必须是引用 sys.messages 中预定义消息的整数)现在可以是 printf 样式的格式字符串:

select formatmessage(
    'This is a string %s and this is an integer %i%sand this is a string weirdly padded with spaces <<%7.3s>>%sand this is a hex representation of an integer %x',
    'foo',
    42,
    char(13) + char(10),
    'bar',
    char(13) + char(10),
    1337
);

/* output:
This is a string foo and this is an integer 42
and this is a string weirdly padded with spaces <<    bar>>
and this is a hex representation of an integer 539
*/

虽然throwdoes not implicitly support this same formatting,但没有什么能阻止你using formatmessage together with this construct

declare @errorMessage nvarchar(max) = formatmessage(
    'This is a string %s and this is an integer %i%sand this is a string weirdly padded with spaces <<%7.3s>>%sand this is a hex representation of an integer %x',
    'foo',
    42,
    char(13) + char(10),
    'bar',
    char(13) + char(10),
    1337
);

throw 50000, @errorMessage, 1;

/* output:
Msg 50000, Level 16, State 1, Line 21
This is a string foo and this is an integer 42
and this is a string weirdly padded with spaces <<    bar>>
and this is a hex representation of an integer 539
*/

【讨论】:

    【解决方案4】:

    这是一个使用 sql_variant 数据类型的简单 printf 过程。不幸的是,它仅适用于 SQL Server 2008 及更高版本。

    CREATE PROCEDURE dbo.printf
      @string nvarchar(max),
      @p1 sql_variant = null,
      @p2 sql_variant = null,
      @p3 sql_variant = null
    AS
    BEGIN
      declare @str nvarchar(200), @pos int, @type char(1)
      select @str = @string, @pos = 0
    
      --- @p1
      set @pos = CHARINDEX('%', @str, @pos)
      if @pos > 0 and substring(@str, @pos, 2) = '%%'
        set @str = stuff(@str, @pos, 2, coalesce(cast(@p1 as nvarchar(100)),'<null>')) 
    
      --- @p2
      set @pos = CHARINDEX('%', @str, @pos)
      if @pos > 0 and substring(@str, @pos, 2) = '%%'
        set @str = stuff(@str, @pos, 2, coalesce(cast(@p2 as nvarchar(100)),'<null>')) 
    
      --- @p3
      set @pos = CHARINDEX('%', @str, @pos)
      if @pos > 0 and substring(@str, @pos, 2) = '%%'
        set @str = stuff(@str, @pos, 2, coalesce(cast(@p3 as nvarchar(100)),'<null>')) 
    
      print @str
    END
    

    这里是示例调用:

    exec dbo.printf 'Hello %%', 'World'
    exec dbo.printf 'Hello %%. Today is %% of the month', 'World', 28
    declare @dd datetime; set @dd = getDate()
    exec dbo.printf 'Hello %%. Today''s date is %%', 'World', @dd
    

    【讨论】:

      【解决方案5】:

      如果您希望在变量中存储一些消息,那么 SET 应该足以让您处理吧?除非我不清楚这个问题。

      SET @varcharVariable = 'message text';
      

      【讨论】:

      • 我应该包括一个例子。那不是我的问题。
      • @DonkeyMaster - 你现在仍然可以在你的问题中包含这个例子;)
      猜你喜欢
      • 2016-11-18
      • 2010-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多