0

REF_CURSORストアド プロシージャ変数の出力からテーブルを作成できるパッケージがあります。クライアント アプリケーションに大量の結果を返すために、これを DevPress XPO ソースで使用します。

以前はソリッド テーブルを作成し、キーを追加してインデックスを作成し、新しいテーブル名を XPO ソースに提供されたクライアントに返しましたが、機能しています。ただし、ソリッド テーブルを使用するのは最善の解決策ではないため、GTT の使用を開始しました。

TOAD でパッケージを実行すると、データは保持されますが、C# からコマンドを実行すると、実行直後にテーブルにデータがありません。接続はまだ閉じられていないため、データが存在しない理由は 100% わかりません。

すべての実行が同じセッションで行われることを確認するために設定できる接続コンテキストに何かがありますか? テーブルに入力するステートメントがありexecute immediate、パッケージを実行するときに TOAD が同じコンテキストを使用する可能性があると思います。

これが私のコードの一部です:

FUNCTION Build_Table_from_Cursor(REF_CURSOR SYS_REFCURSOR, ID NUMBER, AddKeyField CHAR) RETURN VARCHAR2 AS
  QueryCursor SYS_REFCURSOR;
  CursorNumber NUMBER;
  p_tablename varchar2(30);
  pk_name varchar2(30);
BEGIN

   QueryCursor := REF_CURSOR;
   CursorNumber := DBMS_SQL.TO_CURSOR_NUMBER(QueryCursor);
   p_tablename := 'TEMPTABLE';

   UTIL.create_table_from_cursor(CursorNumber, p_tablename);  --This creates the GTT with all the columns
   Execute immediate 'TRUNCATE TABLE ' || p_tablename;  --To Add the key this must be done otherwise there is an error

   pk_name := substr(p_tablename, INSTR(p_tablename, '.') + 1);

   IF(AddKeyField = 'Y') THEN    --Sometimes the Key field already exists
     EXECUTE IMMEDIATE 'ALTER TABLE ' || p_tablename || ' ADD (KEY_FIELD_   NUMBER)';
   END IF;

   EXECUTE IMMEDIATE 'CREATE UNIQUE INDEX ' || p_tablename || 'KEY_INDEX ON ' || p_tablename || '   (KEY_FIELD_)';
   EXECUTE IMMEDIATE 'ALTER TABLE ' || p_tablename || ' ADD CONSTRAINT pk_' || pk_name || ' PRIMARY KEY( KEY_FIELD_ )';

   QueryCursor := DBMS_SQL.TO_REFCURSOR(CursorNumber);

   PDS.UTIL.POPULATE_TABLE_FROM_CURSOR(QueryCursor, p_tablename, 1000);  --This populates the table

   EXECUTE IMMEDIATE 'UPDATE ' || p_tablename || ' SET KEY_FIELD_ = ROWNUM';
  COMMIT; 
  return p_tablename;
END Build_Table_from_Cursor;

これは、TOAD で実行すると完全に機能します。

これを実行すると

using (var conn = factory.CreateConnection(Dal.ConnectionStrings[connectionString].ConnectionString))
{
    conn.Open();
    using (var cmd = factory.CreateCommand(CommandType.StoredProcedure, storedProcedureName))
    {
        var storedProcedureRow = commandExecuteDataSet.StoredProcedure[0];
        foreach (var parametersRow in commandExecuteDataSet.Parameters)
        {
            cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter(parametersRow.Name, parametersRow.Value ?? "", GetDBTypeFromString(parametersRow.OracleDbType)));
        }
        cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter(storedProcedureRow.RefCursorName, DbType.Object, ParameterDirection.Output, true));
        cmd.ExecuteNonQuery();
        var refCursor = cmd.Parameters[storedProcedureRow.RefCursorName].Value;
        cmd.Parameters.Clear();
        cmd.CommandText = "SERVERMODE_UTIL.Build_Table_from_Cursor";
        cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("REF_CURSOR", refCursor));
        cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("ID", biID));
        cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("AddKeyField", "Y"));
        cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("p_tablename", DbType.String, ParameterDirection.ReturnValue));

        cmd.ExecuteNonQuery();
        var tempTableName = cmd.Parameters["p_tablename"].Value.ToString();
        tempTableName = tempTableName.Substring(tempTableName.IndexOf(".") + 1);
    }
}

より大きなパッケージの一部として、これは GTT を作成するために実行されるコードです

l_statement := 'CREATE GLOBAL TEMPORARY TABLE ' || l_tablename || ' (' || CHR(13) || CHR(10) || l_statement || CHR(13) || CHR(10) || ') ON COMMIT PRESERVE ROWS';
execute immediate l_statement;
4

0 に答える 0