0

この場合、MERGEINTOを使用する方がよいかどうかは無視してください。行が存在するかどうかを確認できるかどうかだけです。そうでない場合は、戻りコードを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

IFretが1であるかnullであるか(他の選択肢)をチェックするUPDATEステートメントの周りにはありません。また、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を実行すると、行が存在する場合は作業が2倍になります。行が存在しないときに更新のみを実行することは、選択を実行することと同じ作業です。

于 2012-07-27T08:30:49.200 に答える
1

s.col1 = 1が存在しないのか、s.col2=2が存在しないのかを区別できるようにするにはどうすればよいですか。そして、それらのために2つの異なるリターンコードを持っています。この場合はどうすればよいですか?

私はおそらくそれをBULKCOLLECTで過度に複雑にしました-特に更新が一度に1行のみである場合-しかしもちろんそれに応じてコードを変更することができます-原則は同じままです。このコードは、col1とcol2に関してどのUPDATE条件が満たされているかに応じて、1、2、または3を返すことを目的としています。

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 に答える