8

Firebird データベースのストアド プロシージャに一時テーブルを作成しようとしています。

私のストアドプロシージャのリスト:

SET TERM ^ ;

CREATE PROCEDURE initNATIONALHEALTHFUNDS
 
AS BEGIN

  CREATE GLOBAL TEMPORARY TABLE temp_FUNDS 
  (
    NATIONALHEALTHFUNDID Integer NOT NULL,
    NAME Varchar(128) NOT NULL,
    CODE Integer NOT NULL
  )
  ON COMMIT PRESERVE ROWS;
  commit;
  
 INSERT INTO tempFUNDS (NATIONALHEALTHFUNDID, CODE, NAME)  VALUES ( 01 ,01 , 'Some Foundation');

    
  MERGE INTO NATIONALHEALTHFUNDS  AS target 
   USING tempFUNDS AS source 
   ON target.NATIONALHEALTHFUNDID = source.NATIONALHEALTHFUNDID
   WHEN NOT MATCHED THEN 
    INSERT (NATIONALHEALTHFUNDID, CODE, NAME) VALUES (source.NATIONALHEALTHFUNDID, source.CODE, source.NAME);
    
  drop  TABLE tempFUNDS;
END^

SET TERM ; ^

このプロシージャを作成しようとするたびに、エラーが発生します:

    Engine Code    : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 7, column 3
CREATE


Total execution time: 0.015s

私が間違っていることは何ですか?Firebird 3.0 RC を使用しています

4

3 に答える 3

5

Firebird では、ストアド プロシージャ内で DDL を使用することは許可されていないため、CREATEステートメントは PSQL では許可されていません。lad2025の回答に示されているように、を使用してこの制限を回避できますEXECUTE STATEMENT

ただし、グローバル一時テーブルの背後にある考え方は、一度作成すると、後で使用できるように存在し続けるというものです。データは、データを作成した接続にのみ表示され、グローバル一時テーブルのタイプに応じて、トランザクションのコミット ( ON COMMIT DELETE ROWS) または接続の終了 ( )後にデータが削除されます。ON COMMIT PRESERVE ROWS

Firebird 3.0 言語リファレンスから:

グローバル一時テーブルには永続的なメタデータがありますが、その内容はトランザクション バインド (既定) または接続バインドです。すべてのトランザクションまたは接続には、他のすべてから分離された GTT の独自のプライベート インスタンスがあります。インスタンスは、GTT が参照されている場合にのみ作成されます。それらは、トランザクションの終了時または切断時に破棄されます。

そのため、ストアド プロシージャ内にグローバル一時テーブルを作成しようとする代わりに、最初に作成してから、定義済みの GTTを使用するストアド プロシージャを作成します。

于 2015-11-28T17:18:04.507 に答える
0

上記の他の正解について詳しく説明するために、次のようなより大きなセットに対してクエリを実行する必要があるデータのパラメーター化されたサブセットがある場合など、主にパフォーマンスの問題のために一時テーブルを使用します。

select * from MAIN_TABLE
   where MAIN_TABLE.ID in (select ID from GTT$IDS)

ここで、GTT$IDS には ID のサブセットが取り込まれます。

非常に複雑な手順では、複数の一時テーブルを使用する必要がある場合があるため、次のようにメタデータ内 (もちろん、PSQL ステートメントの外) にそれらを作成します。

create global temporary table GTT$IDS_1 (INT1 integer, INT2 integer);
create index IDX_GTT$IDS_11 on GTT$IDS_1 (INT1);
create index IDX_GTT$IDS_12 on GTT$IDS_1 (INT2);

create global temporary table GTT$IDS_2
...

create global temporary table GTT$IDS_3
...

これを行うことは、一部の高度な SQL 担当者にとっては単純かもしれませんが、私にとっては最も理にかなっています (私の dBase/VFP 時代からの手法を引き継いでいます)。

'PLAN' 句の使用方法 (または正しく機能させる方法) を学ぶのに時間をかけたことがないので、基本的にはこの手法を使用して、遅いクエリを取得したときにコードを介して PLAN を生成します (それが理にかなっている場合)。

于 2015-12-20T16:00:08.393 に答える