4

この質問は、StackOverflowで見つけた他のいくつかの質問と似ていますが、その違いは、新しい質問を正当化するのに十分なほど重要なので、ここにあります。

Oracleの動的SQLから結果セットを取得し、動的SQLステートメントを直接実行したかのように、それをSqlDeveloperのようなツールに結果セットとして表示したいと思います。これはSQLServerでは簡単なので、具体的には、SQL ServerManagementStudioまたはクエリエクスプローラーで結果セットを返すSQLServerの例を次に示します。

EXEC sp_executesql N'select * from countries'

またはより適切に:

DECLARE @stmt nvarchar(100)
SET @stmt = N'select * from countries'
EXEC sp_executesql @stmt

「動的SQLを実行するOraclePL/SQL匿名ブロックから結果セット/カーソルを返す方法」という質問。問題の前半、つまり動的SQLをカーソルに実行することで対処します。「Oracleプロシージャが結果セットを返すようにする方法」という質問でも、同様の答えが得られます。Web検索により、同じテーマの多くのバリエーションが明らかになりました。これらはすべて、私の質問の前半にのみ対応しています。この投稿を見つけましたSqlDeveloperでそれを行う方法を説明しますが、それはSqlDeveloperの機能のビットを使用します。私は実際にカスタムクエリツールを使用しているので、SQLコードに自己完結型のソリューションが必要です。このカスタムクエリツールにも同様に、print(dbms_output.put_line)ステートメントの出力を表示する機能はありません。結果セットのみを表示します。これは、「executeimmediate ... Bulkcollect」を使用するもう1つの可能な方法ですが、この例でも、dbms_output.put_lineステートメントのループを使用して結果をレンダリングしますこのリンクはトピックに対処しようとしますが、質問はそこでも完全に答えられることはありませんでした。

これが可能であると仮定して、もう1つの条件を追加します。関数やプロシージャを定義せずにこれを実行したい(DB権限が制限されているため)。つまり、動的SQLを含む自己完結型のPL / SQLブロックを実行し、SqlDeveloperまたは同様のツールで結果セットを返したいと思います。


要約すると:

  • 任意のSQLステートメント(したがって動的SQL)を実行したい。
  • プラットフォームはOracleです。
  • ソリューションは、プロシージャや関数のないPL/SQLブロックである必要があります。
  • 出力は、正規の結果セットとして生成する必要があります。印刷ステートメントはありません。
  • 出力は、SqlDeveloperの特別な機能を使用せずに、結果セットとしてSqlDeveloperでレンダリングする必要があります。

助言がありますか?

4

4 に答える 4

1

未確定の構造の結果セットを返す任意のクエリを取得する PL/SQL コードのチャンクと、何らかの方法で結果セットを「カスタム GUI ツールで簡単にレンダリングできる」「転送/再構築」を求めているようです。 "。

その場合は、動的 SQL の DBMS_SQL を調べてください。これには、動的 SELECT ステートメントから列を返す DESCRIBE_COLUMNS プロシージャがあります。必要な手順は、

  1. ステートメントを解析する
  2. 結果セットの説明 (列名とデータ型)
  3. 各行をフェッチし、各列に対して、データ型依存関数を呼び出してその値をローカル変数に返します
  4. これらのローカル変数を定義済みの構造に配置して、呼び出し環境に戻ります (たとえば、一貫した列名 [col_1、col_2 など]、おそらくすべて VARCHAR2)。

別の方法として、クエリをXMLFORESTステートメントに組み込み、XML から結果を解析することもできます。


追加: SQL Server とは異なり、Oracle PL/SQL 呼び出しは「自然に」単一の結果セットを返しません。1 つ以上の ref カーソルを開き、それらをクライアントに返すことができます。その後、これらの ref カーソルからレコードと列をフェッチするのはクライアントの責任になります。クライアントがそれを処理しない/処理できない場合、PL/SQL 呼び出しは使用できません。ストアド関数は、事前定義されたコレクション型を返すことができます。これにより、「select * from table(func_name('select * from countries'))」のようなことができます。ただし、関数は DML (更新/削除/挿入/マージ) を実行できません。これは、そのクエリの一貫性の概念が吹き飛ばされるためです。さらに、返される構造が修正されるため、

select * from table(func_name('select * from countries'))

と同じ列のセット (列名とデータ型) を返す必要があります。

select * from table(func_name('select * from persons'))

DBMS_SQL または XMLFOREST を使用すると、このような関数が動的クエリを取得し、それを事前定義された一連の列 (col_1、col_2 など) に再構築して、一貫した方法で返すことができます。しかし、それが何を意味するのか、私にはわかりません。

于 2010-04-07T07:45:32.910 に答える
0

TOADでは、以下のスクリプトを実行すると、v_resultのタイプの入力を求められます。タイプ選択カーソルの選択リストから、結果がToadのデータグリッドに表示されます(結果のようなExcelスプレッドシート)。とはいえ、結果としてカーソルを操作する場合は、常に2つのプログラム(クライアントとサーバー)を作成する必要があります。この場合、「TOAD」がクライアントになります。

DECLARE
   v_result      sys_refcursor;
   v_dynamic_sql   VARCHAR2 (4000);
BEGIN
   v_dynamic_sql := 'SELECT * FROM user_objects where ' || ' 1 = 1';

   OPEN :v_result FOR (v_dynamic_sql);
END;

OracleのSQLDeveloperにも、バインディングのプロンプトを表示する同様のメカニズムが存在する可能性があります。

于 2010-04-05T18:44:25.460 に答える
0

これらを試してみてください。

DECLARE
  TYPE EmpCurTyp  IS REF CURSOR;
  v_emp_cursor    EmpCurTyp;
  emp_record      employees%ROWTYPE;
  v_stmt_str      VARCHAR2(200);
  v_e_job         employees.job%TYPE;
BEGIN
  -- Dynamic SQL statement with placeholder:
  v_stmt_str := 'SELECT * FROM employees WHERE job_id = :j';

  -- Open cursor & specify bind argument in USING clause:
  OPEN v_emp_cursor FOR v_stmt_str USING 'MANAGER';

  -- Fetch rows from result set one at a time:
  LOOP
    FETCH v_emp_cursor INTO emp_record;
    EXIT WHEN v_emp_cursor%NOTFOUND;
  END LOOP;

  -- Close cursor:
  CLOSE v_emp_cursor;
END;


declare
  v_rc    sys_refcursor;
begin
   v_rc := get_dept_emps(10);  -- This returns an open cursor
   dbms_output.put_line('Rows: '||v_rc%ROWCOUNT);
   close v_rc;
end;

ここで他の例を見つけてください。http://forums.oracle.com/forums/thread.jspa?threadID=886365&tstart=0

于 2010-04-05T18:00:06.070 に答える