如何在 SQL 触发器中泛化“WHERE”子句

How to generalize a "WHERE" clause in a SQL trigger

提问人:Finn Kimbrel 提问时间:11/8/2023 最后编辑:marc_sFinn Kimbrel 更新时间:11/9/2023 访问量:27

问:

我对 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”元素之前工作正常,我尝试使用它来指定表中的产品 ID 应与触发命令 () 输入的产品 ID 匹配。Productsproducts.product_id = [whatever product_id is inserted into "Sales"]

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

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 quantity = (products.quantity - sales.quantity_sold) FROM products JOIN sales ON products.product_id = sales.product_id”后,我收到错误“模棱两可的列名:products.quantity”。这很令人兴奋,但也不是我正在寻找的解决方案。

sql sqlite 存储过程 触发器 where-clause

评论

0赞 Vector 11/8/2023
如果您只抓取产品 ID 和销售 ID,将它们设置为某个变量 DIM 作为整数,会发生什么 它们是数据库中的整数 也许声明认为它们是字符串

答:

0赞 Joel Coehoorn 11/8/2023 #1

看起来 Sqlite 需要您使用特殊的 New

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

请注意,某些数据库不保证在每次单独的更改时触发触发器,而是可能会将多个事件批处理在一起以提高性能。因此,假设触发器中只有一行,请小心。

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