【发布时间】:2019-04-08 22:02:01
【问题描述】:
创建一个过程,将数据从我的 table1 插入到我的 table2 并在插入后将其删除,或者如果 table2 已达到其限制,那么我将创建一个新的备份表。
我有两张桌子sii_bck_cfg_tab 和sii_bck_tab
在cfg_tab 上,我有一个表名列表,其中包含几列(id,name_tab, prefix_tab, created_on , keep_days, max_rows_bck)
prefix_tab- 当我需要创建一个新的备份表时,我在其中获取前缀
keep_days - 我想保留表格数据的天数
max_rows- 在我创建一个新表之前添加到备份表中的行数。
在我的bck_tab 我有以下列(id, tab_name, id_cfg_bck, created_on, close_dt)
tab_name-创建的备份表的名称
id_cfg_bck - 来自 cfg_bck 的 FK
close_dt- 备份表达到极限并“关闭”的日期
enter code here
CREATE OR REPLACE PROCEDURE LIMPAR_TAB_proc
IS
stmt VARCHAR2(1000);
stmt_ins_bck VARCHAR2(1000);
n_tab sii_bck_cfg_tab.nome_tab%type;
prefix sii_bck_cfg_tab.pref_tab_bck%type;
max_reg sii_bck_cfg_tab.max_reg_bck%type;
id_fk sii_bck_cfg_tab.id_bck_cfg_tab%type;
dt_criado sii_bck_cfg_tab.criado_em%TYPE;
id_fk2 sii_bck_tab.id_bck_cfg_tab%type;
dt_fec sii_bck_tab.dt_fecho%TYPE;
n_tab2 sii_bck_tab.nome_tab%type;
stmt_ins VARCHAR2(500);
id_seq VARCHAR2(500);
num_rows VARCHAR2(500);
stmt_up VARCHAR2(500);
stmt_del VARCHAR2(500);
CURSOR c1 IS
SELECT ID_BCK_CFG_TAB,Nome_tab, pref_tab_bck, max_reg_bck, criado_em FROM sii_bck_cfg_tab WHERE desativado_em IS NULL OR desativado_em<=SYSDATE AND n_dias_reten>0 ORDER BY criado_em;
CURSOR c2 IS
SELECT sii_bck_tab.ID_BCK_CFG_TAB , sii_bck_tab.nome_tab from sii_bck_tab,sii_bck_cfg_tab WHERE sii_bck_cfg_tab.id_bck_cfg_tab=sii_bck_tab.id_bck_cfg_tab and dt_fecho is NULL;
BEGIN
OPEN c1;
LOOP
--inserir os registos que cumprem a restrição da data e dos dias de retenção
FETCH c1 INTO id_fk,n_tab,prefix,max_reg, dt_criado;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Nome Tabela c1 = ' || id_fk ||' '|| n_tab ||' '|| prefix ||' '|| max_reg);
OPEN c2;
LOOP
FETCH c2 INTO id_fk2, n_tab2;
--DBMS_OUTPUT.PUT_LINE('chave aqui c2= ' || id_fk2 || n_tab2);
--registos de tabelas que não estão fechadas
IF c2%FOUND AND id_fk=id_fk2 THEN
BEGIN
SAVEPOINT start_transaction;
stmt_ins:= 'INSERT all into ' || n_tab2 || ' SELECT * FROM ' || n_tab || ' where ' || dt_criado || '<' || SYSDATE;
--falta verificar se foi bem sucedido e apagar da original
-- EXECUTE IMMEDIATE stmt_ins;
dbms_output.put_line('value '||SQL%ROWCOUNT);
DBMS_OUTPUT.PUT_LINE(stmt_ins);
siima_logs_bck.INSE_LOG(1,'TESTE INSERIR','INS_LOGS','2', 'testes insert log');
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO start_transaction;
END;
stmt_del:= 'DELETE FROM ' || n_tab || ' WHERE (SELECT *
FROM ' || n_tab2 || ' WHERE criado_em' ||'<'|| sysdate ;
DBMS_OUTPUT.PUT_LINE(stmt_del);
siima_logs_bck.INSE_LOG(1,'TESTE ELIMINAR','INS_LOGS','2', 'testes delete log');
ELSE IF c2%NOTFOUND THEN
stmt:= 'create table ' || prefix || SII_BCK_TAB_ID_SEQ.nextval ||
' AS SELECT * FROM '|| n_tab || ' WHERE 1=0';
-- DBMS_OUTPUT.PUT_LINE(stmt);
--EXECUTE IMMEDIATE stmt;
id_seq:= prefix||SII_BCK_TAB_ID_SEQ.CURRVAL;
-- DBMS_OUTPUT.PUT_LINE(id_seq);
stmt_ins_bck:= 'insert into sii_bck_tab(nome_tab,id_bck_cfg_tab) VALUES ' || '(' || id_seq || ',' || id_fk || ')';
-- DBMS_OUTPUT.PUT_LINE(stmt_ins_bck);
--EXECUTE IMMEDIATE stmt_ins_bck;
EXIT WHEN c2%NOTFOUND;
END IF;
END IF;
--vefificar numero de registos e update
EXECUTE IMMEDIATE 'SELECT Count (*) from ' ||n_tab INTO num_rows;
-- DBMS_OUTPUT.PUT_LINE(num_rows);
IF num_rows>max_reg THEN
stmt_up:='update ' || n_tab || ' set ' || dt_fec || '=' || sysdate;
DBMS_OUTPUT.PUT_LINE(stmt_up);
--EXECUTE IMMEDIATE stmt_up;
END IF;
END LOOP;
CLOSE c2;
END LOOP;
CLOSE c1;
end;
目前我遇到的问题是插入动态表,如果我已成功插入备份表,则删除。
stmt_ins:= 'INSERT all into ' || n_tab2 || ' SELECT * FROM ' || n_tab || ' where ' || dt_criado || '<' || SYSDATE;
--这个 stmt 可以在没有 where 子句的情况下工作,但我需要它工作,这样我才能按日期过滤数据。
我想确保我已将我的数据正确插入到我的备份表中,然后从我的主表中删除。
stmt_del:= 'DELETE FROM ' || n_tab || ' WHERE (SELECT *
FROM ' || n_tab2 || ' WHERE criado_em' ||'<'|| sysdate ;
在我的删除语句中,criado_em 列有同样的问题。
这是一个在作业中运行的过程,每天将数据从主表传递到备份表,并在主表上保留一定数量的数据(例如最近 30 天)
感谢您的帮助
【问题讨论】:
-
那么具体的错误是什么,在哪里?
-
一定要这样吗?不能用分区吗? (它们会更容易维护,因为您可以根据需要删除/交换分区。)
-
插入错误,我不能使用 where 子句。可悲的是我不能使用分区:(
-
我得到的错误是 ORA-00920 无效操作符,我还想验证在我从原始表中删除之前是否插入了所有数据
标签: sql oracle plsql procedure