在写存储过程时,调试程序经常用PRINT或Table记录log,Table在事务提交在相对复杂,PRINT在查询分析器中有效,后端程序调用无法看到效果,针对此问题想到利用xp_cmdshell写Debug Log,以下代码供参考。
Create PROC P_FILEOUTPUT
( @PROC_NAME sysname,
@CODE sysname,
@EMS sysname,
@RET_MESSAGE VARCHAR(MAX) OUTPUT
)
AS
create table #t_output
(cmd varchar(100))
DECLARE @cmd varchar(4048),
@db_name sysname,
@path sysname,
@fileName sysname,
@spid sysname ,
@loginame varchar(10) ,
@hostname varchar(10),
@program_name varchar(60) ,
@cmd_txt varchar(1024)
SET @db_name=DB_NAME()
SET @path='d:\log\'+@db_name+'\'
SET @fileName=@path+ISNULL(@PROC_NAME,'')+'_'+cast(@@SPID as varchar(20))+'.txt'
--如果文件夹不存在,需要建立
SET @cmd = 'if not exist '+@path+' md '+@path
INSERT INTO #t_output
EXEC master..xp_cmdshell @cmd
--抓取进程记录
SELECT @spid = spid ,
@loginame= loginame ,
@hostname= hostname ,
@program_name= program_name ,
@cmd_txt=cmd
FROM sys.sysprocesses
WHERE spid = @@SPID
--如果该文件不存在,输入进程信息。便于查问题
SET @cmd = 'if not exist '+@fileName+' '
SET @cmd =@cmd+ '('+' '
--SET @cmd =@cmd+'@echo off '
SET @cmd =@cmd+ 'echo "%date%'+' '+'%time%" >>'+@fileName+' '+char(13)
SET @cmd =@cmd+' '+ '"进程ID |登录名 |主机名 |程序名 |命令" >>'+@fileName+' '
SET @cmd =@cmd+' "'+ ISNULL(@spid,'')+'|' + ISNULL(@loginame,'')+'|' + ISNULL(@hostname,'')+'|' + ISNULL(@program_name,'')+' |'+ ISNULL(@cmd_txt,'') +'" >>'+@fileName+' '
SET @cmd =@cmd+') '
--print @cmd
INSERT INTO #t_output
EXEC master..xp_cmdshell @cmd
--分隔符
IF @CODE='*'
BEGIN
SET @cmd = 'echo "'+isnull(@EMS,'')+'" >>'+@fileName+' '
-- print @cmd
INSERT INTO #t_output
EXEC master..xp_cmdshell @cmd
END
ELSE
BEGIN
--Log文件输出
SET @cmd = 'echo "%date%'+' '+'%time%" >>'+@fileName+' '
SET @cmd =@cmd+' "错误代码 |错误内容" >>'+@fileName+' '
INSERT INTO #t_output
EXEC master..xp_cmdshell @cmd
SET @cmd = 'echo "'+ISNULL(@CODE,'')+' |'+isnull(@EMS,'')+'" >>'+@fileName+' '
---print @cmd
INSERT INTO #t_output
EXEC master..xp_cmdshell @cmd
END
select @RET_MESSAGE=isnull(@RET_MESSAGE,'')+ cmd
from #t_output where cmd is not null
--SELECT * FROM #t_output
测试语句
declare @RET_MESSAGE VARCHAR(MAX)
exec P_FILEOUTPUT '程序名-自定义' , '1' , 'hu' , @RET_MESSAGE OUTPUT
SELECT @RET_MESSAGE
结果存在SET @path='d:\log\'+@db_name+'\' 相应的数据库下,文件名是参数@PROC_NAME+进程
文本内容:第一行为进程相关信息,可以根据自行需要调整【格式尝试多种方式未调整完善】
第二行为错误信息
分隔符使用
在调整程序便于区分每段错误,经常使用分隔符,@CODE为*,@EMS为分隔符
declare @RET_MESSAGE VARCHAR(MAX)
exec P_FILEOUTPUT '程序名-自定义' , '*' , '------------------------测试案例--------------------------------' , @RET_MESSAGE OUTPUT
SELECT @RET_MESSAGE
再次运行下面语句
declare @RET_MESSAGE VARCHAR(MAX)
exec P_FILEOUTPUT '程序名-自定义' , '1' , '测试效果2' , @RET_MESSAGE OUTPUT
SELECT @RET_MESSAGE
xp_cmdshell
exec sp_configure 'xp_cmdshell';
#查看系统实例中是否有xp_cmdshell存储过程;
如果返回结果中的"run_value"为1,则表示xp_cmdshell已经启用;
如果为0,则表示xp_cmdshell尚未启用。
xp_cmdshell
-- 允许修改高级参数
exec sp_configure 'show advanced options',1;
-- 配置生效
RECONFIGURE;
-- 开启xp_cmdshell
exec sp_configure 'xp_cmdshell',1;
-- 配置生效
RECONFIGURE;
xp_cmdshell
-- 开启高级选项
exec sp_configure 'show advanced options',1;
-- 配置生效
RECONFIGURE;
-- 关闭xp_cmdshell
exec sp_configure 'xp_cmdshell',0;
-- 配置生效
RECONFIGURE;
xp_cmdshell
存储过程select * from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell';
xp_cmdshell
xplog70.dll
exec master..xp_dropextendedproc xp_cmdshell,@dllname='xplog70.dll'
xplog70.dll
exec master.dbo.sp_addextendedproc xp_cmdshell,@dllname='具体路径\xplog70.dll'
xp_cmdshell
exec master..sp_dropextendedproc xp_cmdshell;
官方说明:xp_cmdshell (Transact-SQL) - SQL Server | Microsoft Learn