1

私はPostgreSQLサーバー9.0.4を使用しています。1.新しいスキーマを作成し、2.そのスキーマの下にテーブルを作成し、3.そのテーブルにデータを挿入します。同じEXECUTEで失敗します。私が試したら

CREATE OR REPLACE FUNCTION pg_temp.test( ) 
    RETURNS void LANGUAGE plpgsql AS 
$BODY$  
BEGIN
    EXECUTE 'CREATE SCHEMA test; CREATE TABLE test.t (id integer ); 
INSERT INTO test.t (id) VALUES (0);';
END;
$BODY$;

select pg_temp.test( );

次のエラーで失敗します。

ERROR:  schema "test" does not exist
LINE 1: ...t; CREATE TABLE test.t (id integer ); INSERT INTO test.t (id...
                                                             ^

ただし、同じトランザクションで 2 つの EXECUTE を使用すると、同じことが機能します。

CREATE OR REPLACE FUNCTION pg_temp.test( ) 
    RETURNS void LANGUAGE plpgsql AS 
$BODY$  
BEGIN
    EXECUTE 'CREATE SCHEMA test; CREATE TABLE test.t (id integer );';
    EXECUTE 'INSERT INTO test.t (id) VALUES (0);';
END;
$BODY$;

両者の違いが理解できません。誰かがここで私を助けてくれれば幸いです。

ありがとう。

4

3 に答える 3

3

マルチステートメントをトランザクションと誤って同一視しています。

関数全体が単一のトランザクション内で実行されます。何をするにしても、1 回のトランザクションで完了します。PL/PgSQL 関数内で自律的にコミットまたはロールバックするオプションはありません (いずれにせよ、Pg 9.3 以前では、これを読んで新しいバージョンを使用している場合は確認してください)。

複数ステートメントは、一般的には良い考えではありません。解析時に以前のステートメントがまだ実行されていないため、DDL が含まれている場合は 2 倍になります。

EXECUTE2 つのステートメントを使用するだけです。ここでマルチステートメントを使用する利点はありません。

(ちなみに、あなたは PostgreSQL 9.0.4 を使用しています。早急にアップグレードしてください。いくつかの主要なバグ修正と、お使いのバージョンの重大なセキュリティ修正があります。9.0.13 へのアップグレードは安全です。バージョン ポリシーを参照してください。)

于 2013-08-29T23:22:06.027 に答える
1

クレイグの答えはかなり近いです。postgresqlメーリングリストへの投稿への回答で、さらに詳細を入手しました。これを見る

要約する、

  1. 実行される文字列内のすべてのサブステートメントは、実行前に解析されます。したがって、その時点でスキーマが存在しないため、INSERT の解析は失敗します。
  2. ユーティリティ ステートメントである CREATE TABLE は厳密には解析されず、正常に動作します。ただし、この動作は実装固有であり、リリースごとに変わる可能性があります。

さらに遠く、

1 つのクエリ文字列で複数のステートメントを実行しようとすることは、特に DDL の場合は避けるのが最善です。

于 2013-09-01T04:21:34.960 に答える