【问题标题】:Can I use SUM() inside of a SELECT INTO statement on a trigger?我可以在触发器的 SELECT INTO 语句中使用 SUM() 吗?
【发布时间】:2014-04-25 22:18:23
【问题描述】:

我想取同一个外键的每个账单金额的总和。如果总和小于零,我想更新 fk 表中的枚举字段。我找不到任何关于在 SELECT INTO 中使用 sum() 的信息,但如果它有效,那就太好了。

CREATE TRIGGER `bill_log_after_insert` AFTER INSERT ON `bill_log` 
FOR EACH ROW 
  DECLARE @amount DECIMAL;
  SELECT 
    SUM(`bill_amount`) 
  INTO 
    @amount 
  FROM
    `bill_log`
  WHERE 
    `main_fk` = NEW.`main_fk`; 
  IF @amount < 0 THEN 
    UPDATE `main` SET `transaction_type` = 'credit' WHERE `main_pk` = NEW.`main_fk`; 
  END IF;

【问题讨论】:

    标签: mysql sql stored-procedures triggers


    【解决方案1】:

    SELECT INTO 语句中使用SUM 是有效的。但是您的触发器还有其他一些问题:

    如果你想DECLARE 一个局部变量,你不能像会话变量所必需的那样在它前面加上@-符号。局部变量的范围仅在触发器内部,而不是在当前会话的全局范围内,因为它对于会话变量是全局的。为局部变量添加前缀(即v)是一种很好的做法,以将其与查询中的非限定字段名称区分开来,因为相同的名称可能会导致错误或至少是意外行为。

    您还需要在DECLARE 时指定DECIMAL 字段或变量的精度。默认为DECIMAL(10,0)。这意味着该数字可以是 10 位数字,并且没有小数位。如果设置为DECIMAL(8, 2),即数字可以为8位,但其中2位为小数位。

    DELIMITER //
    
    CREATE TRIGGER bill_log_after_insert AFTER INSERT ON bill_log
    FOR EACH ROW
        BEGIN
        DECLARE v_amount DECIMAL(8, 2);
    
        SELECT SUM(bill_amount)
            INTO v_amount
            FROM bill_log
            WHERE main_fk = NEW.main_fk;
    
        IF v_amount < 0 THEN
            UPDATE main SET transaction_type = 'credit' WHERE main_pk = NEW.main_fk;
        END IF;
        END //
    
    DELIMITER ;
    

    演示@SQL Fiddle

    【讨论】:

    • +1。两个小点:DECIMAL(8,2) 允许总共 个小数位,小数点后 两个,小数点前 六个。对变量使用唯一名称是可取的;如果变量名与 SQL 语句中的非限定列的名称匹配(例如,在 SELECT 列表或 WHERE 子句中),MySQL 不一定会返回错误。 MySQL 认为这是指局部变量。在 MySQL 存储程序中,局部变量优先于列名。 (这与 Oracle PL/SQL 等列名优先的其他数据库不同。)
    • @spencer7593 - 感谢您的提示。我更新了我的答案。
    • 此外,限定 SQL 语句中的 ALL 列引用使引用明确。 (我认为不允许将点作为局部变量名的一部分。)
    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 2010-11-05
    • 2013-04-13
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多