PL/pgSQL 函数创建中的错误

Ste*_*and 3 postgresql dynamic-sql cursors plpgsql postgresql-8.3

我不知道这个问题是否更适合这里或 SO ...

这是我想启动的脚本(该函数的代码是从 SO 上的一个问题复制的):

\c mydb

create or replace function truncate_tables(username in varchar) returns void as $$
declare
    stmt RECORD;
    statements cursor for select tablename from pg_tables where tableowner = username;
begin 
    for stmt in statements loop
        execute 'truncate table ' || quote_ident(stmt.tablename) || ' CASCADE ;';
    end loop;
end;
$$ language 'plpgsql';
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

ERROR: syntax at or near "$1"    LINE1:   $1
QUERY $1
CONTEXT: SQL statement in PL/PgSQL function "truncate_tables" near line 5
Run Code Online (Sandbox Code Playgroud)

我是 Postgres 和 PL/pgSQL 的新手,不知道此错误消息的含义。

Erw*_*ter 5

这个特定的例子可以更简单。
您可以同时使用TRUNCATE多个表。聚合所有表名并执行单个语句:

CREATE OR REPLACE FUNCTION truncate_tables(_username text)
  RETURNS void AS
$func$
BEGIN
   EXECUTE (
      SELECT 'TRUNCATE TABLE '
             || string_agg(quote_ident(t.tablename), ', ')
             || ' CASCADE;'
      FROM   pg_tables t
      WHERE  t.tableowner = _username
      AND    t.schemaname = 'public'
   );
END;
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

称呼:

SELECT truncate_tables('postgres');
Run Code Online (Sandbox Code Playgroud)

string_agg()需要 PostgreSQL 9.0或更高版本。
在 8.4 中,您可以替换:

array-to_string(array_agg(quote_ident(t.tablename)), ', ')
Run Code Online (Sandbox Code Playgroud)

对于 v8.3,您将编写自己的聚合函数 - 相当简单,但不再比循环解决方案简单。


在 PostgreSQL 9.1 中一次删除或截断多个表时,性能会下降。在即将发布的 9.2 版中对此进行了修复。我引用发行说明

当许多表被删除或截断时,提高检查点的 fsync 请求队列的性能 (Tom Lane)

pgsql-hackers 上的相关线程。

@Craig 在 SO 上的相关回答帮助我发现了这一点。