我在SQL Server 2005中有一个非常长时间运行的存储过程,我正在尝试调试,我正在使用'print'命令来执行它。问题是,我只是在我的sproc的最后从SQL Server得到消息-我希望能够在sproc的运行时期间立即刷新消息缓冲区并看到这些消息,而不是在最后。
当前回答
使用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
其他回答
为了扩展Eric Isaac的回答,以下是如何正确使用表格方法:
首先,如果你的sp使用事务,你将无法实时监控表的内容,除非你使用READ UNCOMMITTED选项:
SELECT *
FROM table_log WITH (READUNCOMMITTED);
or
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT *
FROM table_log;
为了解决回滚问题,在日志表中添加一个不断增加的ID,并使用以下代码:
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRANSACTION mytran;
-- already committed logs are not affected by a potential rollback
-- so only save logs created in this transaction
DECLARE @max_log_id = (SELECT MAX(ID) FROM table_log);
/*
* do stuff, log the stuff
*/
COMMIT TRANSACTION mytran;
END TRY
BEGIN CATCH
DECLARE @log_table_saverollback TABLE
(
ID INT,
Msg NVARCHAR(1024),
LogTime DATETIME
);
INSERT INTO @log_table_saverollback(ID, Msg, LogTime)
SELECT ID, Msg, LogTime
FROM table_log
WHERE ID > @max_log_id;
ROLLBACK TRANSACTION mytran; -- this deletes new log entries from the log table
SET IDENTITY_INSERT table_log ON;
INSERT INTO table_log(ID, Msg, LogTime)
SELECT ID, Msg, LogTime
FROM @log_table_saverollback;
SET IDENTITY_INSERT table_log OFF;
END CATCH
注意这些重要的细节:
关闭xact_abort;防止SQL Server只是关闭整个事务,而不是运行你的catch块,如果你使用这种技术,一定要包括它。 使用@table_variable,而不是#temp_table。临时表也会受到回滚的影响。
使用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语句来引起flush。
例如:
PRINT 'MyVariableName: ' + @MyVariableName
RAISERROR(N'', 0, 1) WITH NOWAIT
这种方法的优点是PRINT语句可以连接字符串,而RAISERROR不能。(所以无论哪种方式,你都有相同的代码行数,因为你必须声明和设置一个变量来在RAISERROR中使用)。
如果像我一样,你使用AutoHotKey或SSMSBoost或等效的工具,你可以很容易地设置一个快捷键,如“]flush”,为你进入RAISERROR行。如果每次都是同一行代码,这可以节省时间,也就是说,不需要定制以保存特定的文本或变量。
Another better option is to not depend on PRINT or RAISERROR and just load your "print" statements into a ##Temp table in TempDB or a permanent table in your database which will give you visibility to the data immediately via a SELECT statement from another window. This works the best for me. Using a permanent table then also serves as a log to what happened in the past. The print statements are handy for errors, but using the log table you can also determine the exact point of failure based on the last logged value for that particular execution (assuming you track the overall execution start time in your log table.)
是的……RAISERROR函数的第一个参数需要一个NVARCHAR变量。所以试试下面的方法吧;
-- Replace PRINT function
DECLARE @strMsg NVARCHAR(100)
SELECT @strMsg = 'Here''s your message...'
RAISERROR (@strMsg, 0, 1) WITH NOWAIT
OR
RAISERROR (n'Here''s your message...', 0, 1) WITH NOWAIT
推荐文章
- 在SQL server查询中将NULL替换为0
- 在SQL中修改表的模式名
- 如何得到累计和
- 如何在SQL Server 2005的一条语句中更新两个表?
- 如何创建临时表与SELECT * INTO tempTable从CTE查询
- 在SQL Server的选择语句中使用带TOP的变量,而不是动态的
- SQL变量保存整数列表
- 在SQL中转换月号到月名函数
- 改变一个varchar列的最大长度?
- 如何在SQL中从DateTime格式获取时间?
- 暂时关闭约束(MS SQL)
- WHERE子句中的IF子句
- 如何在SSMS中从ntext或nvarchar(max)查看所有文本?
- 创建表如果在SQL Server中不存在
- MSSQL错误“底层提供者在打开时失败”