触发器在批量插入时导致错误(子查询返回多个值)

问题描述 投票:1回答:1
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);
}

[开始批量插入时,触发器将引发此错误:

子查询返回多个值。...

我看着这个触发器,它更新t_Prd表而不是在t_PromoDtl表上插入。

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-server triggers bulkinsert
1个回答
0
投票

您似乎假设将为每一行分别触发SQL Server触发器-这是NOT的情况-对于语句,仅触发触发器[[仅一次。如果这是一个BULK INSERT,则Inserted伪表将包含多行-因此您的语句,例如

set @Barcode = (Select barcodeFull from inserted);
实际上是问题的根源-您在此处选择的是插入的250行中的哪一行?还没有确定-您将返回

一个任意

行-插入的其他249行又会怎样?它们只是被忽略而没有被处理。您需要

rewrite

您的整个触发逻辑为set-based并处理Inserted伪表很可能包含多行的事实。尝试这样的事情:

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是您的

主键列

,它唯一地标识表中的每一行-否则,您可能需要调整JOIN条件以匹配您的情况。
© www.soinside.com 2019 - 2024. All rights reserved.