2012-02-15 56 views
4

之前,我有一個這樣的場景來分配外鍵值:如何使用一個INSERT觸發器

有兩個表table1table2table1有一個主鍵pkeytable2現在有一個外鍵fkey現在在一個插入過程中,如果提供了外鍵,值應插入原樣。否則,它必須使用一些計算從table1獲得主鍵並確定要插入的外鍵。我該怎麼做呢??

我使用的是MySQL 5.0

編輯

我的方案,table1持有的結算明細,也就是table1有票據,總金額支付。客戶支付一定數額的未付餘額或將支付特定賬單。我想在這裏做的是。當我沒有提供bill_id(這是table1的主鍵和table2的外鍵)時,我想要搜索table1中到期的最早的帳單,並扣除應付金額,並進一步扣除剩餘金額(如果有的話)下一張帳單中的帳單。我想在數據庫層而不是上層執行此操作。因此,當插入操作沒有外鍵值時,應該通過觸發器檢索並放置該值,或者直接插入。我如何實現這一目標?

使用這裏提供的答案,我想這:

CREATE DEFINER=`root`@`localhost` TRIGGER `inflow_pay_done_insert` BEFORE INSERT ON `inflow_pay_done` FOR EACH ROW BEGIN 
    DECLARE pkey INT; 
    SET pkey = (SELECT bill_id from inflow_bills where payment_stat = 0 and rs_id = NEW.rs_id order by time_stamp limit 1); 
    SET NEW.bill_id = IF(NEW.bill_id , NEW.bill_id , pkey); 
    UPDATE raw_mat_sup rms SET rms.outstanding_bal_payable = rms.outstanding_bal_payable - NEW.amount where rms.rs_id = NEW.rs_id; 
END| 

和我收到的時候我試圖在inflow_pay_done插入以下錯誤:

/* SQL錯誤(1048):列「bill_id」不能爲空* ​​/

+0

什麼爲當'INSERT'爲'table2'沒有提供選擇從'table1'主鍵的條件?只是爲了擁有有效的關係/外鍵而隨機選擇一個呢?換句話說: – Kaii 2012-02-15 07:16:37

+0

:你能更準確地實現你想要實現的目標嗎? – Kaii 2012-02-15 07:42:31

+0

@Kaii看到我的編輯 – 2012-02-15 08:51:00

回答

4

,你可以在BEFORE INSERT觸發器使用子查詢這個..

DELIMITER | 
DROP TRIGGER `inflow_pay_done_insert`| 
CREATE TRIGGER `inflow_pay_done_insert` BEFORE INSERT ON `inflow_pay_done` 
FOR EACH ROW 
BEGIN 
    UPDATE raw_mat_sup rms 
    SET rms.outstanding_bal_payable = rms.outstanding_bal_payable - NEW.amount 
    WHERE rms.rs_id = NEW.rs_id; 
    NEW.bill_id = IF(NEW.bill_id, 
    /* if "bill_id" is provided in INSERT statement, use provided value */ 
    NEW.bill_id, 
    /* if not, query other table for the correct value */ 
    ( /* this subquery is just an example, put your own query here*/ 
     SELECT bill_id FROM inflow_bills 
     /* find customers newest bill based on newest date and customer id */ 
     WHERE payment_stat = 0 AND rs_id = NEW.rs_id 
     ORDER BY time_stamp DESC LIMIT 1 
    ) 
); 
END; 
| 
delimiter; 
( - >外鍵)0

UPDATE

因爲MySQL Bug的,當列允許爲NULL,並且在列沒有限制,這隻會工作。原因在於,與其他DBMS不同,MySQL在之前檢查約束條件,並且有效地避免執行觸發器來糾正要插入的數據。

直到MySQL的行爲發生變化時,唯一的解決方案是使用STORED PROCEDURE而不是簡單的INSERT。然後使用應該插入的值調用存儲過程。在這個過程中,數據校正(如在這種情況下:選擇正確的bill_id)完成,然後INSERT從存儲過程中執行。

UPDATE II

這個錯誤似乎是固定在5.7.1。Changelog說:

如果一列被聲明爲NOT NULL,則不允許將 NULL插入到列中或將其更新爲NULL。然而,這種約束 即使有一個BEFORE INSERT(或BEFORE UPDATE觸發器 ),該列設置爲一個非NULL值執行。現在,根據SQL標準,在語句結尾處檢查約束條件 。