web-dev-qa-db-ja.com

PL / pgSQL関数作成のバグ

この質問がここに適しているのか、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';

次のエラーが発生します。

ERROR: syntax at or near "$1"    LINE1:   $1
QUERY $1
CONTEXT: SQL statement in PL/PgSQL function "truncate_tables" near line 5

私はPostgresとPL/pgSQLを初めて使用しますが、このエラーメッセージの意味がわかりません。

3

明示カーソルを省略してみてください。

begin;
set role dba;
create role stack;
grant stack to dba;
create schema authorization stack;
set role stack;
--
create table foo(id serial);
insert into foo default values;
create or replace function truncate_tables(username in varchar) returns void as $$
declare r record;
begin 
    for r in (select tablename from pg_tables where tableowner = username) loop
        execute 'truncate table ' || quote_ident(r.tablename) || ' cascade';
    end loop;
end;
$$ language 'plpgsql';
--
select truncate_tables('stack');
select * from foo;
/*
 id
----
(0 rows)
*/
--
rollback;

この特定の例はもっと簡単です。
一度に複数のテーブルを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;
_

コール:

_SELECT truncate_tables('postgres');
_

string_agg()にはPostgreSQL9.0以降が必要です。
8.4では、次のように置き換えることができます。

_array-to_string(array_agg(quote_ident(t.tablename)), ', ')
_

V8.3の場合は、独自の集計関数を作成します。かなり単純ですが、ループソリューションよりも単純ではありません。


PostgreSQL 9.1で多くのテーブルを一度に削除または切り捨てると、パフォーマンスが低下します。今後のバージョン9.2でのこれの修正。引用します リリースノート

多くのテーブルが削除または切り捨てられている場合のチェックポインターのfsync-requestキューのパフォーマンスを改善します(Tom Lane)

pgsql-hackersの関連スレッド

@ CraigのSOでの関連回答 これを発見するのに役立ちました。

4