需要使用 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 函数中获取表的关键字段?

无法从 plpgsql 函数中的动态命名临时表运行“选择进入”

如何使用 plpgsql 函数插入数据?

Plpgsql - 多次迭代记录集

Postgresql - 从 plpgsql 函数返回记录 []

如何在执行 SELECT... 语句时将表列传递给 plpgsql 函数