存在于满足条件的光标中

时间:2013-04-17 14:40:22

标签: sql oracle plsql cursor

我创建了一个返回一些数据的游标。然后,我希望在返回的数据中有一个if语句,用于检查游标中是否存在“test_field”字段,其中test_field2 ='A'。我很难在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),其中test_field = 101和test_field2 ='A',因此进入if语句。

5 个答案:

答案 0 :(得分:0)

这种语法对我来说看起来不合逻辑,AFAIK你不能这样做

解决方案是

IF trec.test_field is not null and  trec.test_field2 = 'A'

答案 1 :(得分: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'

分享并享受。

答案 2 :(得分: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'记录,这可能重要也可能不重要 - 可能不是因为您在示例中根本没有订购。

答案 3 :(得分: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;

...

答案 4 :(得分: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;
...