質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

PL/SQL

PL/SQL (Procedural Language/Structured Query Language) はOracle CorporationによるSQL(非手続き型言語)を手続き型言語に拡張させるために開発されたプログラミング言語です。

Q&A

1回答

747閲覧

効率的なupdate文

tika5711

総合スコア14

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

PL/SQL

PL/SQL (Procedural Language/Structured Query Language) はOracle CorporationによるSQL(非手続き型言語)を手続き型言語に拡張させるために開発されたプログラミング言語です。

0グッド

0クリップ

投稿2021/05/06 23:34

編集2021/05/06 23:47

UPDATE文について勉強中です。
あるテーブルから数万件のデータを抽出定し、抽出したレコードに更新を行うのですが、更新列の更新後の値から別の列の計算を行う必要があります。

例として、

  • TBL_SALARYからEMP_IDが9以下のレコードを抽出する。
  • HIRE_DATEが20051299以下の場合はPRICEを800、でない場合はPRICEを750にする。
  • TIMEは仮に一律90に設定する。
  • PRICE×TIMEでSALARYを更新する。

この場合に思いつく方法は3パターンあるのですが、出来る事ならAパターンのように計算式をSALARY列に書くのは手間・不具合を招きそうですし、Bパターンだと更新処理を2回走らせるのでコスト増と考えています。パターンCは書く量が多くなりますが、やりたい事は満たせています。

他に良い方法があれば教えて下さい。
よろしくお願いいたします。

CREATE TABLE TBL_SALARY ( EMP_ID NUMBER(3) ,EMP_NAME VARCHAR2(30) ,HIRE_DATE NUMBER(8) ,PRICE NUMBER(4) ,TIME NUMBER(3) ,SALARY NUMBER(6) ) / INSERT INTO TBL_SALARY VALUES (1, 'A', 20010101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (2, 'B', 20020101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (3, 'C', 20030101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (4, 'D', 20040101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (5, 'E', 20050101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (6, 'F', 20060101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (7, 'G', 20070101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (8, 'H', 20080101, 0, 0, 0); INSERT INTO TBL_SALARY VALUES (9, 'I', 20090101, 0, 0, 0); COMMIT; / -- <<パターンA>> UPDATE TBL_SALARY TBL SET PRICE = (CASE WHEN HIRE_DATE <= 20051299 THEN 800 ELSE 750 END) ,TIME = 90 ,SALARY= ((CASE WHEN HIRE_DATE <= 20051299 THEN 800 ELSE 750 END)*90) WHERE EMP_ID <= 9 ; -- <<パターンB>> -- 更新その1 UPDATE TBL_SALARY TBL SET PRICE = (CASE WHEN HIRE_DATE <= 20051299 THEN 800 ELSE 750 END) ,TIME = 90 WHERE EMP_ID <= 9 ; -- 更新その2 UPDATE TBL_SALARY TBL SET SALARY = PRICE * TIME WHERE EMP_ID <= 9 ; -- <<パターンC>> DECLARE CURSOR C_SALARY IS SELECT * FROM TBL_SALARY ; TYPE TY_SALARY IS TABLE OF TBL_SALARY%ROWTYPE ; RC_SALARY TY_SALARY; WK_PRICE TBL_SALARY.PRICE%TYPE; WK_TIME TBL_SALARY.TIME%TYPE; WK_SALARY TBL_SALARY.SALARY%TYPE; BEGIN OPEN C_SALARY; LOOP FETCH C_SALARY BULK COLLECT INTO RC_SALARY LIMIT 1000; EXIT WHEN RC_SALARY.COUNT = 0; FOR i IN 1..RC_SALARY.COUNT LOOP IF (RC_SALARY(i).HIRE_DATE <= 20051299) THEN WK_PRICE := 800; ELSE WK_PRICE := 750; END IF; WK_TIME := 90; WK_SALARY := WK_PRICE * WK_TIME; UPDATE TBL_SALARY TBL SET PRICE = WK_PRICE ,TIME = WK_TIME ,SALARY = WK_SALARY WHERE TBL.EMP_ID = RC_SALARY(i).EMP_ID ; END LOOP; END LOOP; CLOSE C_SALARY; DBMS_OUTPUT.PUT_LINE('COMMIT'); COMMIT; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); ROLLBACK; END; /

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

Aパターンで。

出来る事ならAパターンのように計算式をSALARY列に書くのは手間・不具合を招きそうですし

そう思うのであれば、計算式部分をストアドファンクションまたはトリガーにすれば良いかと思います。
また、定義が変更になりますが、仮想列で定義すれば項目の更新は不要になります。

投稿2021/05/07 01:50

編集2021/05/17 01:58
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問