Проблемы вставки триггера SQL - PullRequest
0 голосов
/ 07 июня 2018

Я хочу сделать триггер, где я могу проверить, равно ли значение из запаса товара 0.Тогда триггер должен сделать значение 1.

Мой триггер

CREATE TRIGGER [IfStockIsNull]
ON [dbo].[Products]
FOR DELETE, INSERT, UPDATE
AS
BEGIN

if [Products].Stock = 0
    UPDATE [Products] SET [Stock] = 1
    FROM [Products] AS m
    INNER JOIN inserted AS i
    ON m.ProductId = i.ProductId;
ELSE
    raiserror('Niks aan het handje',10,16);
END

Я получаю сообщение об ошибке:

Altering [dbo].[IfStockIsNull]...
(53,1): SQL72014: .Net SqlClient Data Provider: Msg 4104, Level 16, State 1, 
Procedure IfStockIsNull, Line 7 The multi-part identifier "Products.Stock" 
could not be bound.
(47,0): SQL72045: Script execution error.  The executed script:
ALTER TRIGGER [IfStockIsNull]
ON [dbo].[Products]
FOR DELETE, INSERT, UPDATE
AS BEGIN
       IF [Products].Stock = 0
           UPDATE [Products]
           SET    [Stock] = 1
           FROM   [Products] AS m
                  INNER JOIN
                  inserted AS i
                  ON m.ProductId = i.ProductId;
       ELSE
           RAISERROR ('Niks aan het handje', 10, 16);
   END

An error occurred while the batch was being executed.

Может быть, вы, ребята, можете мне помочь?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Если вы хотите остановить вставку, если строки плохие, сделайте это до внесения изменений:

ALTER TRIGGER [IfStockIsNull] ON [dbo].[Products]
    FOR INSERT, UPDATE  -- DELETE is not really appropriate
AS BEGIN
   IF (EXISTS (SELECT 1
               FROM Products p JOIN
                    inserted i
                    ON m.ProductId = i.ProductId
               WHERE p.Stock = 0
              )
      )
    BEGIN
        RAISERROR ('Niks aan het handje', 10, 16);
    END;
     UPDATE p
         SET Stock = 1
         FROM Products p INNER JOIN
              inserted AS i
              ON p.ProductId = i.ProductId;
END;

Примечания:

  • Сравнение в IF проверяет, есть ли у какой-либо из строк Product 0.Если это так, вся транзакция откатывается.
  • Вы можете жаловаться, что не можете отклонить одну строку.Но так работают транзакции.Если в INSERT произойдет сбой какой-либо строки, будет откатан весь INSERT, а не только одна строка.
  • UPDATE неверен, поскольку в FROM имеется Productsпункт и пункт UPDATE.Вы должны использовать псевдоним для первого.
0 голосов
/ 07 июня 2018

Ряд проблем и сюрпризов в том, что вы пытаетесь запустить здесь.Но в принципе, не пытайтесь выполнить процедурные шаги, когда вы имеете дело с сетами .inserted может содержать 0, 1 или несколько строк, так что , какой запас строки вы спрашиваете в вашей IF?

Лучше иметь дело с этим вWHERE предложение:

CREATE TRIGGER [IfStockIsNull]
ON [dbo].[Products]
FOR INSERT, UPDATE --Removed DELETE, because ?!?
AS
BEGIN

    UPDATE [Products] SET [Stock] = 1
    FROM [Products] AS m
    INNER JOIN inserted AS i
    ON m.ProductId = i.ProductId;
    WHERE m.Stock = 0
    --Not sure what the error is for - the above update may have updated
    --some number of rows, between 0 and the number in inserted.
    --What circumstances should produce an error then?
END

Простой демонстрационный скрипт, в котором UPDATE равен , правильно ориентируясь только на соответствующие строки из inserted:

declare @t table (ID int not null, Val int not null)
insert into @t(ID,Val) values (1,1),(2,2),(3,3)
update
    @t
set
    Val = 4
from
    @t t
        inner join
    (select 2 as c) n
        on
            t.ID = n.c

select * from @t

Показывает, что обновляется только строка с ID из 2.

Даже собственный пример от Microsoft из UPDATE ... FROM синтаксис использует UPDATE <table> ... FROM <table> <alias> ...синтаксис, который утверждает Гордон, не работает:

USE AdventureWorks2012;  
GO  
UPDATE Sales.SalesPerson  
SET SalesYTD = SalesYTD + SubTotal  
FROM Sales.SalesPerson AS sp  
JOIN Sales.SalesOrderHeader AS so  
    ON sp.BusinessEntityID = so.SalesPersonID  
    AND so.OrderDate = (SELECT MAX(OrderDate)  
                        FROM Sales.SalesOrderHeader  
                        WHERE SalesPersonID = sp.BusinessEntityID);  
GO  

В этом примере действительно есть проблема, которая дополнительно объяснена ниже, но которая связана с "множественными совпадающими строками в других таблицах, приведет кнедостаток только в одном обновлении, о котором должен знать каждый, кто работает с UPDATE ... FROM.

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