0

我创建了一个游标,它返回一些数据。然后,我希望在返回的数据中有一个 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 语句。

4

5 回答 5

0

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

一个解决方案是

IF trec.test_field is not null and  trec.test_field2 = 'A'
于 2013-04-17T14:47:41.007 回答
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 回答
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

如果我正确理解您的查询,那么您只是想往前看。如果是这样,您必须知道定义您的订单的字段。我在下面给出了执行此操作的模板。

解决您的语法问题的具体说明是:

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

我宁愿建议在您用于光标的查询中检查此条件,就像这样:

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 回答