我有twoStocks号桌和Purchases号桌

CREATE TABLE Stocks
(
  id int PRIMARY KEY IDENTITY(1,1),
  itemId int NOT NULL,
  qty int  NOT NULL,
  status NVarChar(50) NOT NULL,
)


CREATE TABLE Purchases
(
  id int PRIMARY KEY IDENTITY(1,1),
  itemId int NOT NULL,
  suppId int NOT NULL,
  qty int  NOT NULL,
  Date NVarChar(50) NOT NULL,
  status NVarChar(50) NOT NULL,
)

以下是我想要做的:

在将多个记录插入到Purchases表中时,我希望创建一个触发器来迭代插入的每个记录,并判断Stocks表中的ItemID

更新找到的每个ItemID的TheQuantity(本例中为qty),如果找不到ItemID,则插入到Stocks表中

我已经try 了几种方法,实际上从昨天开始我就一直在与之斗争.

this Post是我见过的最近的一次,但我能弄清楚是怎么回事,看起来它只是在更新现有的记录

这是我到目前为止试过的方法,我是说我最接近的

CREATE trigger [dbo].[trPurchaseInsert] on [dbo].[Purchases] FOR 
  INSERT
 AS
DECLARE @id int;
DECLARE @itemId int;
DECLARE @status NVarChar(50) = 'available';

    SELECT @itemId=i.ItemId FROM INSERTED i
 IF EXISTS(SELECT * FROM Stocks WHERE itemId=@itemId)
 BEGIN
      SET NOCOUNT ON;

     DECLARE @itemIdUpdate int;
     DECLARE @qty int;

    SELECT @qty=[quantity], @itemIdUpdate=[itemId] FROM INSERTED i 
    
    UPDATE Stocks SET qty=qty+@qty WHERE itemId=@itemIdUpdate
  END
 ELSE
 BEGIN
    SET NOCOUNT ON;
    INSERT INTO Stocks SELECT [itemId], [id], [quantity], @status 
    FROM INSERTED i
 END

这在单个插入中运行良好,但在一次将多条记录插入到采购表中时就不起作用了

上面的触发器只更新第一个Itemid,如果找到一个Itemid,则不会更新其余Itemid,甚至不会插入新的Itemid

这里的目标是如果找到itemid则更新库存项目,如果没有找到itemid则插入

欲了解更多详情,请点击see this SQL Fiddle.它包含我try 过的带有注释详细信息的表格(&A

我看到了几条建议使用set base operations with joins的 comments ,但想不出方向

我怎么才能让它工作呢?

推荐答案

Your trigger is fatally flawed.它不考虑插入的多行,也不处理更新和删除.

相反,您应该使用以下命令:

  • 请注意inserteddeleted是如何同时使用的.deleted.qty被减go .
  • 所有的东西都被itemId组合在一起,然后差值被应用到Stocks.
  • 因为您还想插入,所以您需要使用MERGE.或者,您可以使用单独的联接UPDATEINSERT...WHERE NOT EXISTS语句.
CREATE OR ALTER TRIGGER dbo.trPurchaseInsert
ON dbo.Purchases
AFTER INSERT, UPDATE, DELETE
AS

SET NOCOUNT ON;

MERGE Stocks s
USING (
    SELECT
      diff.ItemId,
      qty = SUM(diff.qty)
    FROM (
        SELECT
          i.ItemId,
          i.qty
        FROM inserted i
        UNION ALL
        SELECT
          d.ItemId,
          -d.qty
        FROM deleted d
    ) diff
    GROUP BY
      diff.ItemId
) diff
ON diff.ItemId = s.ItemId
WHEN NOT MATCHED THEN
  INSERT (itemId, qty, status)
  VALUES (diff.itemId, diff.qty, 'available')
WHEN MATCHED THEN
  UPDATE SET
    qty += diff.qty;

I must say, I would not implement this with triggers at all.

最好不要将这样的数据反规范化到另一个表中.如果您需要查询它,您可以从Purchase表中即时进行查询.如果需要,可以使用视图,甚至可以对其进行索引.

CREATE VIEW dbo.vTotalStock
WITH SCHEMABINDING   -- an indexed view must be schema-bound
AS
SELECT
  p.ItemId,
  qty = SUM(p.qty),
  count = COUNT_BIG(*)  -- must always include COUNT_BIG if aggregating and indexing
FROM dbo.Purchases p
GROUP BY
  p.ItemId;
CREATE UNIQUE CLUSTERED INDEX UX ON vTotalStock (ItemId)

db<>fiddle

Sql相关问答推荐

使用SQL/R循环查找邻居

SQL JOIN of 2 Table with 2 sum

SQL是否可以计算每年的所有日期变化?

在SQL中创建一个计数器,根据BigQuery/SQL中的条件递归地添加行值

使用Mac日志(log)时间找出SQL中的好小时和坏小时

前面的语句不喜欢AND LIKE?当try 更新使用ID和日期过滤的表时

仅 for each 唯一ID返回一个元素,并仅返回最新连接的记录

使用SQL创建列出两个时间戳之间小时数的列

PostgreSQL:按小时查看调整日期

根据是否出现过零来筛选数据(跨多行)

最小非重复集的SQL查询

SQL仅返回第一个字母在A-Z之间的值

postgres中的条件索引和触发器

DB2 SQL查询结果多余数据

Postgres,使用 select 插入多个值

Postgresql 生成器列导致语法错误

Postgresql:在链接表中判断相关表中插入值的条件

从 varchar 列中删除特殊字符后的前面的零和字符时遇到问题

PostgresQL-根据另一列找到 3 个最低值

BigQuery 将一行拆分为多列