Advertisement
Guest User

Untitled

a guest
May 23rd, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PL/SQL 8.32 KB | None | 0 0
  1. CREATE OR REPLACE TRIGGER create_cascade_update
  2.     AFTER CREATE ON SCHEMA
  3. DECLARE
  4.  
  5.     TYPE strings IS TABLE OF VARCHAR2(64);
  6.     TYPE fks     IS TABLE OF strings INDEX BY PLS_INTEGER;
  7.    
  8.     v_type VARCHAR2(64) := UPPER(SYS.DICTIONARY_OBJ_TYPE);
  9.     v_name VARCHAR2(64) := UPPER(SYS.DICTIONARY_OBJ_NAME);
  10.    
  11.     pk_cols strings;
  12.     ot_cols strings;
  13.     pk_list VARCHAR2(4000) := '';
  14.     ot_list VARCHAR2(4000) := '';
  15.    
  16.     dep_tables strings;
  17.     dep_tab_fk fks;
  18.    
  19.     trigger_txt VARCHAR2(4000) := '';
  20.    
  21.     PROCEDURE add(txt VARCHAR2) IS
  22.     BEGIN
  23.         trigger_txt := trigger_txt || txt || CHR(10);
  24.     END;
  25.    
  26.     PROCEDURE fill_pks IS
  27.     BEGIN
  28.         SELECT column_name
  29.         BULK COLLECT INTO pk_cols
  30.         FROM user_cons_columns
  31.         WHERE constraint_name IN
  32.             (SELECT constraint_name
  33.              FROM user_constraints
  34.              WHERE constraint_type = 'P' AND
  35.                    table_name = v_name)
  36.         ORDER BY position;
  37.        
  38.         FOR i IN 1..pk_cols.COUNT LOOP
  39.             pk_list := pk_list || pk_cols(i) || ',';
  40.         END LOOP;
  41.         pk_list := TRIM(BOTH ',' FROM pk_list);
  42.     END;
  43.    
  44.     PROCEDURE fill_cols IS
  45.     BEGIN
  46.         SELECT column_name
  47.         BULK COLLECT INTO ot_cols
  48.         FROM user_tab_columns
  49.         WHERE table_name = v_name;
  50.        
  51.         ot_cols := ot_cols MULTISET EXCEPT pk_cols;
  52.        
  53.         FOR i IN 1..ot_cols.COUNT LOOP
  54.             ot_list := ot_list || ot_cols(i) || ',';
  55.         END LOOP;
  56.         ot_list := ','||TRIM(BOTH ',' FROM ot_list);
  57.     END;
  58.    
  59.     PROCEDURE fill_dep_tab IS
  60.     BEGIN
  61.         SELECT DISTINCT table_name
  62.         BULK COLLECT INTO dep_tables
  63.         FROM user_cons_columns
  64.         WHERE constraint_name IN
  65.         (SELECT constraint_name
  66.         FROM user_constraints
  67.         WHERE r_constraint_name =
  68.             (SELECT constraint_name
  69.              FROM user_constraints
  70.              WHERE constraint_type = 'P' AND
  71.                    table_name = v_name));
  72.     END;
  73.    
  74.     PROCEDURE fill_fks IS
  75.     BEGIN
  76.         FOR i IN 1..dep_tables.COUNT LOOP
  77.             SELECT column_name
  78.             BULK COLLECT INTO dep_tab_fk(i)
  79.             FROM user_cons_columns
  80.             WHERE constraint_name IN
  81.             (SELECT constraint_name
  82.             FROM user_constraints
  83.             WHERE r_constraint_name =
  84.                 (SELECT constraint_name
  85.                  FROM user_constraints
  86.                  WHERE constraint_type = 'P' AND
  87.                        table_name = v_name))
  88.             ORDER BY POSITION;
  89.         END LOOP;
  90.     END;
  91. BEGIN
  92.     IF v_type = 'TABLE' THEN
  93.        
  94.         fill_pks;
  95.         fill_cols;
  96.        
  97.         IF pk_cols.COUNT > 0 THEN
  98.        
  99.             fill_dep_tab;
  100.            
  101.             IF dep_tables.COUNT > 0 THEN
  102.            
  103.                 fill_fks;
  104.        
  105.                 add('CREATE OR REPLACE TRIGGER cascade_update_'||v_name);
  106.                 add('FOR UPDATE OF '||pk_list||' ON '||v_name);
  107.                 add('COMPOUND TRIGGER');
  108.                
  109.                 add('idx PLS_INTEGER := 1;');
  110.                
  111.                 FOR i IN 1..pk_cols.COUNT LOOP
  112.                     add('TYPE pk'||i||' IS TABLE OF '||v_name||'.'||pk_cols(i)||'%TYPE INDEX BY PLS_INTEGER;');
  113.                    
  114.                     add('new_pk'||i||' pk'||i||';');
  115.                     add('old_pk'||i||' pk'||i||';');
  116.                     add('emp_pk'||i||' pk'||i||';');
  117.                 END LOOP;
  118.                
  119.                 add('BEFORE STATEMENT IS');
  120.                 add('BEGIN');
  121.                 FOR i IN 1..pk_cols.COUNT LOOP
  122.                     add('idx'||i||' := 1;');
  123.                     add('new_pk'||i||' := emp_pk'||i||';');
  124.                     add('old_pk'||i||' := emp_pk'||i||';');
  125.                 END LOOP;
  126.                 add('END BEFORE STATEMENT;');
  127.                
  128.                 add('BEFORE EACH ROW IS');
  129.                 add('BEGIN');
  130.                 add('IF (');
  131.                 FOR i IN 1..pk_cols.COUNT LOOP
  132.                     add(':NEW.'||pk_cols(i)||' <> :OLD.'||pk_cols(i)||' ');
  133.                     IF i <> pk_cols.COUNT THEN
  134.                         add('OR ');
  135.                     END IF;
  136.                 END LOOP;
  137.                 add(') THEN');
  138.                     FOR i IN 1..pk_cols.COUNT LOOP
  139.                         add('new_pk(idx) := :NEW.'||pk_cols(i)||';');
  140.                         add('old_pk(idx) := :OLD.'||pk_cols(i)||';');
  141.                         add(':NEW.'||pk_cols(i)||' := :OLD.'||pk_cols(i)||';');
  142.                     END LOOP;
  143.                     add('idx := idx + 1;');
  144.                 add('END IF;');
  145.                 add('END BEFORE EACH ROW;');
  146.                
  147.                 add('AFTER STATEMENT IS');
  148.                 add('BEGIN');
  149.                     add('FOR i IN 1..idx-1 LOOP');
  150.                    
  151.                         add('INSERT INTO '||v_name||'('||pk_list||','||ot_list||')');
  152.                         add('SELECT ');
  153.                         FOR i IN 1..pk_cols.COUNT LOOP
  154.                             add('new_pk'||i||'(i)');
  155.                             IF i <> pk_cols.COUNT THEN add(','); END IF;
  156.                         END LOOP;
  157.                         IF ot_list.COUNT > 0 THEN
  158.                             add(','||ot_list);
  159.                         END IF;
  160.                         add('FROM '||v_name);
  161.                         add('WHERE ('||pk_list||') = (SELECT ');
  162.                         FOR i IN 1..pk_cols.COUNT LOOP
  163.                             IF i <> pk_cols.COUNT THEN
  164.                                 add('old_pk'||i||'(i), ');
  165.                             ELSE
  166.                                 add('old_pk'||i||'(i) FROM DUAL);');
  167.                             END IF;
  168.                         END LOOP;
  169.                        
  170.                         FOR i IN 1..dept_tables.COUNT LOOP
  171.                             add('UPDATE '||dept_tables(i));
  172.                             add('SET (');
  173.                             FOR j IN 1..dep_tab_fk(i).COUNT LOOP
  174.                                 IF j <> dep_tab_fk(i).COUNT THEN
  175.                                     add(dep_tab_fk(i)(j)||',');
  176.                                 ELSE
  177.                                     add(dep_tab_fk(i)(j)||')');
  178.                                 END IF;
  179.                             END LOOP;
  180.                             add(' = (SELECT ');
  181.                             FOR j IN 1..pk_cols.COUNT LOOP
  182.                                 IF j <> pk_cols.COUNT THEN
  183.                                     add('new_pk'||i||'(i),');
  184.                                 ELSE
  185.                                     add('new_pk'||i||'(i)) FROM DUAL) WHERE (');
  186.                                 END IF;
  187.                             END LOOP;
  188.                             FOR j IN 1..dep_tab_fk(i).COUNT LOOP
  189.                                 IF j <> dep_tab_fk(i).COUNT THEN
  190.                                     add(dep_tab_fk(i)(j)||',');
  191.                                 ELSE
  192.                                     add(dep_tab_fk(i)(j)||')');
  193.                                 END IF;
  194.                             END LOOP;
  195.                             add(' = (SELECT ');
  196.                             FOR j IN 1..pk_cols.COUNT LOOP
  197.                                 IF j <> pk_cols.COUNT THEN
  198.                                     add('old_pk'||i||'(i),');
  199.                                 ELSE
  200.                                     add('old_pk'||i||'(i)) FROM DUAL);');
  201.                                 END IF;
  202.                             END LOOP;
  203.                         END LOOP;
  204.                        
  205.                         add('DELETE '||v_name);
  206.                         add('WHERE ('||pk_list||') = (SELECT ');
  207.                         FOR j IN 1..pk_cols.COUNT LOOP
  208.                             IF j <> pk_cols.COUNT THEN
  209.                                 add('old_pk'||i||'(i),');
  210.                             ELSE
  211.                                 add('old_pk'||i||'(i) FROM DUAL);');
  212.                             END IF;
  213.                         END LOOP;
  214.                        
  215.                        
  216.                     add('END LOOP;');
  217.                 add('END AFTER STATEMENT;');
  218.             add('END cascade_update_'||v_name||';');
  219.             END IF;
  220.         END IF;
  221.     END IF;
  222. END create_cascade_update;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement