Триггер вызывает ошибку (подзапрос возвращает более одного значения) при массовой вставке - PullRequest
1 голос
/ 18 января 2020
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.

1 Ответ

1 голос
/ 18 января 2020

Кажется, вы предполагаете, что триггер сервера SQL будет запущен отдельно для каждой строки - это НЕ случай - триггер срабатывает только один раз для оператора. И если это BULK INSERT, то псевдотаблица Inserted будет содержать несколько строк - поэтому ваши утверждения типа

set @Barcode = (Select barcodeFull from inserted);

на самом деле являются источником проблемы - что один из 250 вставленных строк вы выбираете здесь? Это не определено - вы получите одну произвольную строку - и что происходит с другими 249 вставленными строками ?? Они просто игнорируются и не обрабатываются.

Вам необходимо переписать всю вашу логику триггера c, чтобы она была на основе набора , и обрабатывать тот факт, что 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 для соответствия вашей ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...