关于SQL Server触发器的奇怪问题,高手请进。

leither 2017-11-30 10:07:24
请见下表
create database student_score
GO
--在数据库中创建学生表
use student_score
GO
create table student
( stu_id char(8) primary key,
stu_name char(10),
stu_sex char(2),
stu_birthday smalldatetime,
class_id char(6)
age int
)
go


为该表建立触发器,监视数据插入:
ALTER trigger [dbo].[stu_insert]
on [dbo].[student]
for insert
as
declare @ID int
select @ID from inserted
exec PROC_INSERT_DATA_DETAIL @ID

触发器通过存储过程 PROC_INSERT_DATA_DETAIL 调用外部程序
存储过程如下:

ALTER PROCEDURE [dbo].[PROC_INSERT_DATA_DETAIL](@InsertID int)
AS
BEGIN
declare @ProcessPath varchar(128)
set @ProcessPath='E:\SVN.NET\Createlog\Debug\Createlog.exe '+ CONVERT(varchar(16),@InsertID)
select @ProcessPath
declare @SQL nvarchar(256)
set @SQL='master.sys.xp_cmdshell ' +'''' + @ProcessPath +''''
insert into dbo.log values(@SQL)
EXEC(@SQL)
END


存储过程调用测试代码:

DECLARE @ID INT
SET @ID = 17
exec PROC_INSERT_DATA_DETAIL @ID

但上述代码调用存储过程时,可以调用外部程序,并且日志中也记录到生成的SQL语句。在触发器调用PROC_INSERT_DATA_DETAIL时外部程序却总是调用不成功,查看日志时显示插入内容为NULL。
...全文
220 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
leither 2017-12-01
  • 打赏
  • 举报
回复
问题补充

ALTER PROCEDURE [dbo].[PROC_INSERT_DATA_DETAIL](@InsertID int)
    AS
    BEGIN
		declare @ProcessPath varchar(128)
		set @ProcessPath='E:\SVN.NET\Createlog\Debug\Createlog.exe '+ CONVERT(varchar(16),@InsertID)
		select @ProcessPath 
		declare @SQL varchar(256)
		--这条可以插入
		--set @SQL='master.sys.xp_cmdshell '  
		--这条不能插入
		--set @SQL='master.sys.xp_cmdshell ' +'''' + @ProcessPath +'''' 
		--这条也不能插入
		--Set @SQL=@ProcessPath	
		insert into dbo.logT1 (logText,InsertTime) values(CONVERT(varchar(16),@InsertID),GETDATE())
		insert into dbo.logT1 (logText,InsertTime) values(@SQL,GETDATE())
		--EXEC(@SQL)
    END
吉普赛的歌 2017-12-01
  • 打赏
  • 举报
回复
引用 4 楼 leither 的回复:
[quote=引用 2 楼 yenange 的回复:] 想得到数据变动信息, 用SQL Server自带的CDC就好, 没必要自己写的了: http://blog.csdn.net/yenange/article/details/49636215
拜读过你的文章了,但我还没能搞明白,CDC如何通知应用程序去读取指定的记录![/quote] 增加一个作业, 定时(比如每10秒)读取 cdc 的表, 如有新的插入记录,做相应的处理就好了。 触发器直接调应用程序, 看起来简单而且直接, 但出错会导致数据无法插入, 也影响了数据的插入效率。 如果要在大数据量插入的情况下用必然堵塞, 不乐观。 另外也可以用SqlDependcy来感知数据的变化作相应的处理: https://www.cnblogs.com/yjmyzz/archive/2009/06/14/1502921.html
leither 2017-12-01
  • 打赏
  • 举报
回复
引用 5 楼 ayalicer 的回复:
[quote=引用 1 楼 sinat_28984567 的回复:]
select @ID from inserted
这句有问题,@ID没有赋值; 如果是每次插入一条,可以试试这样
select @ID=stu_id from inserted
如果是批量插入,得用别的方法
批量就拼接成 一批 exec PROC_INSERT_DATA_DETAIL @ID;[/quote] 按你这样改的话,能拿到ID,但仍然不能调用外部程序,日志记录也还是NULL
  • 打赏
  • 举报
回复
引用 1 楼 sinat_28984567 的回复:
select @ID from inserted
这句有问题,@ID没有赋值; 如果是每次插入一条,可以试试这样
select @ID=stu_id from inserted
如果是批量插入,得用别的方法
批量就拼接成 一批 exec PROC_INSERT_DATA_DETAIL @ID;
leither 2017-12-01
  • 打赏
  • 举报
回复
引用 2 楼 yenange 的回复:
想得到数据变动信息, 用SQL Server自带的CDC就好, 没必要自己写的了: http://blog.csdn.net/yenange/article/details/49636215
拜读过你的文章了,但我还没能搞明白,CDC如何通知应用程序去读取指定的记录!
leither 2017-12-01
  • 打赏
  • 举报
回复
引用 1 楼 sinat_28984567 的回复:
select @ID from inserted
这句有问题,@ID没有赋值; 如果是每次插入一条,可以试试这样
select @ID=stu_id from inserted
如果是批量插入,得用别的方法
按你这样改的话,能拿到ID,但仍然不能调用外部程序,日志记录也还是NULL
吉普赛的歌 2017-12-01
  • 打赏
  • 举报
回复
想得到数据变动信息, 用SQL Server自带的CDC就好, 没必要自己写的了: http://blog.csdn.net/yenange/article/details/49636215
二月十六 2017-12-01
  • 打赏
  • 举报
回复
select @ID from inserted
这句有问题,@ID没有赋值; 如果是每次插入一条,可以试试这样
select @ID=stu_id from inserted
如果是批量插入,得用别的方法
leither 2017-12-01
  • 打赏
  • 举报
回复
问题已经解决,字符拼接有问题,谢谢大家!

declare @InsertID int
select @InsertID = age  from inserted

declare @ProcessPath varchar(256)
set @ProcessPath='master.sys.xp_cmdshell ''E:\SVN.NET\Createlog\Debug\Createlog.exe '+ CONVERT(varchar(16),@InsertID)+''''
insert into dbo.logT1 (logText,InsertTime) values(@ProcessPath,GETDATE())
EXEC(@ProcessPath)

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧