在数组中传递表名称

时间:2014-05-18 15:51:29

标签: postgresql plpgsql dynamic-sql sql-delete

我需要在一组表上执行相同的删除或清除操作(基于几个条件)。为此,我试图将数组中的表名传递给函数。我不确定我做得对。或者有更好的方法吗?

我只是粘贴一个示例,这不是我写的实际功能,但基本与下面相同:

CREATE OR REPLACE FUNCTION test (tablename text[]) RETURNS int AS
$func$
BEGIN

execute 'delete  * from  '||tablename;
  RETURN 1;
END
$func$ LANGUAGE plpgsql;

但是当我调用该函数时,我得到一个错误:

select test( {'rajeev1'} );

ERROR:  syntax error at or near "{"
LINE 10: select test( {'rajeev1'} );
                      ^
********** Error **********

ERROR: syntax error at or near "{"
SQL state: 42601
Character: 179

3 个答案:

答案 0 :(得分:2)

数组语法

'{rajeev1, rajeev2}'ARRAY['rajeev1', 'rajeev2']Read the manual.

TRUNCATE

由于您要从表中删除所有行,请考虑使用TRUNCATEPer documentation:

  

提示: TRUNCATE是一个提供更快速的PostgreSQL扩展   从表中删除所有行的机制。

务必研究细节。如果TRUNCATE适合您,则整个操作变得非常简单,因为该命令接受多个表:

TRUNCATE rajeev1, rajeev2, rajeev3, .. 

动态DELETE

否则你需要像你已经尝试过的动态SQL。可怕的缺失细节:您完全接受 SQL注入和灾难性语法错误。将format() %I (不是%s一起使用来清理表名等标识符。或者,更好的是在这种特殊情况下,使用{{1}的数组而是参数:

regclass

呼叫:

CREATE OR REPLACE FUNCTION f_del_all(_tbls regclass)
  RETURNS void AS
$func$
DECLARE
   _tbl regclass;
BEGIN
   FOREACH _tbl IN ARRAY _tbls LOOP
      EXECUTE format('DELETE * FROM %s', _tbl);
   END LOOP;
END
$func$ LANGUAGE plpgsql;

这里的解释:
Table name as a PostgreSQL function parameter

答案 1 :(得分:1)

您在函数调用中使用了错误的text array constant语法。但即使它是对的,你的功能也不正确。

如果你的函数有text array作为参数,你应该循环遍历数组以执行每个元素的查询。

CREATE OR REPLACE FUNCTION test (tablenames text[]) RETURNS int AS
$func$
DECLARE
    tablename text;
BEGIN
    FOREACH tablename IN ARRAY tablenames LOOP
        EXECUTE FORMAT('delete  * from  %s', tablename);
    END LOOP;
    RETURN 1;
END
$func$ LANGUAGE plpgsql;

然后,您可以同时为多个表调用该函数,而不仅仅是一个。

SELECT test( '{rajeev1, rajeev2}' );

如果您不需要此功能,只需将参数类型更改为text

CREATE OR REPLACE FUNCTION test (tablename text) RETURNS int AS
$func$
BEGIN
    EXECUTE format('delete  * from  %s', tablename);
    RETURN 1;
END
$func$ LANGUAGE plpgsql;

SELECT test('rajeev1');

我建议使用the format function


如果要对由类似名称标识的一组表执行函数(比如purge_this_one_table(tablename)),可以使用以下结构:

create or replace function purge_all_these_tables(mask text)
returns void language plpgsql 
as $$
declare
    tabname text;
begin
    for tabname in
        select relname 
        from pg_class
        where relkind = 'r' and relname like mask
    loop
        execute format(
            'purge_this_one_table(%s)',
            tabname);
    end loop;
end $$;

select purge_all_these_tables('agg_weekly_%');

答案 2 :(得分:0)

应该是:

select test('{rajeev1}');