2012-01-25 11 views
5

W bazie danych Oracle mam klucz obcy, nie znając jego nazwy, tylko column_name i reference_column_name. Chcę napisać skrypt SQL, które powinno spaść ten klucz obcy jeśli istnieje, więc jest to kod używam:upuść indeks lub ograniczenie bez znajomości jego nazwy dla Oracle

declare 
fName varchar2(255 char); 
begin 
SELECT x.constraint_name into fName FROM all_constraints x 
JOIN all_cons_columns c ON 
c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'; 
end; 

Wyjście z tego skryptu jest „anonimowy bloku zakończone”, więc to było udane, ale kiedy dodać część drop:

declare 
fName varchar2(255 char); 
begin 
SELECT x.constraint_name into fName FROM all_constraints x 
JOIN all_cons_columns c ON 
c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'; 
if (fName != '') THEN 
    alter table MY_TABLE_NAME drop constraint fName; 
end if; 
end; 

Potem dostać ten jeden:

Error report: ORA-06550: line 9, column 5: PLS-00103: Encountered the symbol "ALTER" when expecting one of the following:

begin case declare exit for goto if loop mod null pragma raise return select update while with << close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe 06550. 00000 - "line %s, column %s:\n%s" *Cause: Usually a PL/SQL compilation error. *Action:

Więc może ktoś mi powiedzieć jaki jest problem?

Próbowałem też umieścić wszystko w funkcję:

declare 
    function getFName return varchar2 is 
    fName varchar2(255 char); 
    begin 
    SELECT x.constraint_name into fName FROM all_constraints x 
    JOIN all_cons_columns c ON 
    c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
    WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'; 

    return fName; 
    end; 
begin 
    if getFName() != '' then 
    alter table all_events drop constraint getFName(); 
    end if; 
end; 

Wynik był taki sam błąd spowodowany przez instrukcję „alter table”

Ten również nie pomogło:

alter table all_events drop constraint 
    (SELECT x.constraint_name into fName FROM all_constraints x 
    JOIN all_cons_columns c ON 
    c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
    WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'); 

Dane wyjściowe:

Error report: SQL Error: ORA-02250: missing or invalid constraint name 02250. 00000 - "missing or invalid constraint name" *Cause: The constraint name is missing or invalid. *Action: Specify a valid identifier name for the constraint name.

Dla serwera sql (MS SQL) jest tak łatwo to zrobić. Po prostu deklarując zmienną za pomocą @ i ustaw ją, po tym po prostu użyj jej. Na wyroczni nie mam pojęcia, co to nie działa ...

Odpowiedz

6

Twoja oryginalna wersja jest w większości poprawna, z tym, że nie możesz bezpośrednio uruchomić DDL w bloku PL/SQL; Raczej trzeba zawinąć go w EXECUTE IMMEDIATE:

execute immediate 'alter table MY_TABLE_NAME drop constraint "' || fName || '"'; 

Byłoby to prawdą, nawet jeśli nazwa-ograniczenia były znane w czasie kompilacji, ale to podwójnie prawdziwe w Twoim przypadku, ponieważ fName nie jest ograniczeniem -name, ale raczej zmienna zawierająca nazwę ograniczenia.

Również to:

if (fName != '') THEN 

jest niepoprawna/sensowne, ponieważ w Oracle '' oznacza NULL. Zamiast tego należy zamiast tego napisać:

.

+0

Hej właśnie dodatkowy pytanie o to: Z tego select teoretycznej chciałbym uzyskać nazwę więcej niż jedno ograniczenie, jeżeli w kolumnie C1 tabeli A1 odwołuje się do C2 tabeli A2 i C1 odsyła do C3 tabeli A3, więc otrzymam nazwy dla C1-> C2 i C1-> C3, więc pytanie, gdzie mogę dołączyć do informacji, do której kolumny jestem odwołując się ??? – radio

+0

@radio: Na 'all_constraints',' (r_owner, r_constraint_name) 'jest skutecznie obcym kluczem; możesz wrócić do 'all_constraints', aby uzyskać informacje o kolumnach, do których odnośnik się odnosił. (Wewnątrz Oracle, klucz obcy jest zaimplementowany jako klucz obcy dla * innego ograniczenia *. Ma to sens, gdy weźmiesz pod uwagę to, co DBMS musi zrobić, aby wymusić ograniczenie klucza obcego.) – ruakh

+0

@radio: Nawiasem mówiąc, twój "teoretyczny" niepokój trochę mnie martwi, ponieważ są inne, większe problemy z twoim kawałkiem kodu - na przykład, używasz 'all_constraints' i' all_cons_columns' bez sprawdzania 'owner' i nie sprawdzasz, czy 'MY_COLUMN_NAME'' jest jedyną kolumną w kluczu obcym. Więc twój kawałek kodu nie jest uniwersalny. Zakładałem, że planujesz użyć go w konkretnej sytuacji, w której masz dużo innych informacji, ale z jakiegoś powodu po prostu brakowało im nazwy ograniczenia. Jeśli potrzebujesz kodu ogólnego przeznaczenia, masz wiele rzeczy do naprawienia. – ruakh

2

To jest jak kropla wszystkie ograniczenia wpisane „R” dla kolumny:

begin 
    FOR rec IN (SELECT x.constraint_name fName FROM all_constraints x 
     JOIN all_cons_columns c ON 
     c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
     WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME') 
    LOOP 
     EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE_NAME DROP CONSTRAINT "' || rec.fName || '"'; 
    END LOOP; 
end; 
Powiązane problemy