sqlserver数据库中某个表写了一个触发器:
USE [MNRYMAS] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER TRIGGER [dbo].[tritest] ON [dbo].[Equip_LAirCompressor] after insert AS BEGIN declare @newID varchar(50),@Result varchar(100) select @newID=ID from inserted set @Result = 'D:\Debug\Test_GetData.exe "'+@newID+'"' EXEC master..xp_cmdshell @Result SET NOCOUNT ON; END
该触发器是数据库添加数据时调用一个外部的exe(控制台应用程序)。传入参数就是当前插入数据的id。控制台应用程序根绝这个id去查询这条插入的数据进行操作。
具体得查询方式如下:
if (args.Count() <= 0) { return; } //string ID = "151055"; string ID = args[0]; using (SqlConnection conn = new SqlConnection(sql_local)) { string str_sql = "select * from [MNRYMAS].[dbo].[Equip_LAirCompressor] where ID = '" + ID + "'";using (SqlCommand cmd = new SqlCommand(str_sql, conn)) { conn.Open(); //cmd.CommandTimeout = int.MaxValue; SqlDataReader read = cmd.ExecuteReader(); while (read.Read()) { double OldRoomPressure = read["OldRoomPressure"] == null ? 0 : double.Parse(read["OldRoomPressure"].ToString()); double NewRoomPressure = read["NewRoomPressure"] == null ? 0 : double.Parse(read["NewRoomPressure"].ToString()); double CoolingWaterTemp = read["CoolingWaterTemp"] == null ? 0 : double.Parse(read["CoolingWaterTemp"].ToString()); double IsWarning = read["IsWarning"] == null ? 0 : double.Parse(read["IsWarning"].ToString()); string CreateTime = read["CreateTime"].ToString(); //其他操作 } } }
但是,当把ID当参数传入应用程序时,直接到
SqlDataReader read = cmd.ExecuteReader(); 这句就会报错,错误:Timeout expired.
如果按照上面ID的注释方式传入(
string ID = "151055";),直接在程序中吧参数写入进行测试的话,就没有问题。
崩溃了,就是一个是传入的,一个是写死的,传入就不行呢?
参数是可以传进去的。
Console.WriteLine(ID)
打印一下传入的 ID 值看是否有问题
看了,没有问题。到sql语句都是没有问题得。就是到了cmd.ExecuteReader();这一句就报错了。
很是纳闷,搞了快一天了。
我把ID输出了,也把Sql语句输出来看了,都是正常的。可是执行查询的时候就不行了。
这是我记录下来的日志。参数穿进去了,这样看sql语句也是没错的。执行不了查询。。。
@1sa2sa: 上面的代码看着不舒服,而且有2个问题:1)后SQL注入漏洞;2)SqlDataReader没有关闭,稍微修改了一下
using (SqlConnection conn = new SqlConnection(sql_local))
{
string str_sql = "select * from [MNRYMAS].[dbo].[Equip_LAirCompressor] where ID=@ID";
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = str_sql;
cmd.Parameters.AddWithValue("@ID", ID);
conn.Open();
//cmd.CommandTimeout = int.MaxValue;
using (SqlDataReader read = cmd.ExecuteReader())
{
while (read.Read())
{
double OldRoomPressure = read["OldRoomPressure"] == null ? 0 : double.Parse(read["OldRoomPressure"].ToString());
double NewRoomPressure = read["NewRoomPressure"] == null ? 0 : double.Parse(read["NewRoomPressure"].ToString());
double CoolingWaterTemp = read["CoolingWaterTemp"] == null ? 0 : double.Parse(read["CoolingWaterTemp"].ToString());
double IsWarning = read["IsWarning"] == null ? 0 : double.Parse(read["IsWarning"].ToString());
string CreateTime = read["CreateTime"].ToString();
//其他操作
}
}
}
}
@dudu: 谢谢。我这个是先进行方便测试用的,就写的比较粗糙。代码是存在一些问题。
但是,传入参数就无法进行查询,这个是什么原因呢?上面的图就是直接输出的id和sql语句,看着是正确的,但是就是查不出来,这个很是不解。
@1sa2sa: 直接在数据库执行同样的SQL语句正常吗?
@dudu: 正常的。直接执行这条sql语句能正常查出来数据。
@1sa2sa: 问题应该与在触发器中查询刚插入的记录有关,你可以试试把 select @newID=ID from inserted
改为一个已经存在的 ID
@dudu: 我直接 set @newID= 151060,这样写死id的值就可以。但是,触发器中写的是after insert啊。而且我是想实现数据插入是触发外部程序。这样的话,应该怎么办呢?
@dudu: 还有疑问是,触发器端是传了一个参数到外部程序中,外部程序只是接收了一个参数,为什么 select @newID=ID from inserted 这样会影响外部程序呢?而且是id的值已经传了过去。
@1sa2sa: 试试在控制台程序中查询数据库之前 Sleep 一会
@dudu:刚才我也这么想,然后试了一下,sleep了5秒,但是结果还是不行。
不过发现,当外部程序执行完(到报错为止),才能查到数据。在外部程序停止时数据才插入到数据库中。我直接sleep10秒,不去查询数据,什么都不做。当外部程序执行完这十秒,数据才进入到数据库中。
这种情况的话,想在外部程序中根据id查询这条数据,应该是不行的了。
@1sa2sa: 建议换一种不通过触发器的方式
@dudu: 应该是触发器执行完成之后,数据才会插入到数据库中。触发器执行完成需要外部程序先执行完。
@1sa2sa: 是的,就是这个原因