Reputation: 6404
I'm trying to implement an undo and logging feature for my project.
When a user deletes a row from a table with the DELETE_ROW procedure i select all values from that row and insert it into my row_history table by serializing row values as xml with LOG_DELETED_ROW procedure, then i delete row from its original table.
Serializing with built-in functions of Oracle was easy but i couldn't find a way to deserialize the rowdata and insert it back to own table.
Is there any way to store that deleted row into another table and restore it when needed?
Delete Procedure:
create or replace procedure DELETE_ROW(tableName varchar2, userId varchar2, columnName varchar2, columnValue number) is
begin
log_deleted_row(tableName, userId, columnName, columnValue);
execute immediate 'delete from ' || tableName || ' where ' || columnName || ' = ' || columnValue;
end DELETE_ROW;
Logging Procedure:
create or replace procedure LOG_DELETED_ROW(tableName varchar2, userId varchar2, columnName varchar2, columnValue number) is
tableId number;
begin
SELECT ID into tableId FROM TABLES WHERE NAME = tableName;
execute immediate
'INSERT INTO ROW_HISTORY(TABLE_ID,ROW_ID,ROW_DATA)
SELECT
'|| tableId ||',
'|| columnValue ||',
to_clob(
DBMS_XMLGEN.getxmltype(
''SELECT * FROM ' || tableName || ' where ' || columnName || ' = ' || columnValue || '''
)
)FROM DUAL';
end LOG_DELETED_ROW;
Row History Table:
create table ROW_HISTORY
(
ID NUMBER not null,
TABLE_ID NUMBER not null,
ROW_ID NUMBER not null,
ROW_DATA CLOB not null
)
Upvotes: 1
Views: 583
Reputation: 316
DBMS_XMLSAVE seems to be the thing you need.Here is a procedure which should do what you need to do.
CREATE OR REPLACE PROCEDURE insert_xml_data(p_table IN VARCHAR2, xml_data IN CLOB) IS
t_context DBMS_XMLSAVE.CTXTYPE;
t_rows NUMBER;
BEGIN
t_context := DBMS_XMLSAVE.NEWCONTEXT(p_table);
t_rows := DBMS_XMLSAVE.INSERTXML(t_context,xml_data);
DBMS_XMLSAVE.CLOSECONTEXT(t_context);
END;
/
Upvotes: 2
Reputation: 10931
I believe you could use DBMS_SQL package here - it will allow you to reconstruct insert statement knowing table name and columns.
Another, more complicated, way would be to insantiate LCR$_ROW_RECORD object and then run its EXECUTE member - it will perform actual insert.
Upvotes: 0