我在SQL Server 2005中有一个非常长时间运行的存储过程,正在尝试调试,并且正在使用“ print”命令来进行调试。问题是,我只能在存储过程的最后从SQL Server取回消息-我希望能够刷新消息缓冲区并在存储过程的运行时立即查看这些消息,而不是在运行时结束。
我在SQL Server 2005中有一个非常长时间运行的存储过程,正在尝试调试,并且正在使用“ print”命令来进行调试。问题是,我只能在存储过程的最后从SQL Server取回消息-我希望能够刷新消息缓冲区并在存储过程的运行时立即查看这些消息,而不是在运行时结束。
Answers:
使用RAISERROR
功能:
RAISERROR( 'This message will show up right away...',0,1) WITH NOWAIT
您不应该将所有打印完全替换为raiserror。如果某个地方有循环或大游标,则每个迭代一次或两次,甚至每几个迭代一次。
另外:我首先在此链接上了解了RAISERROR,现在我将其视为SQL Server错误处理的权威资料,绝对值得一读:http :
//www.sommarskog.se/error-handling-I.html
在@JoelCoehoorn回答的基础上,我的方法是将所有PRINT语句保留在原位,并在它们后面加上RAISERROR语句以引起刷新。
例如:
PRINT 'MyVariableName: ' + @MyVariableName
RAISERROR(N'', 0, 1) WITH NOWAIT
这种方法的优点是PRINT语句可以连接字符串,而RAISERROR不能。(因此,无论哪种方式,您都有相同数量的代码行,因为您必须声明并设置要在RAISERROR中使用的变量)。
如果像我一样使用AutoHotKey或SSMSBoost或等效工具,则可以轻松设置快捷方式,例如“] flush”,为您输入RAISERROR行。如果每次都是同一行代码,则可以节省您的时间,即不需要自定义以容纳特定的文本或变量。
RAISERROR()
它确实支持printf()
-style字符串插值。例如,如果@MyVariableName
是一个stringish类型(例如,VARCHAR(MAX)
,NVARCHAR(MAX)
等等),可以使用RAISERROR()
与一个行:RAISERROR(N'MyVariableName: %s', 0, 1, @MyVariableName)
。
是的... RAISERROR函数的第一个参数需要一个NVARCHAR变量。因此,请尝试以下操作;
-- Replace PRINT function
DECLARE @strMsg NVARCHAR(100)
SELECT @strMsg = 'Here''s your message...'
RAISERROR (@strMsg, 0, 1) WITH NOWAIT
要么
RAISERROR (n'Here''s your message...', 0, 1) WITH NOWAIT
另一个更好的选择是不依赖PRINT或RAISERROR,而只是将您的“ print”语句加载到TempDB中的## Temp表或数据库中的永久表中,这将使您可以立即通过另一个窗口中的SELECT语句查看数据。这对我来说是最好的。然后,使用永久表还可以作为过去发生的情况的日志。打印语句很容易出错,但是使用日志表,您还可以基于特定执行的最后一个记录值来确定确切的故障点(假设您在日志表中跟踪总体执行开始时间)。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
在监视会话中使用它实时查询它
READ UNCOMMITTED
事务中的数据复制到另一个表,但是您可能会错过之前的时刻ROLLBACK
。因此它可能解决了“多远?” 不是“为什么回滚?”
仅供参考,如果您使用脚本(批处理),而不是存储过程,则GO命令触发刷新输出,例如
print 'test'
print 'test'
go
总的来说,我的结论如下:在SMS GUI或sqlcmd.exe中执行的mssql脚本执行输出,将刷新到第一个GO语句上的文件,stdoutput,gui窗口,或者直到脚本结束。
由于无法将GO放入内部,因此刷新存储过程内部的功能有所不同。
参考:tsql Go语句
go
不仅刷新输出,还按照您提供的链接结束批处理。您的所有内容都会declare
被丢弃,因此调试时不太有用。declare @test int print "I want to read this!" go set @test=5
尽管您会声称错误声明@test
是未定义的,因为它在新批次中。