2017-04-12 24 views
0

我有这样的触发器,它运作良好,但我读了使用游标并循环不好的表现..的MySQL使用一个插入语句而不是游标循环

所以,我怎么能顶替使用光标和循环利用一个INSERT INTO像一个在更新部分的语句:

CREATE TRIGGER `after_insert_invoice` AFTER INSERT ON `invoicetbl` 
FOR EACH ROW BEGIN 
    DECLARE v_finished INTEGER DEFAULT 0; 
    DECLARE my_hour INT(11) DEFAULT 0; 
    DECLARE my_day INT(11) DEFAULT 0; 
    DECLARE my_month INT(11) DEFAULT 0; 
    DECLARE current_item_id BINARY(16); 
    DECLARE current_item_total_price DECIMAL(11, 2); 
    DECLARE current_item_count DECIMAL(11, 3); 

    DECLARE cur CURSOR FOR  SELECT item_id, item_total_price, item_count 
     FROM invoice_itemtbl 
     WHERE invoice_id = NEW.invoice_id; 

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1; 

    SET my_month = EXTRACT(YEAR_MONTH FROM NEW.invoice_date); 
    SET my_day = CONCAT(my_month, LPAD(DAY(NEW.invoice_date), 2, '0')); 
    SET my_hour = CONCAT(my_day, LPAD(HOUR(NEW.invoice_date), 2, '0')); 

    IF NEW.invoice_type = 0 THEN 

     OPEN cur; 

     start_loop: LOOP 

     FETCH cur INTO current_item_id, 
         current_item_total_price, 
         current_item_count; 

     IF v_finished = 1 THEN 
      LEAVE start_loop; 
     ELSE 

(续)

 INSERT 
      INTO sales_result_company_item_month(company_id, currency_id, 
       time_value, item_id, result, invoices_count, item_qty) 
      VALUES (NEW.company_id, NEW.currency_id, my_month, current_item_id, 
        current_item_total_price, 1, current_item_count) 
      ON DUPLICATE KEY 
      UPDATE result = result + current_item_total_price, 
        invoices_count = invoices_count + 1, 
        item_qty = item_qty + current_item_count; 

     END IF; 
     END LOOP; 

     CLOSE cur; 

    END IF; 

    IF NEW.invoice_type = 1 THEN 

    //like here: 
    UPDATE sales_result_company_item_month m 
    INNER JOIN 
    (
     SELECT item_id, returns_count, returns_total 
      FROM invoice_returns 
      WHERE return_invoice_id = NEW.invoice_id 
    ) f ON m.item_id = f.item_id SET m.result = m.result - f.returns_total, 
     m.item_qty = m.item_qty - f.returns_count 
    WHERE m.company_id = NEW.company_id 
     AND m.currency_id = NEW.currency_id 
     AND m.time_value = my_month; 

    END IF; 

END 

(从评论复制 - 后 '固定' 的问题,包括消除光标):

INSERT 
    INTO sales_result_company_item_month 
     (company_id, currency_id, time_value, item_id, 
      result, invoices_count, item_qty) 
SELECT NEW.company_id, NEW.currency_id, my_month, t.item_id, 
     t.item_total_price, 1, t.item_count 
    FROM invoice_itemtbl t 
    WHERE invoice_id = NEW.invoice_id 
    ON DUPLICATE KEY UPDATE 
     result = result + t.item_total_price, 
     invoices_count = invoices_count + 1, 
     item_qty = item_qty + t.item_count; 

回答

2

是的,你也许可以摆脱光标。

这是可以做到

INSERT INTO t (...) 
    ON DUPLICATE KEY UPDATE ... 
    SELECT ...; 

在于,在SELECT获取所有行“更新插入”。在UPDATE子句中,您可能需要VALUES()才能区分所选列和列表中已有的列。请参阅手册中的示例。

如果您想进一步讨论这个问题,请

  • 提供SHOW CREATE TABLE的相关表格,
  • 摆脱kruft(例如,my_day,未使用)
  • 的前缀地方变量与_,或以其他方式区分表列。

current_item_count DECIMAL(11, 3)拼图我:什么“计数”需要3位小数?

+0

非常感谢。这是结果查询:INSERT INTO sales_result_company_item_month(company_id,currency_id,time_value,item_id,result,invoices_count,item_qty) SELECT NEW.company_id,NEW.currency_id,my_month,t.item_id,t.item_total_price,1,t.item_count FROM invoice_itemtbl t WHERE invoice_id = NEW.invoice_id ON DUPLICATE KEY UPDATE result = result + t.item_total_price,invoices_count = invoices_count + 1,item_qty = item_qty + t.item_count;' – user2241289

+0

'current_item_count'它是INT(11),我改变该类型不改变名称。谢谢。 – user2241289

+0

另请参阅:http://stackoverflow.com/a/2472315/2241289 – user2241289