我需要在一组表上执行相同的删除或清除操作(基于几个条件)。为此,我试图将数组中的表名传递给函数。我不确定我做得对。或者有更好的方法吗?
我只是粘贴一个示例,这不是我写的实际功能,但基本与下面相同:
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
答案 0 :(得分:2)
'{rajeev1, rajeev2}'
或ARRAY['rajeev1', 'rajeev2']
。 Read the manual.
TRUNCATE
由于您要从表中删除所有行,请考虑使用TRUNCATE
。 Per 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;
答案 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}');