需要使用 plpgsql 函数截断表
Posted
技术标签:
【中文标题】需要使用 plpgsql 函数截断表【英文标题】:Need to truncate tables using plpgsql function 【发布时间】:2014-02-21 08:55:28 【问题描述】:我编写了一个 pl/pgsql 函数来截断表。 HIST_CLEANUP_TBL 中有 5 个表名。在 5 个中,有 1 个 table_name 在数据库中不存在。
需要的是:它必须检查所有表。如果表不存在,则将错误写入错误表并截断剩余的表。
但是,当不可用的表进入循环时,函数就会终止。
如何在变量中捕获错误代码和文本,以及如何在不存在 1 个表的情况下继续循环。
我们使用的是 postgresql 8.2
BEGIN
for recordvar in
SELECT 'truncate table ' || TABLE_NAME as SQRY FROM HIST_CLEANUP_TBL
loop
QUERY1 := recordvar.SQRY;
RAISE NOTICE 'QUERY: (%)', QUERY1;
BEGIN
execute QUERY1;
RAISE NOTICE 'QUERY EXECUTED SUCCESSFULLY';
EXCEPTION
WHEN others
THEN
--GET STACKED DIAGNOSTICS
ERR_NUM := SQLSTATE;
ERR_MESG := SQLERRM ;
RAISE NOTICE 'ERROR WHILE EXECUTING THE QUERY : %',ERR_NUM;
insert into Refresh_Error_tbl(sqlerr_code,sqlerr_desc,sql_desc, INSERT_DT,refresh_load_id) values(ERR_NUM,ERR_MESG,QUERY1,current_timestamp,'1');
END;
end loop;
END;
【问题讨论】:
您的异常子句本身是否可能引发异常?例如,如果插入出错?如果异常处理程序中有异常,那么它肯定会中止 这里的问题是它没有进入异常循环。 HIST_CLEANUP_TBL Table_name A B C D E 这里,C 表在数据库中不存在。当 C 出现时,该函数正在为表 A 和 B 运行,它终止函数并且表 D 和 E 不会被截断。所以需要将表C写入错误表并处理D和E 【参考方案1】:错误的原因必须在其他地方。以下代码工作正常:
CREATE TABLE hist_cleanup (
table_name text
);
CREATE TABLE table_a();
CREATE TABLE table_b();
-- table_c missing
CREATE TABLE table_d();
CREATE TABLE table_e();
INSERT INTO hist_cleanup
VALUES
('table_a')
, ('table_b')
, ('table_c')
, ('table_d')
, ('table_e');
CREATE TABLE refresh_error (
sqlerr_code text
, sqlerr_desc text
, sql_desc text
, insert_dt timestamp
, refresh_load_id int
);
CREATE OR REPLACE FUNCTION cleanup()
RETURNS VOID AS $$
DECLARE
_rec record;
_query text;
BEGIN
FOR _rec IN (
SELECT table_name
FROM hist_cleanup
) LOOP
_query := 'TRUNCATE TABLE ' || _rec.table_name;
RAISE NOTICE 'QUERY: (%)', _query;
BEGIN
EXECUTE _query;
RAISE NOTICE 'QUERY EXECUTED SUCCESSFULLY';
EXCEPTION
WHEN OTHERS
THEN
RAISE NOTICE 'ERROR WHILE EXECUTING THE QUERY: % %', SQLSTATE, SQLERRM;
INSERT INTO refresh_error (
sqlerr_code
, sqlerr_desc
, sql_desc
, insert_dt
, refresh_load_id )
VALUES (
SQLSTATE
, SQLERRM
, _query
, CURRENT_TIMESTAMP
, '1'
);
END;
END LOOP;
RETURN;
END $$ LANGUAGE plpgsql;
SELECT cleanup();
输出:
NOTICE: QUERY: (TRUNCATE TABLE table_a)
NOTICE: QUERY EXECUTED SUCCESSFULLY
NOTICE: QUERY: (TRUNCATE TABLE table_b)
NOTICE: QUERY EXECUTED SUCCESSFULLY
NOTICE: QUERY: (TRUNCATE TABLE table_c)
NOTICE: ERROR WHILE EXECUTING THE QUERY: 42P01 relation "table_c" does not exist
NOTICE: QUERY: (TRUNCATE TABLE table_d)
NOTICE: QUERY EXECUTED SUCCESSFULLY
NOTICE: QUERY: (TRUNCATE TABLE table_e)
NOTICE: QUERY EXECUTED SUCCESSFULLY
【讨论】:
感谢您的解决方案,我将重新编码功能 嗨 Tomasz,我根据您的建议重新编写了函数,它运行良好。问题是我无法将 SQLSTATE 和 SQLERRM 存储到变量中。每当我尝试存储它时,如果我们忽略它就会抛出错误,它运行良好 很高兴听到这个消息。至于用于存储 SQLSTATE 和 SQLERRM 变量值的变量,可能它们没有被声明或被声明为不正确的类型?不管怎样,我想你可以接受我的回答。 谢谢!我的问题很相似,我需要在 for 循环中截断 7 个表并检查它是否成功。将 FK 放入表中时,脚本会引发错误。再次感谢您!以上是关于需要使用 plpgsql 函数截断表的主要内容,如果未能解决你的问题,请参考以下文章
无法从 plpgsql 函数中的动态命名临时表运行“选择进入”