2015-11-02 66 views
0

我正在嘗試編寫觸發器來控制記錄是否已在表中。如果記錄已在表中(例如按名稱比較),那麼當前記錄集合valid ='False'並插入新記錄。有什麼辦法嗎?檢查表中是否存在值 - 觸發器

這是我的想法,但它不起作用。

create or replace TRIGGER 
Check_r 
    before insert on t$customer 
    FOR each ROW 
    declare 
    v_dup number; 
    v_com number; 
    v_id number; 
    v_id_new number; 
    begin 
    v_date:=SYSDATE; 
     select count(id) INTO v_dup from t$customer where surname=:NEW.surname ; 
     select count(id) INTO v_com from t$customer where firstname =:NEW.firstname and 
     address=:NEW.address; 
     select id into v_id from t$customer where surname=:NEW.surname; 
    if v_dup > 0 and v_com=0 then 
    v_id_new:= m$_GET_ID; -- get id 
    update t$customer set valid = 'False' where id = v_id; 
    insert into t$customer (id, surname ,firstname, valid, address) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address); 
    end if; 
    if v_dup = 0 then 
    v_id_new:= m$_GET_ID; -- get id 
    insert into t$customer (id, surname ,firstname, valid , address) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address); 
    end if; 
    end; 
+1

我不會那樣做觸發器。 –

+2

表A上的觸發器通常無法查詢表A,因爲該表的數據當前處於通量狀態。而且觸發器也不能在另一個表中插入/更新。您正在編寫一個觸發器,假定該行被插入,在正確的情況下,應該再次插入該行。有解決方法,但是對於你所問的問題,我會建議編寫一個你的應用程序調用的PL/SQL過程來檢查,然後根據需要進行插入或更新。 –

+2

它不起作用? –

回答

0

首先,這是插入的觸發器。你不需要編寫插入語句。

其次,您需要更新舊記錄。只需使用where子句進行更新即可。

CREATE OR REPLACE TRIGGER Check_r 
before insert on t$customer 
FOR each ROW 
BEGIN 
    UPDATE t$customer set valid = 'False' 
    WHERE surname = :NEW.surname 
    AND firstname =:NEW.firstname; 
:NEW.id := m$_GET_ID; 
END; 
+0

將無法​​工作 - 您無法更新觸發器觸發的表(「表正在變異...」) –

+0

它與Oracle 12c一起工作。 –

0

您可以使用複合觸發器,例如:

CREATE OR REPLACE TRIGGER Check_r 
    FOR INSERT ON t$customer 
    COMPOUND TRIGGER 

    TYPE customerRecordType IS RECORD(
     surname t$customer.surname%TYPE, 
     firstname t$customer.firstname%TYPE, 
     address t$customer.address%TYPE, 
     ID nubmer); 
    TYPE customerTableType IS TABLE OF customerRecordType; 
    customerTable customerTableType := customerTableType(); 

    n NUMBER; 

BEFORE STATEMENT IS 
BEGIN  
    customerTable.DELETE; -- not requried, just for better understanding 
END STATEMENT; 


BEFORE EACH ROW IS 
BEGIN  
    customerTable.EXTEND; 
    customerTable(customerTable.LAST).surname := :NEW.surname; 
    customerTable(customerTable.LAST).firstname := :NEW.firstname; 
    customerTable(customerTable.LAST).address := :NEW.address; 
    customerTable(customerTable.LAST).ID := m$_GET_ID; 
    :NEW.ID := customerTable(customerTable.LAST).ID; 
END BEFORE EACH ROW; 

AFTER STATEMENT IS 
BEGIN 
    FOR i IN customerTable.FIRST..customerTable.LAST LOOP  
     SELECT COUNT(*) INTO n 
     FROM t$customer 
     WHERE surname = customerTable(i).surname;  
     IF n > 1 THEN 
      UPDATE t$customer 
      SET valid = 'False' 
      WHERE surname = customerTable(i).surname; 
     END IF; 

     SELECT COUNT(*) INTO n 
     FROM t$customer 
     WHERE firstname = customerTable(i).firstname 
      AND address = customerTable(i).address; 
     IF n > 1 THEN 
      UPDATE t$customer 
      SET valid = 'False' 
      WHERE firstname = customerTable(i).firstname 
       AND address = customerTable(i).address 
     END IF; 
    END LOOP; 

END AFTER STATEMENT;  

END; 
/

請注意,這個解決方案是醜陋和貧窮方面的性能! 但它應該給你一個印象它是如何工作的。

一般來說,你應該把所有這些放到PL/SQL過程而不是觸發器中。