批量插入时触发器导致错误(子查询 return 多于一个值)
Trigger causes error (subquery return more than one value) on Bulk Insert
Alter Trigger [dbo].[DiscountUpdate]
on [dbo].[t_PromoDtl]
Instead of insert
as
begin
Declare @Barcode nvarchar(25);
Declare @disper decimal(18,0);
Declare @status int;
Declare @BranchID nvarchar(15);
set @Barcode = (Select barcodeFull from inserted); ---/// I think error happens in here.
set @disper = (Select disPer from inserted); ---/// I think error happens in here.
set @status = (Select p.status from inserted p); ---/// I think error happens in here.
begin
if @status = 2
begin
update t_Prd
set PrdDiscnt = @disper
where BarcodeFull = @Barcode;
end
else
begin
update t_Prd
set PrdDiscnt = 0
where BarcodeFull = @Barcode;
end
end
end
这是我的 C# 代码..
using (var sqlBulk3 = new SqlBulkCopy(_connectionString, SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints))
{
using (SqlConnection con6 = new SqlConnection(_connectionString))
{
con6.Open();
SqlCommand cmdtt = new SqlCommand("Truncate Table t_PromoDtl", con6);
cmdtt.CommandType = CommandType.Text;
cmdtt.ExecuteNonQuery();
con6.Close();
}
sqlBulk3.DestinationTableName = "t_PromoDtl";
sqlBulk3.WriteToServer(PromoDtl);
}
开始批量插入时,触发器抛出此错误:
Sub query returns more than one value....
我查看了这个更新 t_Prd
table 而不是插入 t_PromoDtl
table 的触发器。
set @Barcode = (Select barcodeFull from inserted); ---/// I think error happens in here.
set @disper = (Select disPer from inserted); ---/// I think error happens in here.
set @status = (Select p.status from inserted p); ---/// I think error happens in here.
您似乎假设 SQL 服务器触发器将针对每一行单独触发 - 这是 不是 的情况 - 触发器被触发 只有一次 一个声明。如果这是一个 BULK INSERT
,那么 Inserted
伪 table 将包含 多行 - 所以你的语句像
set @Barcode = (Select barcodeFull from inserted);
实际上是问题的根源 - 您在此处选择插入的 250 行中的哪一行?不确定 - 您将返回 任意 行 - 其他 249 行也插入会怎样?它们只是简单地被忽略而不被处理。
您需要重写您的整个触发逻辑基于集合并处理Inserted
伪table 很可能包含多行。
尝试这样的事情:
ALTER TRIGGER [dbo].[DiscountUpdate]
ON [dbo].[t_PromoDtl]
INSTEAD OF INSERT
AS
BEGIN
-- update "dbo.T_Prd.PrdDiscnt" to "disPer" when status is 2
UPDATE p
SET PrdDiscnt = i.disPer
FROM dbo.T_Prd p
INNER JOIN Inserted i ON i.BarcodeFull = p.BarcodeFull
WHERE i.Status = 2;
-- update "dbo.T_Prd.PrdDiscnt" to "0" when status is not 2
UPDATE p
SET PrdDiscnt = 0
FROM dbo.T_Prd p
INNER JOIN Inserted i ON i.BarcodeFull = p.BarcodeFull
WHERE i.Status <> 2;
我在这里假设 BarcodeFull
是您的 主键列 ,它唯一标识 table 中的每一行 - 如果不是这样,您可能需要调整 JOIN 条件以符合您的情况。
Alter Trigger [dbo].[DiscountUpdate]
on [dbo].[t_PromoDtl]
Instead of insert
as
begin
Declare @Barcode nvarchar(25);
Declare @disper decimal(18,0);
Declare @status int;
Declare @BranchID nvarchar(15);
set @Barcode = (Select barcodeFull from inserted); ---/// I think error happens in here.
set @disper = (Select disPer from inserted); ---/// I think error happens in here.
set @status = (Select p.status from inserted p); ---/// I think error happens in here.
begin
if @status = 2
begin
update t_Prd
set PrdDiscnt = @disper
where BarcodeFull = @Barcode;
end
else
begin
update t_Prd
set PrdDiscnt = 0
where BarcodeFull = @Barcode;
end
end
end
这是我的 C# 代码..
using (var sqlBulk3 = new SqlBulkCopy(_connectionString, SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints))
{
using (SqlConnection con6 = new SqlConnection(_connectionString))
{
con6.Open();
SqlCommand cmdtt = new SqlCommand("Truncate Table t_PromoDtl", con6);
cmdtt.CommandType = CommandType.Text;
cmdtt.ExecuteNonQuery();
con6.Close();
}
sqlBulk3.DestinationTableName = "t_PromoDtl";
sqlBulk3.WriteToServer(PromoDtl);
}
开始批量插入时,触发器抛出此错误:
Sub query returns more than one value....
我查看了这个更新 t_Prd
table 而不是插入 t_PromoDtl
table 的触发器。
set @Barcode = (Select barcodeFull from inserted); ---/// I think error happens in here.
set @disper = (Select disPer from inserted); ---/// I think error happens in here.
set @status = (Select p.status from inserted p); ---/// I think error happens in here.
您似乎假设 SQL 服务器触发器将针对每一行单独触发 - 这是 不是 的情况 - 触发器被触发 只有一次 一个声明。如果这是一个 BULK INSERT
,那么 Inserted
伪 table 将包含 多行 - 所以你的语句像
set @Barcode = (Select barcodeFull from inserted);
实际上是问题的根源 - 您在此处选择插入的 250 行中的哪一行?不确定 - 您将返回 任意 行 - 其他 249 行也插入会怎样?它们只是简单地被忽略而不被处理。
您需要重写您的整个触发逻辑基于集合并处理Inserted
伪table 很可能包含多行。
尝试这样的事情:
ALTER TRIGGER [dbo].[DiscountUpdate]
ON [dbo].[t_PromoDtl]
INSTEAD OF INSERT
AS
BEGIN
-- update "dbo.T_Prd.PrdDiscnt" to "disPer" when status is 2
UPDATE p
SET PrdDiscnt = i.disPer
FROM dbo.T_Prd p
INNER JOIN Inserted i ON i.BarcodeFull = p.BarcodeFull
WHERE i.Status = 2;
-- update "dbo.T_Prd.PrdDiscnt" to "0" when status is not 2
UPDATE p
SET PrdDiscnt = 0
FROM dbo.T_Prd p
INNER JOIN Inserted i ON i.BarcodeFull = p.BarcodeFull
WHERE i.Status <> 2;
我在这里假设 BarcodeFull
是您的 主键列 ,它唯一标识 table 中的每一行 - 如果不是这样,您可能需要调整 JOIN 条件以符合您的情况。