2016-05-30 10 views
1

Ich habe eine Tabelle namens PKCHANGES, die ein paar Spalten hat, von denen eine die primary_key-Spalte ist. Ich möchte einen Trigger für andere Tabellen erstellen, und bei einer Einfügung greife ich einige Werte und poste sie in die Tabelle PCHANGES. Alles ist in Ordnung, außer wenn ich die Primärschlüsselwerte versuche und poste. Ich möchte, dass in der Spalte primary_key ich die Primärschlüsselwerte Komma getrennt eingeben. Wenn also TableX 3 Primärschlüssel hat, poste ich in PKCHANGES (Spalte primary_key) Wert1, Wert2, Wert3.Dynamische Abfrage mit: neuer Wert

Bisher habe ich nur leite die unten als Ergebnis zu bekommen und nicht die tatsächlichen Werte ": new.pkCol1: new.pkCol2: new.pkCol3"

Mein PL/SQL-Block:

DECLARE 
mySql varchar2(5000); 
myTable varchar2(10) := 'TableX'; 
BEGIN 
    mySql := 'CREATE OR REPLACE TRIGGER ' || 't_1' || ' AFTER INSERT ON ' || myTable || ' 
     FOR EACH ROW 
     DECLARE 
     currentPK varchar2(200); --Contains the current primary key value in the loop 
     result varchar2(200); --Contains the appended string of primary key values 

     --Cursor that contains primaryKeys for table 
     CURSOR pks IS 
     SELECT cols.column_name FROM all_constraints cons, all_cons_columns cols 
     WHERE cons.constraint_type = ''P'' 
     AND cons.constraint_name = cols.constraint_name 
     AND cons.table_name = ' || '''' || myTable || '''' || '; 

     BEGIN 
     --Loop through primary keys, get the value from the trigger, and append the string. 
     for current_pk IN pks LOOP 
      BEGIN 
      currentPK := '':new.'' || current_pk.column_name; 
      result:= result || currentPK; 
     END; 
    END LOOP;' 
    || 
    ' --Insert the appended values into the primary_key column 
     INSERT INTO PKCHANGES(primary_key)' || 
      'VALUES (result);' 
    || ' END;'; 
    dbms_output.put_line(mySql); 
EXECUTE IMMEDIATE mySql; 
END; 

Irgendeine Idee?

Antwort

2

Der Primärschlüssel des TableX muss nicht bei jedem Einsatz abgefragt werden. Es ist stabil und wenn Sie es einmal geändert haben, werden Sie auch den Trigger ändern.

Damit können Sie die Logik aus dem Auslöser herausspringen.

Im ersten Schritt verketten die PK. Ich würde LISTAGG vorziehen, da es den Begrenzer elegant behandelt. Sie erhalten etwas wie :new.COL1||','||:new.COL2||','||:new.COL3

Stellen Sie auch sicher, dass der Tabellenname im richtigen Fall ist (ich nehme Großbuchstaben an; andernfalls müssen Sie den Namen angeben).

Im nächsten Schritt den Trigger erzeugen, die im Grunde nur die INSERT

DECLARE 
mySql varchar2(5000); 
myTable varchar2(10) := 'TableX'; 
result varchar2(200); -- Contains the concatenated string of primary key column names with delimiters, 
         -- e.g. ":new.COL1||','||:new.COL2||','||:new.COL3" 
BEGIN 
     SELECT listagg(':new.'||cols.column_name,'||'',''||') within group (order by position) into result 
     FROM all_constraints cons, all_cons_columns cols 
     WHERE cons.constraint_type = 'P' 
     AND cons.constraint_name = cols.constraint_name 
     AND cons.table_name = upper(myTable); 

    mySql := 'CREATE OR REPLACE TRIGGER ' || 't_1' || ' AFTER INSERT ON ' || myTable || ' 
     FOR EACH ROW 
     BEGIN 
     --Insert the appended values into the primary_key column 
     INSERT INTO PKCHANGES(primary_key)' || 
      'VALUES ('||result||');'  
    || ' END;'; 
    dbms_output.put_line(mySql); 
EXECUTE IMMEDIATE mySql; 
END; 
/

-Test

create table TableX 
(col1 number, 
col2 number, 
col3 number, 
col4 number); 
alter table TableX add (primary key (col1, col2, col3)); 

insert into TableX values (1,2,3,4); 


select * from PKCHANGES; 

PRIMARY_KEY 
----------- 
1,2,3 
+0

Brilliant Dank enthalten :) – Dragonfly