10

私は次の手順を持っています:

CREATE PROCEDURE foo ()
    SELECT * FROM fooBar INTO TEMP tempTable;

    -- do something with tempTable here

    DROP TABLE tempTable;
END PROCEDURE;

DROP TABLEが呼び出される前に例外が発生した場合はどうなりますか?fooが終了した後もtempTableは存在しますか?

その場合、tempTableがすでに存在するため、fooは次に呼び出されたときに失敗する可能性があります。それはどのように扱われるべきですか。

編集:私はinformix11.5を使用しています

4

5 に答える 5

5

ドキュメントによると、セッションが終了すると一時テーブルは削除されます。

于 2009-12-02T18:05:59.297 に答える
4

他の人が述べたように、一時テーブルは明示的に削除するかセッションが終了するまで存続します。

テーブルが既に存在するためにストアド プロシージャが失敗した場合、SPL は例外を生成します。ON EXCEPTION 句を追加することで例外に対処できますが、SPL のよりバロックな部分の 1 つであるストアド プロシージャ言語に入る必要があります。

これは、ストアド プロシージャを少し変更したバージョンです。ゼロ除算の例外 (SQL -1202) が生成されます。

CREATE PROCEDURE foo ()
    define i integer;
    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;
END PROCEDURE;

execute procedure foo();
SQL -1202: An attempt was made to divide by zero.

execute procedure foo();
SQL -958: Temp table temptable already exists in session.

これは、コードを介して最初に SELECT を実行し、テーブルを作成した後、ゼロ除算に違反したことを示しています。ただし、2 回目は、一時テーブルが既に存在していたために SELECT が失敗したため、別のエラー メッセージが表示されました。

drop procedure foo;
CREATE PROCEDURE foo()
    define i integer;

    BEGIN
        ON EXCEPTION
            DROP TABLE tempTable;
            SELECT * FROM 'informix'.systables INTO TEMP tempTable;
        END EXCEPTION WITH RESUME;
        SELECT * FROM 'informix'.systables INTO TEMP tempTable;
    END;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;
END PROCEDURE;

BEGIN/END ブロックは、例外処理をトラップされたステートメントに制限します。BEGIN/END がない場合、例外処理はプロシージャ全体をカバーし、ゼロ除算エラーにも反応します (したがって、DROP TABLE が機能し、プロシージャが正常に実行されたように見えます)。

この時点でまだ temptable が存在することに注意してください。

+ execute procedure foo();
SQL -1202: An attempt was made to divide by zero.
+ execute procedure foo();
SQL -1202: An attempt was made to divide by zero.

これは、一時テーブルが存在するため、手順が失敗しなくなったことを示しています。

次の方法で、ON EXCEPTION ブロックを選択したエラー コード (これには -958 が妥当と思われます) に制限できます。

ON EXCEPTION IN (-958) ...

IBM Informix Guide to SQL: Syntax マニュアルの第 3 章「SPL ステートメント」を参照してください。

Informix 11.70 では、'IF EXISTS' 句と 'IF NOT EXISTS' 句が CREATE ステートメントと DROP ステートメントに追加されていることに注意してください。したがって、変更したDROP TABLEステートメントを使用できます。

DROP TABLE IF EXISTS tempTable;

したがって、Informix 11.70 以降では、プロシージャを記述する最も簡単な方法は次のとおりです。

DROP PROCEDURE IF EXISTS foo;

CREATE PROCEDURE foo()
    define i integer;
    DROP TABLE IF EXISTS tempTable;

    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;  -- Still a good idea
END PROCEDURE;

これを使用することもできますが、それが何であれ、プロシージャの以前の定義を取得すると、期待したものではない可能性があります。

CREATE PROCEDURE IF NOT EXISTS foo()
    define i integer;
    DROP TABLE IF EXISTS tempTable;

    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;  -- Still a good idea
END PROCEDURE;
于 2009-12-03T00:31:07.890 に答える
3

私はついにジョナサンとRETのソリューションのバリエーションを使用しました:

CREATE PROCEDURE foo ()
    ON EXCEPTION IN (-206)
    END EXCEPTION WITH RESUME;

    DROP TABLE tempTable;    

    SELECT * FROM fooBar INTO TEMP tempTable;

    -- do something with tempTable here

    DROP TABLE tempTable;
END PROCEDURE;
于 2009-12-03T18:27:10.190 に答える
2

はい、一時テーブルは引き続き存在します。定義上、一時テーブルには、明示的に削除されない限り、それらを作成したセッションの有効期間があります。

一時テーブルは、それを作成したセッションでのみ見ることができ、複数のユーザーが同じ手順を並行して実行することを妨げるものはありません。一時テーブルの存在をテストするための Adam の回答は、ユーザーがプロシージャを実行している場合、ゼロ以外の結果を返します。一時テーブルを所有するセッションが現在のセッションでもあることをテストする必要があります。この質問がストアド プロシージャの範囲内にあることを考えると、明示的な DROP を追加し、いくつかの例外処理でラップする方が簡単かもしれません。

于 2009-12-02T20:52:21.153 に答える
1
SELECT count(*) 
INTO w_count 
FROM sysmaster:systabnames s,sysmaster:systabinfo i
WHERE i.ti_partnum = s.partnum
AND sysmaster:BITVAL(i.ti_flags,'0x0020') = 1
AND s.tabname = 'tempTable' ;

w_countが1の場合、SELECT...INTOの前にテーブルを削除します。DROPTABLEと同じです。

于 2009-12-02T18:16:12.043 に答える