2012-01-25 22 views
5

oracleデータベースでは、名前がわからず、外部キーがあり、column_nameとreference_column_nameだけがあります。 私はそれが存在する場合は、この外部キーをドロップする必要があるSQLスクリプトを書きたいので、これは私が使用するコードです: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; 

、このスクリプトの出力は、「完了無名ブロック」であるので、それが成功しました私はドロップ一部追加したときしかし:

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; 

をそれから私は、このいずれかを取得する:

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:

だから、誰もが、問題はここにあるものを私に伝えることができますか?

私はまた、機能にすべてを入れてみました:

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; 

結果は声明によって引き起こさ同じエラーでした

の「ALTER TABLE」がこの1も助けにはならなかった。

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'); 

出力は:

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.

SQL Server(MS SQL)の場合は、これを簡単に実行できます。変数を@で宣言し、それを設定した後は、それを使ってください。オラクルでは、それが動作していないという手がかりはありません。

答えて

6

PL/SQLブロックでDDLを直接実行することはできません。むしろ、あなたはEXECUTE IMMEDIATEでそれをラップする必要があります。

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

これはfNameは制約ではありませんので、制約名は、コンパイル時に知られているが、それはあなたのケースで二重に本当れた場合も同様になります-nameではなく、constraint-nameを含む変数。

はまた、この:オラクル''NULLを意味するので

if (fName != '') THEN 

は、意味のある/有効ではありません。代わりに、

IF fName IS NOT NULL THEN 

と記述してください。

+0

ねえこのことについてだけ追加質問:私は、カラムC1場合は、複数の制約名になるだろう理論上のこのselect文でテーブルA1のテーブルC2のC2への参照とテーブルA3のC3へのC1の参照があるので、C1-> C2とC1-> C3の名前を取得するので、質問はどこにあるのですか?参照して??? – radio

+0

@ラジオ: 'all_constraints'では、'(r_owner、r_constraint_name) 'は実質的には外部キーです。 'all_constraints'に再び参加して、参照される列に関する情報を取得することができます。 (Oracleの内部では、外部キーは別の制約*への外部キーとして実装されています。これは、外部キー制約を実施するためにDBMSが何を行う必要があるかを検討するときに意味があります。) – ruakh

+0

@radio:ちなみに、あなたの "理論的な"懸念は少し心配です。あなたのコードには他にも大きな問題があります。たとえば、 'owner'をチェックせずに' all_constraints'と 'all_cons_columns'を使います。 'MY_COLUMN_NAME''が外部キーの唯一の列であることを確認することはしません。だからあなたのコードのビットは一般目的ではありません。私はあなたが他の多くの情報を持っている特定の状況でそれを使用することを計画していたと仮定していましたが、なんらかの理由で制約名が不足していました。汎用コードが必要な場合は、修正するべきことがたくさんあります。 – ruakh

2

これは列に「R」と入力すべての制約を削除する方法です:

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; 
関連する問題