1. ホーム
  2. sql

[解決済み] Oracle PL/SQL - "SELECT INTO" 使用時に ORA-01403 "No data found" が発生する。

2022-03-08 15:43:17

質問

OracleでTriggerを開発しているときに、この問題に直面しました。 ORA-01403: データが見つかりません . 私はいくつかの研究を行い、問題の根本を理解しました。とはいえ エラー例外処理 上記のエラーを防ぐことはできますが、私の問題を解決することはできません。

現在、私が探しているのは 最適 クエリ量を少なくし、可能な限り最高のパフォーマンスを達成するための回避策です。私は実際の構造に簡単な例を作成し、シナリオを説明しようとします。

シナリオ

私は、ある期間を設定するために、quot;日付参照"テーブルを持っています。

CREATE TABLE DATE_REFERENCE (
    DATE_START                  DATE NOT NULL,
    DATE_END                    DATE NOT NULL,
    -- Several other columns here, this is just a silly example
    CONSTRAINT PK_DATE_REFERENCE PRIMARY KEY(DATE_START, DATE_END)
);

トリガーがかかったら、1つの DATE フィールド - 例えば DATE_GIVEN (例:日本酒)。私が必要とするのは

  1. を見つけるには DATE_REFERENCE が含まれる行 DATE_GIVEN BETWEEN DATE_START AND DATE_END (簡単)です。 または
  2. 前のオプションが返した場合 データなし 次に近いものを探す必要があります。 DATE_START から DATE_GIVEN .

どちらの場合でも、私は すべての列を持つ行 テーブルから DATE_REFERENCE のように、Opt1やOpt2にマッチするかどうかに関係なく。まさにそこで、説明したような問題に直面したのです。

このテストブロックを テスト を作成し、解決策を探っています。以下はその例です。 が動作しない , 知っている。 しかし、それは まさに 私が実現したいこと (概念的には)です。というようなコメントを付けています。 -- Lots of code より精巧なトリガーの一部であることを明確にするためです。

DECLARE
    DATE_GIVEN       DATE; 
    RESULTROW        DATE_REFERENCE%ROWTYPE;
BEGIN

    -- Lots of code
    -- Lots of code
    -- Lots of code

    DATE_GIVEN := TO_DATE('2014-02-26 12:30:00', 'YYYY-MM-DD HH24:MI:SS');

    -- This one throws the ORA-01403 exception if no data was found
    SELECT 
       * INTO RESULTROW
    FROM
       DATE_REFERENCE
    WHERE
       DATE_GIVEN BETWEEN DATE_START AND DATE_END;

    -- If the above didn't throw exceptions, I would continue like so:
    IF RESULTROW IS NULL THEN

        SELECT 
           * INTO RESULTROW
        FROM
           DATE_REFERENCE
        WHERE
           DATE_START > DATE_GIVEN
           AND ROWNUM = 1
        ORDER BY DATE_START ASC;

    END IF;

    -- Now RESULTROW is populated, and the rest of the trigger code gets executed ~beautifully~

    -- Lots of code
    -- Lots of code
    -- Lots of code

END;

質問

上記のPL/SQLブロックは、どちらかというと コンセプト より 作業コード を取得するための最良の方法は何ですか? RESULTROW を入力し、パフォーマンスとできるだけ少ないクエリに配慮してください。

長い質問で申し訳ありませんが、シナリオの説明が必要だと思ったからです。どんな助けや考えでも、前もってありがとうございます!

どのように解決するのですか?

フィールドに直接入力し、順序付けと rownum :

SELECT * INTO RESULTROW
FROM (SELECT *
      FROM DATE_REFERENCE
      ORDER BY (CASE WHEN DATE_GIVEN BETWEEN DATE_START AND DATE_END
                     THEN 1 ELSE 0
                END) DESC,
               (DATE_START - DATE_GIVEN)
     ) t
WHERE rownum = 1;

これで、1回のクエリで情報が入力されます。

EDIT

サブクエリに条件を入れる場合、それが必要です。

SELECT * INTO RESULTROW
FROM (SELECT *
      FROM DATE_REFERENCE
      WHERE DATE_GIVEN <= DATE_END
      ORDER BY (CASE WHEN DATE_GIVEN BETWEEN DATE_START AND DATE_END
                     THEN 1 ELSE 0
                END) DESC,
               (DATE_START - DATE_GIVEN)
     ) t
WHERE rownum = 1;

私は、正しい条件は DATE_GIVEN <= DATE_END . これは between を意味するはずである。 DATE_GIVEN < DATE_START . これは、次のように仮定しています。 DATE_END は決して NULL .