-2

新しい一時テーブルを作成するPL/SQL関数があります。テーブルの作成には。を使用しますexecute immediate。oracle sqldeveloperで関数を実行すると、すべて問題ありません。この関数は、エラーなしで一時テーブルを作成します。しかし、UがSQLを使用する場合:

Select function_name from table_name

例外があります:

ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML
ORA-06512: at "SYSTEM.GET_USERS", line 10
14552. 00000 -  "cannot perform a DDL, commit or rollback inside a query or DML "
*Cause:    DDL operations like creation tables, views etc. and transaction
       control statements such as commit/rollback cannot be performed
       inside a query or a DML statement.

アップデート

申し訳ありませんが、タブレットPCから書き込み、テキストのフォーマットに問題があります。私の機能:

CREATE OR REPLACE FUNCTION GET_USERS 
(
    USERID IN VARCHAR2
)
RETURN VARCHAR2 
AS
    request VARCHAR2(520) := 'CREATE GLOBAL TEMPORARY TABLE ';
BEGIN
    request := request || 'temp_table_' || userid || 
            '(user_name varchar2(50), user_id varchar2(20), is_administrator varchar2(5)') ||
            ' ON COMMIT PRESERVE ROWS';
    EXECUTE IMMEDIATE (request);
    RETURN 'true';
END GET_USERS;
4

2 に答える 2

2

エラーは明白です:

ORA-14552:クエリまたはDML内でDDL、コミットまたはロールバックを実行できません

Oracleでは、クエリ内でコミットすることはできません。Oracleのクエリはアトミックであり(完全に成功するか、変更を加えない)、DMLの途中でコミットすると機能しないため、意味がないという説明が考えられます。選択クエリの場合、すべての行は単一の論理ポイントインタイムから返される必要があり、選択の途中でコミットすると、一貫性のない結果が得られます。

OracleのDDLは暗黙的なコミットを発行するため、クエリ内でDDLを作成することはできません。

ただし、これはあなたの場合には問題にはならないでしょう。SQLサーバーのような一時テーブルは、OracleのGLOBALLY一時テーブルと同等ではありません。Oracleの一時テーブルの前に常に:が付いているのには理由がありますGLOBALLY。一時テーブルのデータは各セッションにプライベートですが、すべてのセッションに表示されます。

Oracleでは、一時テーブルの作成は比較的コストのかかる操作であり、個別の一時テーブルを作成しないでください。同じジョブを実行するすべてのセッションで、同じ共通構造を使用する必要があります。Oracleでは、複数の一時テーブルを作成する代わりに、テーブルを1回作成して、すべてのプロシージャで再利用する必要があります。後で必要になる場合は、なぜそれを削除するのですか?

いずれの場合も、SELECTに依存する複数のDDLを実行することにした場合は、SELECTクエリの代わりにPLSQLブロックで実行できます。

DECLARE
   l VARCHAR2(100);
BEGIN
   FOR cc IN (SELECT col FROM tab) LOOP
      l := create_temp_table(cc.col);
   END LOOP;
END;
于 2012-10-24T16:17:27.900 に答える
0

Oracle 10g XEで以下のソリューションをテストしましたが、うまくいきました。

関数の作成:

CREATE OR REPLACE FUNCTION GET_USERS 
(
    USERID IN VARCHAR2
)
RETURN VARCHAR2 
AS
    request VARCHAR2(255) := 'CREATE GLOBAL TEMPORARY TABLE ';
BEGIN
    request := request || 'temp_table_' || userid || 
            '(user_name varchar2(50), user_id varchar2(20), is_administrator varchar2(5))' ||
            ' ON COMMIT PRESERVE ROWS';
    EXECUTE IMMEDIATE request;
    RETURN 'true';
END GET_USERS;

実行機能:

SET SERVEROUTPUT ON
DECLARE
 RESULT  VARCHAR(255);
BEGIN
   RESULT:=gET_USERS('ADMIN3');
   dbms_output.put_line(result);
END;

一時テーブルから選択します。

SELECT * FROM temp_table_admin3;
于 2012-10-24T19:14:43.673 に答える