0

データを返すカーソルを作成しました。次に、返されたデータに、フィールド 'test_field' が test_field2='A' であるカーソルに存在するかどうかを確認する if ステートメントが必要です。ただし、ifステートメントで構文を正しくするのに苦労しており、オンラインでポインターを見つけることができません。

CURSOR test_cur IS
      SELECT *
      FROM  test
      where name=pk_name;

BEGIN

FOR trec IN test_cur LOOP
    --The following line where my syntax is incorrect
    IF trec.test_field EXISTS IN test_cur WHERE trec.test_field2 = 'A' THEN
        {logic code to go here}
    END IF;
...

サンプルデータ:

name    | test_field    | test_field2
--------------------------------------
x       |  101          | ROL
x       |  101          | A
x       |  102          | ROL
x       |  103          | ROL

カーソルの最初のループでは、次のようになります。

trec.name=x
trec.field=101
trec.field2=ROL 

私がやりたいことは、別の行 (y) があることを認識することです (y) where test_field=101 および test_field2='A' したがって、if ステートメントに入ります。

4

5 に答える 5

0

後のカーソル レコードを先読みすることはできません。また、カーソルを複数回実行するとコストがかかり、とにかく役に立たない可能性があります。

'A'レコードが常に最初になるようにカーソル内のデータを並べ替えてから、追跡変数を使用'A'して、現在のname/のtest_field組み合わせのレコードがあるかどうかを確認できます。

DECLARE
    last_name test.name%TYPE := null;
    last_test_field test.test_field%TYPE := null;
    has_a BOOLEAN := false;
    CURSOR cur IS
        SELECT name, test_field, test_field2
        FROM  test
        WHERE name='x'
        ORDER BY name, test_field, test_field2;
        -- assumes 'A' actually comes first
BEGIN
    FOR rec IN cur LOOP
        -- reset tracking variables if major values change
        IF last_name IS NULL OR last_name != rec.name
            OR last_test_field != rec.test_field
        THEN
            last_name := rec.name;
            last_test_field := rec.test_field;
            has_a := (rec.test_field2 = 'A');
        END IF;
        IF has_a THEN
            DBMS_OUTPUT.PUT_LINE('name ' || rec.name || ' test_field '
                || rec.test_field || ' test_field2 ' || rec.test_field2
                || ' matched condition');
        END IF;
    END LOOP;
END;
/

name x test_field 101 test_field2 A matched condition
name x test_field 101 test_field2 ROL matched condition

PL/SQL procedure successfully completed.

より適切なアプローチは、カーソル内のすべてのレコードにフラグを追加し、分析関数を使用して結果セットの「ピーク」を先取りすることです。繰り返しますが、これは実際に値がアルファベット順に最初に来ると仮定しています'A'。そうでない場合は、実際の値を最初に取得するために関数を微調整する必要があります。

SELECT name, test_field, test_field2,
    first_value(test_field2)
        over (partition by name, test_field
            order by test_field2) as has_a
            -- assumes 'A' actually comes first
FROM  test;

NAME       TEST_FIELD TEST_FIELD HAS_A
---------- ---------- ---------- ----------
x                 101 A          A
x                 101 ROL        A
x                 102 ROL        ROL
x                 103 ROL        ROL

...またはさらに良いのは、これはターゲット値のアルファベット順に依存せず、より明確な結果が得られるためです。

SELECT name, test_field, test_field2,
    MAX(CASE WHEN test_field2 = 'A' THEN 'true' END)
        OVER (PARTITION BY name, test_field) AS has_a
FROM test;

NAME       TEST_FIELD TEST_FIELD HAS_
---------- ---------- ---------- ----
x                 101 ROL        true
x                 101 A          true
x                 102 ROL
x                 103 ROL

それをカーソルに置くと、次のようになります。

DECLARE
    CURSOR cur IS
        SELECT name, test_field, test_field2,
            MAX(CASE WHEN test_field2 = 'A' THEN 'true' END)
                OVER (PARTITION BY name, test_field) AS has_a
        FROM  test
        WHERE name='x'
        ORDER BY name, test_field, test_field2 DESC;
        -- forcing us to see ROL first, just to show it works
BEGIN
    FOR rec IN cur LOOP
        IF rec.has_a = 'true' THEN
            DBMS_OUTPUT.PUT_LINE('name ' || rec.name || ' test_field '
                || rec.test_field || ' test_field2 ' || rec.test_field2
                || ' matched condition');
        END IF;
    END LOOP;
END;
/

name x test_field 101 test_field2 ROL matched condition
name x test_field 101 test_field2 A matched condition

PL/SQL procedure successfully completed.

これはまた、ループで最初にレコードを処理することを強制するものではないことに注意してください'A'。これは、重要である場合とそうでない場合があります。

于 2013-04-17T15:30:18.640 に答える
0

カーソルに使用するクエリ内でこの条件を確認することをお勧めします。次のようにします。

CURSOR test_cur IS
    SELECT TEST.*,
           CASE
              WHEN EXISTS
                      (SELECT 1
                         FROM TEST T
                        WHERE     T.TEST_FIELD = TEST.TEST_FIELD
                              AND T.TEST_FIELD2 = 'A')
              THEN
                 1
              ELSE
                 0
           END
              HAS_A
      FROM TEST
          WHERE NAME=PK_NAME;

BEGIN

FOR trec IN test_cur LOOP
    --The following line where my syntax is incorrect
    IF trec.has_a = 1 THEN
        {logic code to go here}
    END IF;
...
于 2016-03-14T05:40:12.327 に答える
0

その構文は私には論理的に見えません。私の知る限り、それはできません

解決策は

IF trec.test_field is not null and  trec.test_field2 = 'A'
于 2013-04-17T14:47:41.007 に答える
0

私があなたの質問を正しく理解しているなら、あなたはただ先を見ようとしています。その場合、注文を定義するフィールドを知っている必要があります。そのためのテンプレートを以下に示します。

構文の問題を解決するための特定のステートメントは次のとおりです。

FOR trec IN test_cur LOOP -- 構文が正しくない次の行

SELECT COUNT(*) INTO l_count FROM  test
  where name= trec.test_field AND test_field2 = 'A' 
  and key > trec.key
   --this condition specifies if we need to look only further   
  ;

if l_count>0 then
    {logic code to go here}
END IF;

以下は、完全なテンプレートを言い換えたものです。

CURSOR test_cur IS
  SELECT *
  FROM  test
  where name=pk_name

  ORDER by --<<whatever key that helps identify order>>

  ;

BEGIN

FOR trec IN test_cur LOOP
--The following line where my syntax is incorrect

SELECT COUNT(*) INTO l_count FROM  test
  where name= trec.test_field AND test_field2 = 'A' 
  and key > trec.key
   --this condition specifies if we need to look only further   
  ;

if l_count>0 then
    {logic code to go here}
END IF;

...

于 2013-04-17T19:09:00.577 に答える
0

ここで、'trec.test_fields が test_field = trec.test_field の場所に存在する' と言うときtest_field、プログラムのどこかに別の変数という名前が付けられていることを意味していると思います。その場合は、変数の名前を に変更して、変数とstrTest_fieldテーブル内のフィールドの間で名前が競合しないようにし、カーソルを次のように変更します。

CURSOR test_cur IS
      SELECT *
      FROM  test t
      where t.name = pk_name AND
            t.test_field = strTest_field AND
            t.test_field2 = 'A'

共有してお楽しみください。

于 2013-04-17T15:02:51.957 に答える