0

ストアドプロシージャでクエリを動的に作成して実行する必要があります。

2つのテーブルusersとuser_updatesがあります。

従業員テーブルにはemp_id, username, division, product, region, title etc.

Employee_updatesには次のような列がありますemp_id, effective_date, column_name, new_value etc.

基本的にこれが私がやりたいことです。

  1. 特定の発効日のuser_udatesテーブルに更新があるすべての従業員を取得します。

  2. 各従業員をループします。

  3. 指定された発効日の各従業員のすべての更新を取得します。従業員は、employee_updatesテーブルに1つまたは複数の更新がある場合があります。

  4. 次のような更新に基づいて動的な「UPDATE」クエリを作成します。

    update employee set col1 = new_val_1, col2 = new_val_2 where emp_id = ?

これは私がこれまでにしたことです

    create or replace
PROCEDURE SP_RUN_EMPLOYEE_UPDATES 
(
  IN_DATE IN DATE
) 
  IS
      
    update_sql varchar2(225); 
      
employee_id BI_EMPLOYEE_UPDATE.employee_id%TYPE;   

    CURSOR  employees 
        IS   SELECT distinct(employee_id)
               FROM BI_EMPLOYEE_UPDATE 
             WHERE EFFECTIVE_DATE = to_date(IN_DATE,'dd-mm-yy') 
              AND EXECUTED = 'N' AND ACTIVITY_ID = '0'
              ;
   
    CURSOR e_updates 
    IS  SELECT * 
         FROM BI_EMPLOYEE_UPDATE 
        WHERE EFFECTIVE_DATE = to_date(IN_DATE,'dd-mm-yy') 
         AND EXECUTED = 'N' 
         AND ACTIVITY_ID = '0' 
         and employee_id = employee_id ;
      
     BEGIN
      
   OPEN employees;
   LOOP
    FETCH employees into employee_id;
        EXIT WHEN employees%NOTFOUND;
            
           FOR e_update in e_updates
         update_sql :=  'UPDATE BI_EMPLOYEE SET ';
              LOOP
                -- create dynam,ic update statment
             
                 UPDATE BI_EMPLOYEE_UPDATE
                 SET EXECUTED = 'Y'
                 WHERE EMPLOYEE_UPDATE_ID = e_update.EMPLOYEE_UPDATE_ID ;
                
                END LOOP;
            
            -- run dynamic sql 
     
              END LOOP;
 CLOSE employees;
END;

助けてください。

4

1 に答える 1

4

ここには、次のようないくつかの問題があります。

  • IN_DATEは日付として宣言されているため、通過する必要はありませんTO_DATE()
  • 必要なカーソルループは1つだけです。employee_id何らかの理由ですべての更新を一緒に処理する場合は、order by句を追加できます。
  • 動的SQLはまったく必要ありません。静的SQL更新の一部としてカーソルからの値を使用できます。

したがって、単一のループを持つ単純なバージョンは、次のようになります。

CREATE OR REPLACE PROCEDURE sp_run_employee_updates (p_date IN DATE) IS
    CURSOR c_updates IS
        SELECT *
        FROM bi_employee_update
        WHERE effective_date = p_date
        AND executed = 'N' 
        AND activity_id = '0'
        FOR UPDATE;     
BEGIN
    -- loop around all pending records
    FOR r_update IN c_updates LOOP
        -- apply this update to the bi_employee record
        UPDATE bi_employee
        SET col1 = r_update.col1, col2 = r_update.col2
        WHERE emp_id = r_update.employee_id;

        -- mark this update as executed
        UPDATE bi_employee_update
        SET executed = 'Y'
        WHERE CURRENT OF c_updates;
    END LOOP;
END sp_run_employee_updates;

これは、for updateandwhere current of構文を使用して、作業中の行をロックし、更新を簡素化します。こちらのドキュメントを参照してください。

どちらかeffective_dateまたはp_date時間コンポーネントがある場合、それらは一致しないことに注意してください。の可能性は低いですp_dateが、を推測するのは困難ですeffective_date。もしそうなら、あなたはそれをする必要があるかtrunc()、またはbetween時間を範囲を探すために使用します。

于 2012-09-11T13:43:27.157 に答える