0

多くのクエリを実行し、変数に格納する多くの値を取得するストアド プロシージャがあります。この手順で、ユーザーが指定したテーブルにクエリ結果を挿入できるようにしたいと考えています。指定されたテーブル名を varchar パラメータとして保存しますが、このテーブルに挿入するにはどうすればよいですか?

コンパイル時に、Oracle はテーブルが存在しないと言っています。

4

2 に答える 2

5

おそらく、使用している変数の名前を持つテーブルが存在しないことを示していますが、もちろん存在しません。実際のテーブルは、コンパイル時に存在する場合と存在しない場合があります。柔軟であるため、そうではない可能性があると想定する方がおそらく安全です。いずれにせよ、それがどうなるかわからないので、これを実現するには動的 SQL を使用する必要があります。

別の回答のコメントで述べたように、SQL インジェクションに注意する必要があります。通常、動的 SQL でバインド変数を使用したいのですが、オブジェクト名にバインドを使用できないため、連結する必要があります。dbms_assertパッケージを含む 11g を使用していることを願っています。

簡単な例を次に示します。

create or replace procedure p42 (table_name varchar2) as
begin
  execute immediate 'insert into '
    || dbms_assert.qualified_sql_name(table_name)
    || ' select * from dual';
end;
/

次に、プロシージャが既に存在する後にテーブルを作成し、プロシージャを正常に呼び出すことができます。

create table t42 (dummy varchar2(1));

exec p42('t42');

select * from t42;

DUMMY
-----
X     

実際のクエリは明らかにより複雑になり、ターゲット テーブル名と共に渡すフィルター値にはバインド変数を使用する必要があります。


この呼び出しの利点は、dbms_assert不正なものが渡された場合や、厄介なものが渡された場合にエラーが発生することです。

exec p42('t42 select ''Y'' from dual union all');

ORA-44004: invalid qualified SQL name
ORA-06512: at "SYS.DBMS_ASSERT", line 207
ORA-06512: at "STACKOVERFLOW.P42", line 3
ORA-06512: at line 1

プロシージャが渡された値を単純に連結した場合:

  execute immediate 'insert into ' || table_name || ' select * from dual';

...次に、同じ呼び出しで 2 つの行がテーブルに挿入されます。

exec p42('t42 select ''Y'' from dual union all');

select * from t42;

DUMMY
-----
Y     
X

データの整合性が重要である場合、これは心配する必要があります。使用できない場合はdbms_assert、渡された名前が実際に存在し、aなどのall_tablesようなものが含まれていないことを確認してみてください。 union-in関数はあなたのために大変な仕事をします。

于 2013-08-21T18:36:25.227 に答える
0

次のようなことを試してください:

exec ('insert into ' + @tblname + ' (col) values (123)')
于 2013-08-21T17:51:09.437 に答える