ORA_ROWSCN היא עמודה ווירטואלית (Pseudocolumn) אשר מייצגת את נקודת הזמן האחרונה בה נעשה שינוי מסויים לשורה. עמודה זו היא חלופה נהדרת לפקודת ה ,SELECT FOR UPDATE  בצורה זו ניתן לשמור על עקביות מבלי לנעול את השורה. לדוגמא – נוכל להשתמש בה כאשר נרצה להבטיח כי עדכונים על שורה מסויימת יבוצעו על ערכה הנוכחי בלבד, אם ערכה השתנה כתוצאה מפעילות של סשן אחר – שורה זו כבר לא רלוונטית עבורנו.


נייצר טבלה ונתשאל אותה יחד עם עמודת ה
ORA_ROWSCN

HR >CREATE TABLE emp_test
AS SELECT * FROM employees WHERE rownum <= 5 ;

Table created.

HR >SELECT ora_rowscn, employee_id ,
last_name , first_name , salary , department_id
FROM emp_test ;

ORA_ROWSCN EMPLOYEE_ID LAST_NAME     FIRST_NAME               SALARY DEPARTMENT_ID

---------- ----------- ------------- -------------------- ---------- -------------

   2521095         119 Colmenares    Karen                      2503            30

   2521095         120 Weiss         Matthew                    8003            50

   2521095         121 Fripp         Adam                       8203            50

   2521095         122 Kaufling      Payam                      7903            50

   2521095         123 Vollman       Shanta                     6503            50



נבצע עדכון על אחת השורות ונצפה ב
ORA_ROWSCN החדש :

HR >UPDATE emp_test SET salary = salary + 1 WHERE employee_id = 119;

1 row updated.

HR >COMMIT ;

Commit complete.

HR >SELECT ora_rowscn, employee_id ,
last_name , first_name , salary , department_id
FROM emp_test ;

 

 

ORA_ROWSCN EMPLOYEE_ID LAST_NAME    FIRST_NAME               SALARY DEPARTMENT_ID

---------- ----------- ------------ -------------------- ---------- -------------

   2521095         119 Colmenares   Karen                      2504            30

   2521095         120 Weiss        Matthew                    8003            50

   2521095         121 Fripp        Adam                       8203            50

   2521095         122 Kaufling     Payam                      7903            50

   2521095         123 Vollman      Shanta                     6503            50

 

שימו לב כי ערך ה ORA_ROWSCN לא השתנה, באופן דיפולטיבי אורקל לא עוקב אחרי שינויי SCN עבור טרנסאקציות שנעשה להם COMMIT ברמת השורה. כדי לשנות זאת, נבנה את הטבלה מחדש יחד עם הפקודה ROWDEPENDENCIES 

 

HR >DROP TABLE emp_test ;

Table dropped.

HR >CREATE TABLE emp_test
ROWDEPENDENCIES
AS SELECT * FROM employees  WHERE rownum <= 5   ;

Table created.

HR >SELECT ora_rowscn, employee_id , last_name ,
first_name , salary , department_id
FROM emp_test ;

ORA_ROWSCN EMPLOYEE_ID LAST_NAME     FIRST_NAME               SALARY DEPARTMENT_ID

---------- ----------- ------------- -------------------- ---------- -------------

   2521141         119 Colmenares    Karen                      2503            30

   2521141         120 Weiss         Matthew                    8003            50

   2521141         121 Fripp         Adam                       8203            50

   2521141         122 Kaufling      Payam                      7903            50

   2521141         123 Vollman       Shanta                     6503            50

HR >UPDATE emp_test SET salary = salary + 1 WHERE employee_id = 119;

1 row updated.

HR >COMMIT ;

Commit complete.

HR >SELECT ora_rowscn, employee_id , last_name ,
first_name , salary , department_id
FROM emp_test ;

ORA_ROWSCN EMPLOYEE_ID LAST_NAME    FIRST_NAME               SALARY DEPARTMENT_ID

---------- ----------- ------------ -------------------- ---------- -------------

   2521155         119 Colmenares   Karen                      2504            30

   2521141         120 Weiss        Matthew                    8003            50

   2521141         121 Fripp        Adam                       8203            50

   2521141         122 Kaufling     Payam                      7903            50

   2521141         123 Vollman      Shanta                     6503            50

 

הפעם ניתן לראות כי ערך ה ORA_ROWSCN השתנה עבור אותה שורה.

להלן דוגמא בסיסית של קוד PLSQL אשר משתמש ביכולת ה ORA_ROWSCN על מנת לא לעדכן שורות אשר עודכנו כתוצאה מפעילות של סשן אחר.

DECLARE

   TYPE emp_rec_type IS RECORD

           (emp_id employees.employee_id%type,

           emp_rowscn number);

   TYPE emp_tab_type IS TABLE OF emp_rec_type INDEX BY binary_integer ;

   emp_tab emp_tab_type ;

BEGIN

   SELECT employee_id , ora_rowscn

   BULK COLLECT INTO emp_tab

   FROM employees

   WHERE department_id = 50 ;

   FOR i IN 1..emp_tab.count LOOP

  UPDATE employees

  SET salary = salary + 1

  WHERE employee_id = emp_tab(i).emp_id

  AND  ora_rowscn   = emp_tab(i).emp_rowscn ;

          IF sql%rowcount = 1 THEN 

              DBMS_OUTPUT.PUT_LINE     ('Update Successful - ' || emp_tab(i).emp_id);

              ELSE DBMS_OUTPUT.PUT_LINE('Update Failed - ' || emp_tab(i).emp_id || ' row updated              by another user');

  END IF;

  END LOOP ;

  COMMIT ; 

END ;