2017-01-25 3 views
0

条件のセットに基づいて値を切り替えようとしていて、UPDATE式のSET句内にネストされたCASE文がある場合、そのカラムは更新されません。UPDATE SET句のネストされたCASE文

単純なCASE式が存在する場合、列は更新されているように見えます。ただし、この例のOVERRIDDEN_CHECK_NUMBERおよびOVERRIDDEN_AMOUNTでは、列は更新されません。

UPDATEのOVERRIDDEN_DATE、OVERRIDDEN_USER_ID、CHECK_NO、およびAMOUNT列は、問題なく更新されています。

このUPDATE文でOVERRIDDEN_CHECK_NUMBERとOVERRIDDEN_AMOUNTが更新されない理由を教えていただけますか?

入れ子にされたCASE文は、UPDATE式のSET句には使用できませんか?

SQL例

UPDATE WAREHOUSE.BANK_STATEMENT_ACTIVITY 
    SET OVERRIDDEN_CHECK_NO  = --(CASE :btn           
             (CASE WHEN (:btn = '1') THEN CASE WHEN '141973' = '141973' THEN NULL 
                      WHEN '141973' != '999999' THEN LPAD(TRIM(141973), 12, '0') 
                     END 
             WHEN (:btn = '2') THEN '1740 - Previously Paid Warrant' 
             ELSE NULL 
            END), 
     OVERRIDDEN_AMOUNT   = --(CASE :btn 
             (CASE WHEN (:btn = '1') THEN CASE WHEN 253.20 = 253.20 THEN NULL 
                      WHEN 253.20 != 999.99 THEN LPAD(TRIM(253.20), 12, '0') 
                     END 
             WHEN (:btn = '2') THEN NULL 
             ELSE NULL 
            END), 
     OVERRIDDEN_DATE   = SYSDATE, 
     OVERRIDDEN_USER_ID  = 1009, 
     CHECK_NO     = (CASE :btn 
             WHEN '1' THEN LPAD(TRIM(999999), 12, '0') 
             WHEN '2' THEN '142775' 
             ELSE NULL 
             END), 
     AMOUNT     = (CASE :btn 
             WHEN '1' THEN TRIM(78.60) 
             WHEN '2' THEN TRIM(253.20) 
             ELSE NULL 
             END) 
     WHERE TO_NUMBER(CHECK_NO) = (CASE :btn 
             WHEN '1' THEN '141973' 
             WHEN '2' THEN '142775' 
             ELSE NULL 
            END) 
     AND AMOUNT    = (CASE :btn 
             WHEN '1' THEN 78.60 
             WHEN '2' THEN 253.20 
             ELSE NULL 
            END) 
     AND TRUNC(LOAD_DATE)  = (CASE :btn 
             WHEN '1' THEN TRUNC(LOAD_DATE) 
             WHEN '2' THEN (SELECT (MAX(LOAD_DATE)) FROM WAREHOUSE.BANK_STATEMENT_ACTIVITY) 
             ELSE NULL 
             END) 
     AND BANKACCTNO   = (SELECT LONGDESC 
            FROM TCMS.COMPLEMENTARY_VALIDATIONS 
            WHERE TEXTCODE = 'BANKACCT' 
            AND CODE = 80); 

EDIT

働いていた編集者を経て更新クエリを指摘@mathguy logival問題を修正した後。ただし、PL/SQLパッケージでこれを実行すると、表の更新は失敗します。ここで

は更新前である:

Before - result

彼女は結果の後にある:

After - result

彼らは同じです。

これは、実際のパッケージの手順である:

PROCEDURE UpdateBankStatementActivity(btn IN VARCHAR2) 
AS 
BEGIN 
DBMS_OUTPUT.PUT_LINE('UpdateBankStatementActivity - btn: ' || btn); 
DBMS_OUTPUT.PUT_LINE('UpdateBankStatementActivity - bsa_rec.OVERRIDDEN_CHECK_NO: ' || bsa_rec.OVERRIDDEN_CHECK_NO || CHR(10) || 
                'bsa_rec.OVERRIDDEN_AMOUNT: ' || bsa_rec.OVERRIDDEN_AMOUNT || CHR(10) || 
                'bsa_rec.CHECK_NO: ' || bsa_rec.CHECK_NO || CHR(10) || 
                'bsa_rec.AMOUNT: ' || bsa_rec.AMOUNT || CHR(10) || 
                'bsa_rec.LOAD_DATE:' || bsa_rec.LOAD_DATE); 
    UPDATE WAREHOUSE.BANK_STATEMENT_ACTIVITY 
    SET OVERRIDDEN_CHECK_NO  = --(CASE :btn           
             (CASE WHEN (btn = '1') THEN CASE WHEN bsa_rec.OVERRIDDEN_CHECK_NO = bsa_rec.CHECK_NO THEN NULL 
                     WHEN bsa_rec.OVERRIDDEN_CHECK_NO != bsa_rec.CHECK_NO THEN LPAD(TRIM(bsa_rec.OVERRIDDEN_CHECK_NO), 12, '0') 
                    END 
             WHEN (btn = '2') THEN '1740 - Previously Paid Warrant' 
             ELSE NULL 
            END), 
     OVERRIDDEN_AMOUNT   = --(CASE :btn 
             (CASE WHEN (btn = '1') THEN CASE WHEN bsa_rec.OVERRIDDEN_AMOUNT = bsa_rec.AMOUNT THEN NULL 
                     WHEN bsa_rec.OVERRIDDEN_AMOUNT != bsa_rec.AMOUNT THEN LPAD(TRIM(bsa_rec.OVERRIDDEN_AMOUNT), 12, '0') 
                    END 
             WHEN (btn = '2') THEN NULL 
             ELSE NULL 
            END), 
     OVERRIDDEN_DATE   = SYSDATE, 
     OVERRIDDEN_USER_ID  = bsa_rec.OVERRIDDEN_USER_ID, 
     CHECK_NO     = (CASE btn 
             WHEN '1' THEN LPAD(TRIM(bsa_rec.CHECK_NO), 12, '0') 
             WHEN '2' THEN LPAD(TRIM(bsa_rec.CHECK_NO), 12, '0') 
             ELSE NULL 
             END), 
     AMOUNT     = (CASE btn 
             WHEN '1' THEN TRIM(bsa_rec.OVERRIDDEN_AMOUNT) 
             WHEN '2' THEN TRIM(bsa_rec.AMOUNT) 
             ELSE NULL 
             END) 
     WHERE TO_NUMBER(CHECK_NO) = (CASE btn 
             WHEN '1' THEN bsa_rec.OVERRIDDEN_CHECK_NO 
             WHEN '2' THEN bsa_rec.CHECK_NO 
             ELSE NULL 
            END) 
     AND AMOUNT    = (CASE btn 
             WHEN '1' THEN bsa_rec.OVERRIDDEN_AMOUNT 
             WHEN '2' THEN bsa_rec.AMOUNT 
             ELSE NULL 
            END) 
     AND TRUNC(LOAD_DATE)  = (CASE btn 
            WHEN '1' THEN TRUNC(bsa_rec.LOAD_DATE) 
            WHEN '2' THEN (SELECT MAX(LOAD_DATE) FROM WAREHOUSE.BANK_STATEMENT_ACTIVITY) 
            ELSE NULL 
            END) 
     AND BANKACCTNO   = (SELECT LONGDESC 
            FROM TCMS.COMPLEMENTARY_VALIDATIONS 
            WHERE TEXTCODE = 'BANKACCT' 
            AND CODE = 80); 

    COMMIT; 
END UpdateBankStatementActivity; 

最初のSQLコードスニペットのパラメータ値は、PL/SQLブロック内のパラメータと一致しています。

+0

私はこれがうまくいくと思います。アップデート前のデータ、アップデート実行(変数値を含む)、アップデート後のデータを掲載してください。私は働いていない単一の列が質問を説明するのに十分であると信じています。 – Aleksej

+0

mathguyは私が訂正したロジックを指摘し、エディタを介して更新を行います。しかし、パッケージを介して実行すると、テーブルは更新されていません...できるだけ早くサンプルを提供します。 – TheSchnitz

+0

@ TheSchnitz - パッケージ内のプロシージャのコードを変更して、すべてを再コンパイルしてください。それ以外の場合は、Oracleは引き続き「最後に正常終了」バージョンを使用します。 – mathguy

答えて

1

「更新しない」とはどういう意味ですか?

ネストされたcaseの式には明らかな論理的瑕疵があります。:btn = '1'です。つまり、を渡すたびに、「内部」case式の最初の枝は常にTRUEと評価されるため、「更新値」はnullになります。それはあなたが気づいている問題ですか?次に:overridden_amountの場合、結果は常にnullになります。 overridden_check_noの場合はnullとなる場合は、:btn = '2'の場合のみです。

"outer" case式は、簡単な式で使用するのと同じ構文で書くことができます(case :btn when '1' then case .... end else ... end)。

EDIT:変更された質問に(おそらく)回答します。私は論理全体を完全に辿ることができるとは確信していません。しかし、どのような例で起こっている(あなたがbtn = '1'でプロシージャを呼び出したと仮定すると、このです:

overridden_check_nooverridden_amountの両方が元のテーブルにnullているあなたは2つの列を確認し、両方の列のネストされた(内部)case式では。用語の一つがnullです!だから、case評価はelse句、またはときelsenullでデフォルトに、含まれていないに通じ低下すると、テストの=または!=のいずれかで。どちらもtrueあるザupdateが実際に動作しました。値がnullになりました。内側のcaseステートメントの「実際の分岐」はいずれもtrueと評価されていませんでした。

スタンドアロンSQL updateとしてエディタから直接実行すると、これは問題なく動作します。プロシージャのコードとエディタのコードが異なる場合を除いて、どうすればそれが可能か疑問に思っています。

+0

ありがとうございました。しかし、私はこれをエディタで単独でテストするとテーブルを更新するようですが、PL/SQLパッケージでこれを実行すると、テーブルは更新されません。 – TheSchnitz

+0

私は恥ずかしい気がします。私はちょうど私のエラーを発見した。私のテスト手順では、私は間違った量を渡して、特定のテストレコードを更新するために基本的にWHERE句が正しくないようにしました。手伝ってくれてどうもありがとう!謝罪。 – TheSchnitz