1

Oracle 用の ADO.Net プロバイダーを使用して、セミコロンで区切られた 2 つの select ステートメントを実行しています。system.Data.OracleClient データ プロバイダーを使用しています。ただし、ADO.Net コードの実行時に無効な文字エラーが発生するため、Oracle はセミコロンを好まないようです。同じデータベーストリップで両方の SELECT ステートメントを実行する必要があるため、これをどのように解決できるかについてのアイデアはありますか?

            string sql = @"
                        WITH
                      x AS
                      (
                        SELECT
                          RowNum AS RowIndex,
                          CAST(Contract_Id AS VARCHAR2(1000)) Contract_Id,
                          Contract_Number,
                          Name AS Contract_Name,
                          Contract_Number
                          || ' '
                          || Name AS Contract_Description,
                          Eff_Date,
                          Expiry_Date
                        FROM
                         contracts
                        WHERE
                          contract_number LIKE :ContractSearchText
                        OR name LIKE :ContractSearchText
                      )
                    SELECT
                      *
                    FROM
                      x
                    WHERE
                      RowIndex  >= :StartingRowIndex
                    AND RowIndex < (:StartingRowIndex + :MaxRows) ;

                    SELECT
                          COUNT(*)
                        FROM
                          contracts
                        WHERE
                          contract_number LIKE :ContractSearchText
                        OR name LIKE :ContractSearchText;
                       ";

アップデート

アレックスの返信は、私が見つけた最良の回答です。しかし、テーブルが 2 回ヒットしたのか 1 回だけヒットしたのかはわかりません。代替クエリは、カウント派生テーブルを使用した CROSS JOIN の作成に依存しています。この代替回答でテーブルが1回だけヒットした場合、誰かが教えてくれますか?

                          WITH
                      x AS
                      (
                        SELECT
                          RowNum AS RowIndex,
                          CAST(Contract_Id AS VARCHAR2(1000)) Contract_Id,
                          Contract_Number,
                          Name AS Contract_Name,
                          Contract_Number
                          || ' '
                          || Name AS Contract_Description,
                          Eff_Date,
                          Expiry_Date
                        FROM
                          vha_int_contract
                        WHERE
                          contract_number LIKE :ContractSearchText
                        OR name LIKE :ContractSearchText
                      ),
                      y as ( select count(distinct contract_id)  TotalCount from x)
                    SELECT
                      *
                    FROM
                      x cross join y
                    WHERE
                      RowIndex  >= :StartingRowIndex
                    AND RowIndex < (:StartingRowIndex + :MaxRows)
4

2 に答える 2

2

通常、呼び出しで複数の SQL ステートメントを実行することはできず、PL/SQL への切り替えは実際には必要ありません。同時に一致する行の数をカウントしようとしているようです。「30 の結果 1 から 5」のようなことができると思います。2 つの別々の呼び出しを行うことはできますが、その間に別のトランザクションがコミットされる可能性があるため、一貫性のない結果が得られるリスクがあります (したがって、「25 から 30 の 29」、または「25 から 29 のような部分的な最後のページ」は必要ありません)。 30'?)。

返された各行の追加フィールドとして合計数を取得できます。これは少し冗長ですが、それ以上のコストはかかりません。実際には、テーブルに 1 回ヒットするだけなので、2 つの個別のクエリはありません。この場合、すべてをカウントしたいので、これは空の句でのanalytic functionバージョンを使用します。countover

SELECT x.*, COUNT(1) OVER () Range_Count
FROM
(
    SELECT
        RowNum AS RowIndex,
        CAST(Contract_Id AS VARCHAR2(1000)) Contract_Id,
        Contract_Number,
        Name AS Contract_Name,
        Contract_Number
        || ' '
        || Name AS Contract_Description,
        Eff_Date,
        Expiry_Date,
        COUNT(1) OVER () Total_Count
    FROM
        contracts
    WHERE
        contract_number LIKE :ContractSearchText
        OR name LIKE :ContractSearchText
    ) x
WHERE RowIndex >= :StartingRowIndex
AND RowIndex < (:StartingRowIndex + :MaxRows)

楽しみのために、ここで 2 つのカウントを行いました。必要なものは内部クエリにありCOUNT(1) OVER () Total_Countます。これTotal_Countにより、返されたすべての行に列が表示され、元の個別のCOUNT(*)クエリで見つかった値と同じ値になります。ただし、外側のクエリにも1つ入れました。COUNT(1) OVER () Range_Countこれにより、範囲内にあるレコードの数が表示されます。これは:Max_Rows、最後の「ページ」に到達するまで続きます。役に立たないかもしれませんし、処理中に行を数えることもできますが、実際に可能であることを示すだけです。

現在、クエリには順序付けがありません。つまり、期待する結果が得られない可能性があります。ORDER BY内部クエリに句を追加するか、 RowNumtoを変更ROW_NUMBER() OVER(ORDER BY Contract_ID)して分析テーマに固執することをお勧めします。


あなたのコメントからあなたが何を望んでいるのかよくわかりません。それぞれに一致するレコードの数が必要な場合はContract_Id、内部クエリに別の用語を追加できます。

    COUNT(1) OVER (PARTITION BY Contract_Id) Contract_Id_Count

個別の値の総数が必要なContract_Id場合は、代わりにこれを追加します。

    COUNT(DISTINCT Contract_Id) OVER () Contract_Id_Count
于 2012-07-30T10:46:33.020 に答える
1

op により良い方法を提供できること以外に、ado.net はセミコロンを好まないと言う立場にあるのでしょうか? 通常はテーブルを作成するバッチクエリをいくつか実行し、何かをしてからテーブルを削除します。T-SQL では、ターミネータが必須である Oracle とは異なり、SQL Server はほとんどの操作でステートメントを終了するためにセミコロンを必要としないため、上記が可能です。

薄い問題を回避するために私が現在考えることができる唯一の方法は、ストアド プロシージャを使用することです (T-SQL ほど優れていないか、コーディングが簡単ではありません) が、バッチ ステートメントを実行できます。

于 2012-08-01T15:43:41.303 に答える