如何概括 SQL 触发器中的“WHERE”子句

问题描述 投票:0回答:1

我对 SQL 非常陌生,现在正在练习创建触发器函数。目前,我正在尝试创建一个存储过程,以便在发生销售或库存更新时更新产品记录。现在,它看起来像这样:

CREATE TRIGGER IF NOT EXISTS after_sale_insert
AFTER insert ON sales
BEGIN
    INSERT INTO log_messages (message) 
    VALUES ('new sale record created and product quantity updated');

    UPDATE products
    SET quantity = (SELECT products.quantity - sales.quantity_sold 
                    FROM products
                    JOIN sales ON products.product_id = sales.product_id)
    WHERE products.product_id = sales.product_id;
END;

触发器在“WHERE”元素之前工作正常,我尝试使用该元素来指定

Products
表中的产品 ID 应与触发命令 (
products.product_id = [whatever product_id is inserted into "Sales"]
) 输入的产品 ID 相匹配。

我正在使用以下命令对其进行测试:

INSERT INTO sales (product_id, quantity_sold) 
VALUES (1, 20);

但是,我现在的方式只会让我的程序(SQLite)返回错误(“没有这样的列:sales.product_id”)。总之:我正在努力弄清楚如何创建一个可以普遍适用并且仍然可以在 SQLite 中运行的

WHERE
子句。有什么帮助吗?

我的表格的完整代码如下:

CREATE TABLE products 
(
    product_id INTEGER PRIMARY KEY,
    product_name TEXT NOT NULL,
    quantity INTEGER NOT NULL,
    price REAL NOT NULL
);

CREATE TABLE sales 
(
    sale_id INTEGER PRIMARY KEY,
    product_id INTEGER NOT NULL,
    quantity_sold INTEGER NOT NULL,
    FOREIGN KEY (product_id) REFERENCES products(product_id)
);

CREATE TABLE stock_updates 
(
    update_id INTEGER PRIMARY KEY,
    product_id INTEGER NOT NULL,
    new_quantity INTEGER NOT NULL,
    FOREIGN KEY (product_id) REFERENCES products(product_id)
);

CREATE TABLE log_messages 
(
    id INTEGER PRIMARY KEY,
    message TEXT
);

INSERT INTO products (product_name, quantity, price) 
VALUES ('Product A', 100, 50.00),
       ('Product B', 50, 70.00),
       ('Product C', 200, 30.00);

我尝试过使用 JOIN 元素并添加“old”。语句各个部分的前缀,这没有帮助。如果我消除“WHERE”语句,触发器在技术上可以工作(因为它不会返回错误),但它会将所有产品的数量更改为 20。这是通过我的测试插入到 Sales 表中的数量命令,但绝对不是它应该做的事情。

完全消除“WHERE”语句并将“SET”语句更改为“SET数量 = (products.quantity - sales.quantity_sold) FROM products JOIN sales ON products.product_id = sales.product_id”后,我收到错误“不明确的列”名称:产品.数量。”这很令人兴奋,但也不是我正在寻找的解决方案。

sql sqlite stored-procedures triggers where-clause
1个回答
0
投票

看起来Sqlite需要你使用特殊的

New
:

WHEN 子句和触发器操作都可以使用“NEW.column-name”和“OLD.column-name”形式的引用来访问正在插入、删除或更新的行的元素

请注意,某些数据库不能保证每次单独的更改都会触发触发器,但可能会将多个更改一起批处理以提高性能。因此,请谨慎假设触发器中只有一行。

此外,在大多数平台上,触发器不能保证“main”语句是原子的,因此您必须小心不要设置竞争条件。使用包含在事务中的两个单独的连续语句来执行此类操作通常会更好。

© www.soinside.com 2019 - 2024. All rights reserved.