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 ברמת השורה. כדי לשנות זאת, נבנה את הטבלה מחדש יחד עם הפקודה <span dir="ltr" style="background-image: none;background-position: 0px 0px;line-height: 18pt"><span style="font-family: courier new"><span style="font-size: 12pt">ROWDEPENDENCIES</span></span></span>
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 ;