批量插入时触发器导致错误(子查询 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 条件以符合您的情况。