Bazı kritik önemdeki tablolarımızda silinen kayıtları takip etmek isteyebiliriz. Bir anlamda windowstaki çöp kutusu gibi. Bu amaçla aşağıdaki prosedürü yazdım. Bu prosedüre parametreolarak silinen kayıtları takip etmek istediğimiz tablonun adını geçiriyoruz. Prosedür önce silinen kayıtları atacağı tabloyu tablo adının sonuna “__cop” ekleyerek oluşturuyor. Ayrıca silinen kayıtların atılacağı tabloya orjinal tablo yapısından farklı olarak DELETE_USER,DELETE_PC,DELETE_DATE,DELETE_OS_USER kolonlarını ekliyor. Bu kolonlarda isimlerinden anlaşılacağı gibi, kaydı silen kullanıcı adı, silindiği pc ismi,silindiği tarih ve silinen pc nin işletim sistemi kullanıcı adları tutuluyor.

Daha sonra prosedür silme işleminde çalışacak BEFORE DELETE trigger ını oluşturuyor. trigger ın adı tabloadı_rb_trg oluyor.Bundan böyle orjinal tablomuzda silinen her kaydı __cop tablomuzda tutmuş olacağız.

/***********************************************************************/
/* kendisine parametre olarak geçirilen tablo için tablo adının */
/* sonuna __cop ekleyerek cop kutusu tablosu olusturur */
/* daha sonra bu tablodan silme işlemi yapıldığında silinen kayıtı */
/* cop kutusu tablosuna aktaracak olan trigger tablo_adi_tab_rb_trg */
/* formatinda oluşturulur */
/* son güncelleme 17.06.2010 -- metin ergoktas */
/***********************************************************************/

CREATE OR REPLACE PROCEDURE cop_kutusu_olustur_metin(tablo_adi IN VARCHAR2) IS

CURSOR c_tablo IS
SELECT * FROM user_tab_columns WHERE table_name = tablo_adi;

tablo_alan VARCHAR2(4000) := ' ';
tablo_deger VARCHAR2(4000) := ' ';
tum_alanlar VARCHAR2(4000);
nint NUMBER := 0;
table_rec c_tablo%ROWTYPE;
col_number NUMBER;
kolon_vir VARCHAR2(4000);

BEGIN
--silinen kayıtların atılacağı tabloyu olustur
EXECUTE IMMEDIATE 'create table' || ' ' || tablo_adi || '__cop' || ' ' ||
'as select * from ' || ' ' || tablo_adi || ' ' ||
'where 1=2';

EXECUTE IMMEDIATE 'ALTER TABLE' || ' ' || tablo_adi || '__cop' || ' ' ||

'ADD'||' '||
'('||
'DELETE_USER VARCHAR2'||'('||'100'||')'||','||
'DELETE_DATE DATE'||','||
'DELETED_PC VARCHAR2'||'('||'100'||')'||','||
'DELETED_OS_USER VARCHAR2'||'('||'100'||')'||

')';

SELECT COUNT(*)
INTO col_number
FROM user_tab_columns r
WHERE r.TABLE_NAME = tablo_adi;

--bu loop da kolonlar kısmını hazırlıyoruz
FOR table_rec IN c_tablo LOOP
IF nint = 0 THEN
--ilk sutun
tablo_alan := CONCAT(table_rec.column_name, ',');
--son sutun
ELSIF nint = col_number - 1 THEN
tablo_alan := CONCAT(tablo_alan, table_rec.column_name);

ELSE
--diger sutunlar
kolon_vir := CONCAT(table_rec.column_name, ',');
tablo_alan := CONCAT(tablo_alan, kolon_vir);
END IF;
nint := nint + 1;
END LOOP;

tablo_alan := tablo_alan ||','||'DELETE_USER,DELETE_DATE,DELETED_PC,DELETED_OS_USER';

nint := 0;

--bu loop da values kısmını hazırlıyoruz
FOR table_rec IN c_tablo LOOP
IF nint = 0 THEN
--ilk sutun
tablo_deger := CONCAT(':old.' || table_rec.column_name, ',');
--son sutun
ELSIF nint = col_number - 1 THEN
tablo_deger := CONCAT(tablo_deger, ':old.' || table_rec.column_name);
ELSE
--diger sutunlar
kolon_vir := CONCAT(':old.' || table_rec.column_name, ',');
tablo_deger := CONCAT(tablo_deger, kolon_vir);
END IF;
nint := nint + 1;
END LOOP;

tablo_deger := CONCAT(tablo_deger,',sys_context(''USERENV'',''SESSION_USER''),SYSDATE,sys_context(''USERENV'',''TERMINAL''),sys_context(''USERENV'',''OS_USER'')');

-- burda triggerımızı oluşturuyoruz
EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER' || ' ' || tablo_Adi ||
'_rb_trg' || ' ' ||

'BEFORE DELETE on' || ' ' || tablo_adi || ' ' ||
'for each row' || ' ' ||

'DECLARE' || ' ' ||

'BEGIN' || ' ' || 'INSERT INTO' || ' ' || tablo_adi ||
'__cop' || ' ' || '(' || ' ' || tablo_alan || ' ' || ')' || ' ' ||
'VALUES' || '(' || ' ' || tablo_deger || ' ' || ');' || ' ' ||
'END;';

END;
print
Share