2016-08-29 6 views
0

2番目のテーブルの更新された値で1つのテーブルの値を更新しようとしています。しかし、私は最初のテーブルのMODIFIED_BYとMODIFIED_ON列を更新しておりますので、私は唯一の更新された値がある行更新する:条件付き相関更新

UPDATE SAFETY_ADMIN.SAFETY_USERS tbl1 
    SET (SUPERVISOR_ID,DEPT_ID,USER_ID,EMPLOYEE_TYPE,EMPLOYEE_NAME,EMAIL,MODIFIED_BY,MODIFIED_ON) = 
(
    SELECT SAFETY_ADMIN.FN_GETSUPERVISORID(tbl2.SUPID),CAST(tbl2.DEPTID AS NUMBER(19)),UPPER(SUBSTR(tbl2.EMAIL,1,INSTR(tbl2.EMAIL,'@')-1)),tbl2.EMPTYPE,tbl2.EMPNAME,tbl2.EMAIL,SYS_CONTEXT('USERENV', 'OS_USER'),CURRENT_TIMESTAMP 
    FROM PS_LOAD.EMPLOYEEDATA tbl2 
    WHERE tbl1.EMPLOYEE_ID = CAST(tbl2.EMPID AS NUMBER(19)) AND 
    (
    tbl1.SUPERVISOR_ID <> SAFETY_ADMIN.FN_GETSUPERVISORID(tbl2.SUPID) OR 
    tbl1.DEPT_ID <> CAST(tbl2.DEPTID AS NUMBER(19)) OR 
    tbl1.USER_ID <> UPPER(SUBSTR(tbl2.EMAIL,1,INSTR(tbl2.EMAIL,'@')-1)) OR 
    tbl1.EMPLOYEE_TYPE <> tbl2.EMPTYPE OR 
    tbl1.EMPLOYEE_NAME <> tbl2.EMPNAME OR 
    tbl1.EMAIL <> tbl2.EMAIL 
) 
); 

をしかし、私のクエリは、NULL値でDEPT_IDを更新文句ヌル値は存在しません。私はWHERE条件を間違った場所に置いていると感じています。私はSQL Serverのより多くの人です。誰かがOracleでこれを行う方法を教えてもらえますか?他のテーブルからデータを取得する必要がOracleのアップデートで

答えて

1
私はあなたが where exists句を追加する場合、それはあなたのために働くべきだと思い

...

UPDATE SAFETY_ADMIN.SAFETY_USERS tbl1 
    SET (SUPERVISOR_ID,DEPT_ID,USER_ID,EMPLOYEE_TYPE,EMPLOYEE_NAME,EMAIL,MODIFIED_BY,MODIFIED_ON) = 
(
    SELECT SAFETY_ADMIN.FN_GETSUPERVISORID(tbl2.SUPID),CAST(tbl2.DEPTID AS NUMBER(19)),UPPER(SUBSTR(tbl2.EMAIL,1,INSTR(tbl2.EMAIL,'@')-1)),tbl2.EMPTYPE,tbl2.EMPNAME,tbl2.EMAIL,SYS_CONTEXT('USERENV', 'OS_USER'),CURRENT_TIMESTAMP 
    FROM PS_LOAD.EMPLOYEEDATA tbl2 
    WHERE tbl1.EMPLOYEE_ID = CAST(tbl2.EMPID AS NUMBER(19)) AND 
    (
    tbl1.SUPERVISOR_ID <> SAFETY_ADMIN.FN_GETSUPERVISORID(tbl2.SUPID) OR 
    tbl1.DEPT_ID <> CAST(tbl2.DEPTID AS NUMBER(19)) OR 
    tbl1.USER_ID <> UPPER(SUBSTR(tbl2.EMAIL,1,INSTR(tbl2.EMAIL,'@')-1)) OR 
    tbl1.EMPLOYEE_TYPE <> tbl2.EMPTYPE OR 
    tbl1.EMPLOYEE_NAME <> tbl2.EMPNAME OR 
    tbl1.EMAIL <> tbl2.EMAIL 
) 
) where exists 
(
    SELECT 1 
    FROM PS_LOAD.EMPLOYEEDATA tbl3 
    WHERE tbl1.EMPLOYEE_ID = CAST(tbl3.EMPID AS NUMBER(19)) AND 
    (
    tbl1.SUPERVISOR_ID <> SAFETY_ADMIN.FN_GETSUPERVISORID(tbl3.SUPID) OR 
    tbl1.DEPT_ID <> CAST(tbl3.DEPTID AS NUMBER(19)) OR 
    tbl1.USER_ID <> UPPER(SUBSTR(tbl3.EMAIL,1,INSTR(tbl3.EMAIL,'@')-1)) OR 
    tbl1.EMPLOYEE_TYPE <> tbl3.EMPTYPE OR 
    tbl1.EMPLOYEE_NAME <> tbl3.EMPNAME OR 
    tbl1.EMAIL <> tbl3.EMAIL 
) 
+0

これはまさに私が探していたもので、期待どおりに動作しました! :)あまりにもPL/SQLがひどいです。このクエリはMS SQL Serverの半分のサイズになります。 –

+1

@David:PL/SQLはありません。 SQLのみ。 – sstan

+0

@DavidPは 'NULL'値を監視します。たとえば、 'SAFETY_USERS'で' EMAIL'が 'NULL'で、' EMPLOYEEDATA'に値がある場合、行は更新されません。 –

1

一般的にはるかに短いMERGEを使用して書かれていますコ関連サブクエリ

MERGE INTO safety_admin.safety_users su 
USING (
    SELECT safety_admin.fn_getsupervisorid(ed.supid) as supervisor_id, 
     to_number(ed.deptid) as deptid, 
     to_number(ed.empid) as empid, 
     upper(substr(ed.email,1,instr(ed.email,'@')-1)) as user_id, 
     ed.emptype, 
     ed.empname, 
     ed.email, 
     ed.empid 
    FROM ps_load.employeedata ed 
) t ON (su.employee_id = t.empid) 
WHEN MATCHED THEN UPDATE 
    SET (supervisor_id, dept_id, user_id, employee_type, employee_name, email, modified_by, modified_on) 
    = (t.supervisor_id, t.deptid, t.email, t.emptype, t.empname, sys_context('userenv', 'os_user'), current_timestamp) 
WHERE (su.supervisor_id <> t.supervisor_id OR 
     su.dept_id <> t.deptid OR 
     su.user_id <> user_id OR 
     su.employee_type <> t.emptype OR 
     su.employee_name <> t.empname OR 
     su.email <> t.email); 

でプレーンUPDATEように私はset (a,b,c,) = (....)は、MERGEのSET部分に有効である完全にわかりません。それでも問題が解決しない場合は、各列を個別に指定する必要があります。

varcharを数値に変換するには、少し長めのcast()オペレータの代わりにto_number()を使用します。

Oracleにはすべて大文字で書く必要はなく、SQLでは大文字と小文字が区別されません。

関連する問題