2009-06-15 14 views
32

Oto definicja procedury przechowywanej:Execute Immediate wewnątrz procedura przechowywana utrzymuje dając wystarczajÄ priviliges błąd

CREATE OR REPLACE PROCEDURE usp_dropTable(schema VARCHAR, tblToDrop VARCHAR) IS 
BEGIN 
    DECLARE v_cnt NUMBER; 
    BEGIN 
    SELECT COUNT(*) 
     INTO v_cnt 
     FROM all_tables 
    WHERE owner = schema 
     AND table_name = tblToDrop; 

    IF v_cnt > 0 THEN 
     EXECUTE IMMEDIATE('DROP TABLE someschema.some_table PURGE'); 
    END IF; 
    END; 
END; 

Oto wezwanie:

Z jakiegoś powodu, trzymam się niewystarczające przywraca błąd polecenia EXECUTE IMMEDIATE. Sprawdziłem online i okazało się, że błąd niewystarczających uprawnień zwykle oznacza, że ​​konto użytkownika Oracle nie ma uprawnień do polecenia użytego w zapytaniu, które jest przepustką, która w tym przypadku jest DROP. Mam jednak uprawnienia do upuszczania. Jestem naprawdę zdezorientowany i nie mogę znaleźć rozwiązania, które będzie dla mnie skuteczne.

Dziękuję z góry.

ROZWIĄZANIE:

Jak Steve wymienionych poniżej, model bezpieczeństwa Oracle jest dziwne, że to musi wiedzieć, wyraźnie gdzieś w procedurze jaką uprawnieniami do wykorzystania. Sposób, aby poinformować Oracle, że jest użycie słowa kluczowego AUTHID w instrukcji CREATE OR REPLACE. Jeśli chcesz mieć taki sam poziom przywilejów jak twórca procedury, użyj AUTHID DEFINER. Jeśli chcesz, aby baza danych Oracle korzystała z uprawnień użytkownika, który aktualnie uruchamia procedurę składowaną, chcesz użyć AUTORID CURRENT_USER. Deklaracja procedury wygląda następująco:

CREATE OR REPLACE PROCEDURE usp_dropTable(schema VARCHAR, tblToDrop VARCHAR) 
AUTHID CURRENT_USER IS 
BEGIN 
    DECLARE v_cnt NUMBER; 
    BEGIN 
    SELECT COUNT(*) 
     INTO v_cnt 
     FROM all_tables 
    WHERE owner = schema 
     AND table_name = tblToDrop; 

    IF v_cnt > 0 THEN 
     EXECUTE IMMEDIATE('DROP TABLE someschema.some_table PURGE'); 
    END IF; 
    END; 
END; 

Dziękuję wszystkim za odpowiedź. To był zdecydowanie bardzo irytujący problem, aby dostać się do rozwiązania.

+0

byłem stoi podobny problem, ale najśmieszniejsze jest bez użycia „Definer AUTHID” lub „AUTHID CURRENT_USER” Procedura wykonywał dla tabeli rozwijanej instrukcja, ale nie dla utworzenia tabeli. AUTHID rozwiązanie działa :) Dzięki! – Aniket

+0

Dzięki, te dwa słowa "AUTHID CURRENT_USER" rozwiązują mój problem! Dzięki! – Roman

Odpowiedz

15

Model zabezpieczeń Oracle jest taki, że podczas wykonywania dynamicznego SQL za pomocą polecenia Wykonaj natychmiast (w kontekście bloku lub procedury PL/SQL) użytkownik nie ma uprawnień do obiektów lub poleceń przyznawanych przy użyciu przypisania do roli. Twój użytkownik prawdopodobnie ma rolę "DBA" lub coś podobnego. Musisz jawnie przyznać temu użytkownikowi uprawnienia do "tabeli upuszczania". To samo by miało zastosowanie, gdybyś próbował wybierać z tabel w innym schemacie (takim jak system lub sys) - musisz przyznać temu użytkownikowi jawne uprawnienia SELECT dla tej tabeli.

+1

Dzięki za odpowiedź. Próbowałem 'WYKONAJ NATYCHMIAST (" NADAWANIE tabeli GRANT "|| nazwa_schematu || '.' || tblToDrop || 'TO ben');' , ale otrzymuję niepoprawny błąd uprawnień dla tej linii. Szukałem przywileju upuszczenia tabeli, ale nie mogę niczego znaleźć. Próbowałem wszystkich i "drop table", ale dostaję ten sam błąd. Czy wiesz, gdzie mogę znaleźć odpowiednią nazwę przywileju lub co robię źle tutaj? Dziękuję raz jeszcze. – tundal45

+1

Nie używaj polecenia WYKONAJ NATYCHMIAST aby przyznać przywilej.Musisz przyznać przywileje tabeli upuszczania dla BEN: GRANT DROP TABLE TO BEN –

+3

Steve, Właśnie to wymyśliłem. Okazuje się, że mogę zdefiniować uprawnienia w ramach procedury za pomocą AUTHID. Jeśli chcę mieć te same uprawnienia co twórca, używam AUTHID DEFINER. Jeśli chcę mieć uprawnienia bieżącego użytkownika, używam AUTHID CURRENT_USER. Oto jak wygląda procedura shell: utworzyć lub zamienić PROCEDURA some_procedure AUTHID CURRENT_USER JEST BEGIN DECLARE BEGIN END; KONIEC; – tundal45

0

Alternatywnie można przyznać użytkownikowi uprawnienia użytkownika DROP_ANY_TABLE, a procedura zostanie uruchomiona bez żadnych zmian. Niebezpiecznie może, ale zależy od tego, co robisz :)

+0

Poza tym rodzaj unieważnia powód posiadania przywilejów w pierwszej kolejności. Również "DROP_ANY_TABLE" jest mało prawdopodobne, aby w przypadku jakiejkolwiek korporacji o znacznej wielkości można było ją otrzymać w sposób produkcyjny. –

3

możesz użyć "AUTORYZOWANY CURRENT_USER" w treści swojej definicji procedury dla swoich wymagań.

2

Należy użyć tego przykładu z AUTHID current_user:

CREATE OR REPLACE PROCEDURE Create_sequence_for_tab (VAR_TAB_NAME IN VARCHAR2) 
    AUTHID CURRENT_USER 
IS 
    SEQ_NAME  VARCHAR2 (100); 
    FINAL_QUERY VARCHAR2 (100); 
    COUNT_NUMBER NUMBER := 0; 
    cur_id   NUMBER; 
BEGIN 
    SEQ_NAME := 'SEQ_' || VAR_TAB_NAME; 

    SELECT COUNT (*) 
    INTO COUNT_NUMBER 
    FROM USER_SEQUENCES 
    WHERE SEQUENCE_NAME = SEQ_NAME; 

    DBMS_OUTPUT.PUT_LINE (SEQ_NAME || '>' || COUNT_NUMBER); 

    IF COUNT_NUMBER = 0 
    THEN 
     --DBMS_OUTPUT.PUT_LINE('DROP SEQUENCE ' || SEQ_NAME); 
     -- EXECUTE IMMEDIATE 'DROP SEQUENCE ' || SEQ_NAME; 
     -- ELSE 
     SELECT 'CREATE SEQUENCE COMPTABILITE.' || SEQ_NAME || ' START WITH ' || ROUND (DBMS_RANDOM.VALUE (100000000000, 999999999999), 0) || ' INCREMENT BY 1' 
     INTO FINAL_QUERY 
     FROM DUAL; 

     DBMS_OUTPUT.PUT_LINE (FINAL_QUERY); 
     cur_id := DBMS_SQL.OPEN_CURSOR; 
     DBMS_SQL.parse (cur_id, FINAL_QUERY, DBMS_SQL.v7); 
     DBMS_SQL.CLOSE_CURSOR (cur_id); 
    -- EXECUTE IMMEDIATE FINAL_QUERY; 

    END IF; 

    COMMIT; 
END; 
/
Powiązane problemy