fbpx

כל תוכנית PLSQL רצה תחת סט השראות מסויים. באופן דיפולטיבי, רצה התוכנית תחת ההרשאות של היוזר אשר הגדיר אותה (Definer) ולחילופין, החל מגרסת 8i, תוכל לרוץ תחת ההרשאות של היוזר אשר מריץ אותה (Invoker).

לדוגמא – יוזר sales_1 מייצר פרוצדורה אשר נועדה לעדכן את טבלת הלקוחות בסכמה שלו,  את ההרשאות להרצת הפרוצדורה הוא מעביר ליוזר sales_2.
Definer Right – כאשר יוזר sales_2 מריץ את הפרוצדורה, באופן דיפולטיבי היא רצה תחת סט ההרשאות של היוצר שלה  sales_1. משמעות הדבר – ל sales_2 יש את היכולת לעדכן את טבלת הלקוחות של יוזר sales_1 באמצעות הפרוצדורה, עם זאת sales_2 לא יכול לעדכן את טבלת הלקוחות ישירות.
Invoker Right – כאשר יוזר sales_2 מריץ את הפרוצדורה, היא רצה תחת סט ההרשאות שלו. משמעות הדבר – לפרוצדורה לא יהיו את ההרשאות לעדכן את הטבלה השייכת ל sales_1, עם זאת אם ליוזר sales_2
תהיה טבלה תחת אותו שם, הפרוצדורה תוכל לשמש אותו.

Definer Right

תחת יוזר sales1 נייצר פרוצדורה בשם customers_proc על טבלת customers, באמצעות פרוצדורה זו נוכל להכניס שורה חדשה או לעדכן שורה קיימת בטבלה.

SYS > CONN sales1/sales1
Connected.
SALES1 >
SALES1 > DROP TABLE customers ;

Table dropped.

SALES1 >
SALES1 > CREATE TABLE customers
  2   (id number,
  3    name varchar2(25)) ;

Table created.

SALES1 >
SALES1 > CREATE OR REPLACE PROCEDURE customers_proc
  2  (p_code number, -- 1 is for insert, 2 is for update
  3   p_id   number,
  4   p_name varchar2)
  5  -- authid definer (By default Definer's rights)
  6  IS
  7  BEGIN
  8     IF p_code = 1 THEN
  9             INSERT INTO customers
 10             VALUES (p_id , p_name) ;
 11             DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' row was inserted');
 12     ELSIF p_code = 2 THEN
 13             UPDATE customers
 14             SET name = p_name
 15             WHERE id = p_id ;
 16             DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' rows was updated');
 17     END IF ;
 18  END ;
 19  /

Procedure created.

SALES1 >
SALES1 > SET SERVEROUTPUT ON
SALES1 >
SALES1 > EXEC customers_proc (1, 1, 'Moshe')
1 row was inserted

PL/SQL procedure successfully completed.

SALES1 >
SALES1 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         1 Moshe

SALES1 >
SALES1 > EXEC customers_proc (2, 1, USER)
1 rows was updated

PL/SQL procedure successfully completed.

SALES1 >
SALES1 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         1 SALES1

SALES1 >
SALES1 > COMMIT ;

Commit complete.

כעת ניתן את ההרשאות על הפרוצדורה ליוזר sales2

SALES1 > GRANT EXECUTE ON customers_proc TO sales2 ;

Grant succeeded.

SALES1 >
SALES1 > CONN sales2/sales2
Connected.
SALES2 >
SALES2 > SET SERVEROUTPUT ON
SALES2 >
SALES2 > EXEC sales1.customers_proc (1, 2, 'David')
1 row was inserted

PL/SQL procedure successfully completed.

SALES2 >
SALES2 > EXEC sales1.customers_proc (2, 2, USER)
1 rows was updated

PL/SQL procedure successfully completed.

SALES2 >
SALES2 > COMMIT ;

Commit complete.

SALES2 >
SALES2 > CONN sales1/sales1
Connected.
SALES1 >
SALES1 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         1 SALES1
         2 SALES2

ניתן לראות כי ליוזר sales2 יש גישה מלאה לטבלה באמצעות הפרוצדורה.

Invoker Right

כעת נחזור על התהליך, אך הפעם נגדיר את הפרוצדורה לרוץ תחת סט ההרשאות של היוזר אשר מריץ אותה. ניתן לראות כי עבור יוזר sales1 דברים נותרו כפי שהיו

SALES1 > CONN sales1/sales1
Connected.
SALES1 >
SALES1 > DROP TABLE customers ;

Table dropped.

SALES1 >
SALES1 > CREATE TABLE customers
  2   (id number,
  3    name varchar2(25)) ;

Table created.

SALES1 >
SALES1 > CREATE OR REPLACE PROCEDURE customers_proc
  2  (p_code number, -- 1 is for insert, 2 is for update
  3   p_id   number,
  4   p_name varchar2)
  5  AUTHID CURRENT_USER -- (Activate Invoker’s rights)
  6  IS
  7  BEGIN
  8     IF p_code = 1 THEN
  9             INSERT INTO customers
 10             VALUES (p_id , p_name) ;
 11             DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' row was inserted');
 12     ELSIF p_code = 2 THEN
 13             UPDATE customers
 14             SET name = p_name
 15             WHERE id = p_id ;
 16             DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' rows was updated');
 17     END IF ;
 18  END ;
 19  /

Procedure created.

SALES1 >
SALES1 > SET SERVEROUTPUT ON
SALES1 >
SALES1 > EXEC customers_proc (1, 1, 'Moshe')
1 row was inserted

PL/SQL procedure successfully completed.

SALES1 >
SALES1 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         1 Moshe

SALES1 >
SALES1 > EXEC customers_proc (2, 1, USER)
1 rows was updated

PL/SQL procedure successfully completed.

SALES1 >
SALES1 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         1 SALES1

SALES1 >
SALES1 > COMMIT ;

Commit complete.

כעת ניתן שוב את ההרשאות על הפרוצדורה ליוזר sales2

SALES1 > GRANT EXECUTE ON customers_proc TO sales2 ;

Grant succeeded.

SALES1 >
SALES1 > CONN sales2/sales2
Connected.
SALES2 >
SALES2 > SET SERVEROUTPUT ON
SALES2 >
SALES2 > EXEC sales1.customers_proc (1, 2, 'David')
BEGIN sales1.customers_proc (1, 2, 'David'); END;

*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SALES1.CUSTOMERS_PROC", line 9
ORA-06512: at line 1

SALES2 >
SALES2 > EXEC sales1.customers_proc (2, 2, USER)
BEGIN sales1.customers_proc (2, 2, USER); END;

*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SALES1.CUSTOMERS_PROC", line 13
ORA-06512: at line 1

SALES2 >
SALES2 > COMMIT ;

Commit complete.

SALES2 >
SALES2 > CREATE TABLE customers
  2   (id number,
  3    name varchar2(25)) ;

Table created.

SALES2 >
SALES2 > EXEC sales1.customers_proc (1, 2, 'David')
1 row was inserted

PL/SQL procedure successfully completed.

SALES2 >
SALES2 > EXEC sales1.customers_proc (2, 2, USER)
1 rows was updated

PL/SQL procedure successfully completed.

SALES2 >
SALES2 >
SALES2 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         2 SALES2

SALES2 >
SALES2 > CONN sales1/sales1
Connected.
SALES1 >
SALES1 > SELECT * FROM customers ;

        ID NAME
---------- -------------------------
         1 SALES1

SALES1 >

ניתן לראות כי הפעם יוזר sales2 לא יכל לגשת לטבלת sales1 למרות שקיבל הרשאה על הפרוצדורה, עם זאת ברגע שנוצרה תחת הסכמה שלו טבלה עם אותו שם, הפרוצדורה יכלה לשרת אותה.

 לסיכום

ב Definer Right נשתמש כאשר נרצה לתת את ההרשאות לטבלאות שלנו באמצעות תוכנית PLSQL ולא ישירות.
ב
Invoker Right נשתמש כאשר נרצה לייצר קוד גנרי אשר יוכל לשמש טבלאות בעלות אותו שם בסכמות שונות.