0

忽略在这种情况下使用 MERGE INTO 是否更好。我只是想知道是否可以检查该行是否存在。如果不是,则将返回码设置为 1 并立即返回。如果是,则继续执行其余代码,最后将返回码设置为 0。下面的代码不起作用,因为它总是执行到最后。我应该如何解决它?

  BEGIN

    -- check 
    SELECT CASE
      WHEN NOT EXISTS (SELECT 1 FROM s WHERE s.col1 = 1 AND s.col2 = 2)
      THEN 1
    END
    INTO ret FROM dual;

    -- update
    UPDATE s
    SET s.col3 = 3
    WHERE s.col1 = 1 AND s.col2 = 2;

    COMMIT;

    SELECT 0 INTO ret FROM dual;
    RETURN ret;

  END foo;

如果我希望能够区分它s.col1 = 1不存在或s.col2 = 2不存在怎么办。并为它们提供 2 个不同的返回码。在这种情况下我该怎么办?

4

3 回答 3

4

我想知道是否有必要首先检查该行是否存在以及为什么您不立即发出 UPDATE ?

你不能做这样的事情吗?

BEGIN

    -- update
    UPDATE s
    SET s.col3 = 3
    WHERE s.col1 = 1 AND s.col2 = 2;

    COMMIT;

    IF SQL%ROWCOUNT = 0 THEN
      RETURN 0;
    ELSE
      RETURN 1;
    END IF;

END foo;
于 2012-07-27T08:33:15.877 回答
3

您没有对存储的值做任何事情ret

IFUPDATE 语句周围没有检查 ret 是 1 还是 null(另一种选择)。并且因为没有 IF,所以程序的其余部分总是被执行。

需要这样的东西:

SELECT sum(case when col1 = 1 then 1 else 0 end) as col1_count, 
       sum(case when col2 = 2 then 1 else 0 end) as col2_count
    into ret1, ret2
FROM s 
WHERE s.col1 = 1
   or s.col2 = 2;

if ret1 > 0 and ret2 > 0 then
   update ...;
   commit;
   ret := 0;
elsif  (ret1 > 0 and ret2 = 0) then 
   ret := 1;
elsif (ret1 = 0 and ret2 > 0) then 
   ret := 2;
end if;

return ret;

一种更有效的方法是简单地进行更新并检查是否有任何行被修改。如果行存在,则在执行更新之前运行 select 只会使工作加倍。当行不存在时仅运行更新与执行选择的工作相同。

于 2012-07-27T08:30:49.200 回答
1

What if I want be able to distinguish if it's s.col1 = 1 not exist or s.col2 = 2 not exist. And have 2 different return codes for them. How should I do in this case?

I've probably over-complicated it with a BULK COLLECT - especially if the update is for only one row at any one time - but you can of course modify the code accordingly - the principle remains the same. The code aims to return 1,2 or 3 depending on which UPDATE condition is met regarding col1 and col2.

DECLARE

    TYPE test_rec is record ( .... );

    TYPE result_tab IS TABLE OF test_rt%ROWTYPE;

    lt_results result_tab;

    lv_ret NUMBER(1) := 0;

BEGIN

    SELECT x.* FROM (
    SELECT s.*, 1 as ret
    FROM s
    WHERE s.col1 = 1 and s.col2 != 2
    UNION ALL
    (SELECT s.*, 2
    FROM s
    WHERE s.col1 =! 1 and s.col2 = 2)
    UNION ALL
    (SELECT s.*, 3
    FROM s
    WHERE s.col1 = 1 and s.col2 = 2))
    BULK COLLECT INTO lt_results;

    FOR i in lt_results.first .. lt_results.last LOOP
        <<DO YOUR UPDATE>>
        lv_ret := lt_results(i).ret;
    END LOOP;

    COMMIT;

    RETURN lv_ret;

END;
于 2012-07-27T09:49:15.150 回答