2017-03-14 7 views
0

Angenommen, ich habe die folgende Tabellenstruktur:Oracle mehrreihigen ‚einfügen, wenn nicht vorhanden‘ aus wählen Sie mit Tabelle verknüpft wörtliche

a (a_id number primary key, a_code varchar unique not null) 
b (b_id number primary key, a_id number foreign key references a(a_id), b_value varchar 

ich auf dem Tisch b ein paar hundert Paare von (a_id, b_value) einfügen müssen, wenn sie tun nicht bereits vorhanden, und die Information, die ich habe, ist (a_code, b_value). Ich komme aus einem Postgres-Hintergrund, wo dies trivial wäre, aber ich habe Probleme, einen Weg zu finden, es in Oracle abzuwickeln, ohne eine materialisierte Ansicht zu erstellen und anschließend zu löschen oder einen Insert pro Zeile auszuführen.

Dies waren die am wenigsten hässliche Lösung ich in der Lage war, um mit:

insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(b_value, iun_b_value) */ 
into b (b_id, a_id, b_value) 
select b_id.nextval, a_id, b_value 
from a 
inner join 

(select 'code1' a_code, 'value1' b_value from dual union all 
select 'code2' a_code, 'value2' b_value from dual union all 
select 'code3' a_code, 'value3' b_value from dual union all 
select 'code4' a_code, 'value4' b_value from dual) new 

on a.a_code = new.b_value 

Aber mir wurde gesagt, ich nicht, dass semantischer Hinweis für den Umgang mit doppelten Zeilen auf der Produktion verwenden kann, so habe ich versucht, dies:

merge into b using 
    (select a_id, b_value 
    from a inner join 

    (select 'code1' a_code, 'value1' b_value from dual union all 
    select 'code2' a_code, 'value2' b_value from dual union all 
    select 'code3' a_code, 'value3' b_value from dual union all 
    select 'code4' a_code, 'value4' b_value from dual) new 

    new on a.a_code = new.a_code) insert_codes 

on (insert_codes.a_code = b.a_code and insert_codes.b_value = b.b_value) 
when not matched then 
    insert (b.b_id, b.a_id, b.b_value) 
    values (b_id.nextval, insert_codes.a_id, 1, insert_codes.b_value) 

Aber ich bekomme die gleichen "ORA-00980: synonym translation is no longer valid" Fehler ich immer war, als ich ein Alias ​​in einem subselect Referenzierung während dieser mit einer where not exists Klausel zu lösen versuchen.

Gibt es eine Möglichkeit, dies ohne materialisierte Ansichten oder Mehrfacheinsätze zu tun?

Antwort

0

Ein Blick auf mein vereinfachtes Beispiel ließ mich erkennen, was falsch war. Die on Klausel war

on (insert_codes.a_code = b.a_code and insert_codes.b_value = b.b_value) 

aber es sollte

on (insert_codes.a_id = b.a_id and insert_codes.b_value = b.b_value) 

werden, so funktioniert das:

merge into b using 
    (select a_id, b_value 
    from a inner join 

    (select 'code1' a_code, 'value1' b_value from dual union all 
    select 'code2' a_code, 'value2' b_value from dual union all 
    select 'code3' a_code, 'value3' b_value from dual union all 
    select 'code4' a_code, 'value4' b_value from dual) new 

    new on a.a_code = new.a_code) insert_codes 

on (insert_codes.a_id = b.a_id and insert_codes.b_value = b.b_value) 
when not matched then 
    insert (b.b_id, b.a_id, b.b_value) 
    values (b_id.nextval, insert_codes.a_id, 1, insert_codes.b_value) 

Posting hier, falls jemand anderes hat Probleme weg ziehen die gleiche Art von Einsatz in der Zukunft.

+0

Die Frage ergibt keinen Sinn. Die Lösung macht Sinn, stimmt aber nicht mit Ihrer Frage überein. In der Frage, die Sie sagten, ist die Information, die Sie haben, '(a_code, b_value)'. Das macht keinen Sinn, weil es dir nicht sagt, an welche "a_id" das angehängt werden soll. In der Lösung verwenden Sie jedoch in der "korrigierten" on-Klausel "insert_codes.a_id". Also, haben Sie tatsächlich '(a_id, b_value)' und nicht '(a_code, b_value)' als Eingaben? Das würde alle Fragen beantworten. So haben Sie dem falschen Problem die richtige Lösung gegeben. – mathguy

+0

Ich habe vergessen zu erwähnen, dass es eine 1 zu 1 Relation zwischen 'a_id' und' a_code' gibt, meine schlechte (ich werde die Frage bearbeiten, um das zu reflektieren). 'a_code' ist ebenfalls eindeutig und nicht null, nur nicht der Primärschlüssel. Meine Literale, aliased als 'new', _are_' (a_code, b_value) 'Paare. Ich verbinde das mit der Tabelle "a", um die entsprechende 'a_id' für jedes' a_code'-Literal zu erhalten und so die '(a_id, b_value)' Paare zu erhalten, die ich einfügen möchte, und das Alias ​​_that_ als 'insert_codes'. Die "on" -Klausel der Zusammenführung war also fehlerhaft, weil ich auf ein Feld Bezug nahm, das keinen Sinn ergab und nicht einmal in "insert_codes" existierte. –

Verwandte Themen