Supponiamo che io ho la seguente tabella con i seguenti vincoli:Convalida indice/vincolo univoco istruzione MERGE per riga o per istruzione?
create table test as (
select 1 as id, 'a' as name from dual
union all
select 2, 'b' from dual
union all
select 3, 'c' from dual
);
create unique index ind on test(name);
alter table test add constraint constr unique (name);
select * from test;
ID NAME
---------- ----
1 a
2 b
3 c
Supponiamo ora che faccio la seguente MERGE
:
merge into test t using (
select 4 as id, 'b' as name from dual
union all
select 2 as id, null as name from dual
) s on (s.id = t.id)
when matched then update set t.name = s.name
when not matched then insert(t.id, t.name) values(s.id, s.name)
select * from test;
ID NAME
---------- ----
1 a
2
3 c
4 b
disposta la sopra MERGE
mai fallire? Se è UPDATE
s prima, e quindi INSERT
s, l'indice/vincolo non verrà invalidato durante l'esecuzione. Ma se prima è INSERT
s, e quindi UPDATE
s, l'indice sarà temporaneamente invalidato e l'istruzione potrebbe fallire ?.
Qualcuno può spiegare in dettaglio (o indicare nella giusta direzione) in che modo Oracle RDBMS gestisce tali problemi? Inoltre, la gestione è la stessa quando si utilizza la clausola LOG ERRORS INTO
?
ragione principale per cui chiedo a questa domanda e il motivo per cui ho bisogno di una soluzione: ho FUSIONE dichiarazioni in esecuzione per diverse ore con errori accedere al clausola. La registrazione degli errori sembra funzionare come una transazione autonoma. Alcuni errori di vincoli univoci (basati su indici univoci) vengono registrati molto prima che l'istruzione finisca in aumento (tra gli altri, vedo che la sequenza sta salendo), e non so perché (anche se alla fine, dopo l'upsert, non dovrebbe esserci un vincolo univoco invalidato). Quando guardo la tabella ERROR, vedo ORA-00001: vincolo univoco (XXX.YYY) violato su un'operazione INSERT. Posso inserire questo record dalla tabella ERROR nella tabella principale senza causare un errore di vincolo univoco. Quindi mi chiedo perché l'errore viene registrato in primo luogo.
MODIFICA: Le risposte seguenti indicano che quando viene eseguita un'istruzione, i vincoli vengono applicati alla fine dell'istruzione. Comprendo e accetto (mentre vorrei conoscere maggiori dettagli sulla manutenzione degli indici in tali scenari). Quello che non capisco e il motivo per cui questa domanda non è ancora stata risolta è il motivo per cui sto avendo questi ORA-00001: gli errori violati del vincolo univoco (XXX.YYY) registrati mentre non dovrebbero essere. Sembra che il meccanismo di registrazione degli errori non si comporti in modo atomico.
EDIT2:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
Edit3: ho giocato un po 'ed è stato in grado di riprodurre questo errore:
drop table test;
drop table err_test;
create table test as (
select 1 as id, 'a' as name from dual
union all
select 2, 'b' from dual
union all
select 3, 'c' from dual
);
create unique index ind on test(name);
alter table test add constraint constr unique (name);
--select test.rowid, test.* from test;
BEGIN
DBMS_ERRLOG.CREATE_ERROR_LOG (
dml_table_name => 'TEST',
err_log_table_name => 'ERR_TEST');
END;
/
--truncate table err_test;
select * from err_test;
merge /*+ PARALLEL(t 2) */ into test t using (
select 4 as id, 'b' as name from dual
union all
select 2 as id, null as name from dual
) s on (s.id = t.id)
when matched then update set t.name = s.name
when not matched then insert(t.id, t.name) values(s.id, s.name)
LOG ERRORS INTO ERR_TEST('TEST,ID:'||s.id) REJECT LIMIT UNLIMITED;
select * from err_test;
Nell'ultimo select * from err_test;
ottengo sempre: ORA-00001: unique constraint (XXX.CONSTR) violated
. Ora la cosa strana è che la dichiarazione vera e propria fusione (in produzione) non lavorare in parallelo più, e ho ancora ottenere questo errore a volte ...
edit4: La migliore risposta che ho contrassegnato come accettato , anche se la domanda stessa non ha una risposta completa. Sembra che sia solo un bug in Oracle.
Quale versione di database esatto * è in esecuzione? Metalink contiene un paio di documenti sui bug relativi a MERGE e ORA-00001. –
Alos, hai provato a eseguire MERGE senza registrazione degli errori? Metalink 17449815 ("L'incoerenza dell'indice è stata osservata per un MERGE sql con un ramo UPDATE sia INSERT che e anche ERROR LOGGING (clausola LOG ERRORS INTO)") potrebbe essere rilevante. –
@FrankSchmitt Buona idea vederlo come un bug. La versione è 11.2.0.4.0. Lo esaminerò. Ho provato a eseguirlo senza la clausola ERROR LOGGING, ma non ho mai riscontrato alcun vincolo. È un ambiente di produzione, quindi non posso rimuovere la clausola indefinitamente. –