Oracle - Hilfe bei Updatestatement

Nun bekomme ich folgende Meldung (bekam ich auch schon bei dem von mir geposteten Stmt!):
Code:
ORA-01427 Unterabfrage für eine Zeile liefert mehr als eine Zeile

Hier nochmal das Stmt mit welchem ich auf die Where-Klausel komme:

Code:
select * from Waizinger where not exists
(select 'x' from V_STANDORTE_GEO v where 
      (trim(v.STO_NR_SAM) = trim(Waizinger.gemnr)||'/'||trim(Waizinger.Sammler) 
      or trim(v.STO_NR_SAM) = trim(Waizinger.Sammler)
      )
      and v.SAMMLER_NR = 3 and v.gemnr  = Waizinger.gemnr)
and Waizinger.GPS_H is null
order by Waizinger.gemnr,Waizinger.Sammler

Hierbei bekomme ich ungefähr ~2400 Zeilen raus und eben jene möchte ich mit meinem Update-Stmt updaten.
 
offenbar liefert die Unterabfrage mehrere Ergebnisse, so dass die DB nicht entscheiden kann, welches davon verwendet werden soll. Man könnte mal versuchen, das Ergebnis der Subquery auf Eindeutigkeit zu prüfen, also etwa:

SQL:
select E_30019_DBK, NEU_MERC_X, NEU_MERC_Y, count(*)
  from (SELECT v.E_30019_DBK,
				       round(f_dms2mercatorx(TO_NUMBER(substr(w.GPS_E,1,2)),TO_NUMBER(substr(w.GPS_E,4,2)),60 * TO_NUMBER('0' || TO_CHAR(substr(w.GPS_E,6,4))) ) ,0) NEU_MERC_X,
				       round(f_dms2mercatory(TO_NUMBER(substr(w.GPS_N,1,2)),TO_NUMBER(substr(w.GPS_N,4,2)),60 * TO_NUMBER('0' || TO_CHAR(substr(w.GPS_N,6,4))) ) ,0) NEU_MERC_Y
				     FROM waizinger w, v_standorte_geo v
				     WHERE
				          (TRIM(v.STO_NR_SAM) = TRIM(w.gemnr)||'/'||TRIM(w.Sammler)
				                              OR TRIM(v.STO_NR_SAM) = TRIM(w.Sammler)
				          )
				          AND v.SAMMLER_NR = 3
				          AND v.gemnr  = w.gemnr
				          AND v.E_30019_DBK in (select dbk
				                                  from e_30019_save)
				          AND w.GPS_H IS NOT NULL)
 group by E_30019_DBK, NEU_MERC_X, NEU_MERC_Y
having count(*) > 1;

Allerdings muss ich gestehen, dass mich das letzte Stücke Code (diesmal mit NOT EXISTS) etwas verwirrt - bisher ging ich davon aus, dass es um eine EXISTS-Prüfung ginge. Sollte der Aktualisierungs-Prozess tatsächlich eher etwas unübersichtlich sein, wär's vielleicht eine Überlegung wert, ob man ihn nicht doch eher in Einzelschritte auflösen möchte (z.B. unter Verwendung temporärer Tabellen). Das entspricht zwar nicht der reinen Lehre (und könnte temporäre Sperren erforderlich machen, um die Konsistenz der Änderungen zu gewährleisten), hätte aber den Vorteil, dass man eher im Blick behalten könnte, ob die DML-Operation auch das tut, was man von ihr möchte.

Gruß

MP
 
Zuletzt bearbeitet von einem Moderator:
hi!
Hatte mich falsch ausgedrückt!
Folgendes beschreibt jene die vom Update ausgeschlossen werden sollen:
Code:
select * from Waizinger where not exists
(select 'x' from V_STANDORTE_GEO v where 
      (trim(v.STO_NR_SAM) = trim(Waizinger.gemnr)||'/'||trim(Waizinger.Sammler) 
      or trim(v.STO_NR_SAM) = trim(Waizinger.Sammler)
      )
      and v.SAMMLER_NR = 3 and v.gemnr  = Waizinger.gemnr)
and Waizinger.GPS_H is null
order by Waizinger.gemnr,Waizinger.Sammler

Demnach sollten jene Upgedadet werden:
Code:
select * from Waizinger where exists
(select 'x' from V_STANDORTE_GEO v where 
      (trim(v.STO_NR_SAM) = trim(Waizinger.gemnr)||'/'||trim(Waizinger.Sammler) 
      or trim(v.STO_NR_SAM) = trim(Waizinger.Sammler)
      )
      and v.SAMMLER_NR = 3 and v.gemnr  = Waizinger.gemnr)
and Waizinger.GPS_H is not null
order by Waizinger.gemnr,Waizinger.Sammler

Das ganze ist wirklich nicht sehr übersichtlich, zumal die benutzte View auf etliche Tabellen zugreift (und hiermit ist das ganze auch sehr sehr langsam) und zweitens die tabelle waizinger daten beinhaltet, welche von einem excel file eingespielt wurden (wurde nicht von mir eingegeben u ist nicht immer "regelkonform" - deshalb auch die TRIMs und concats).
Werde nun das Select mal ausführen und mal schauen was dabei rauskommt.

vielen dank derweil.

**EDIT**
So nun hab ich es endlich!
Die View liefert tatsächlich bei 5 Sätzen doppelte Werte, dies konnte ich nun mit einem
Code:
DISTINCT
ausräumen:

Code:
UPDATE e_30019_save e
  SET (e.geo_merc_x, e.geo_merc_Y) = 
        ( SELECT DISTINCT round(f_dms2mercatorx(TO_NUMBER(substr(w.GPS_E,1,2)),TO_NUMBER(substr(w.GPS_E,4,2)),60 * TO_NUMBER('0' || TO_CHAR(substr(w.GPS_E,6,4))) ) ,0) NEU_MERC_X,
                 round(f_dms2mercatory(TO_NUMBER(substr(w.GPS_N,1,2)),TO_NUMBER(substr(w.GPS_N,4,2)),60 * TO_NUMBER('0' || TO_CHAR(substr(w.GPS_N,6,4))) ) ,0) NEU_MERC_Y
               FROM waizinger w, v_standorte_geo v
               WHERE
                    (TRIM(v.STO_NR_SAM) = TRIM(w.gemnr)||'/'||TRIM(w.Sammler) 
                                        OR TRIM(v.STO_NR_SAM) = TRIM(w.Sammler)
                    AND v.SAMMLER_NR = 3
                    AND v.gemnr  = w.gemnr
                    )
                    AND e.dbk = v.E_30019_DBK
                    AND w.GPS_H IS NOT NULL
      ),
      e.geo_qual = 7,
      e.geo_naehe = 0,
      e.geo_upd_i_90023_id = 14,
      e.geo_upd = SYSDATE
WHERE EXISTS ( SELECT NULL
               FROM waizinger w, v_standorte_geo v
               WHERE
                    (TRIM(v.STO_NR_SAM) = TRIM(w.gemnr)||'/'||TRIM(w.Sammler) 
                                        OR TRIM(v.STO_NR_SAM) = TRIM(w.Sammler)
                    AND v.SAMMLER_NR = 3
                    AND v.gemnr  = w.gemnr
                    )
                    AND e.dbk = v.E_30019_DBK
                    AND w.GPS_H IS NOT NULL
      )

Nochmals vielen Dank für deine Hilfe, ich fühle mich nun richtig gestärkt im Thema Update ;) (habe einiges gelernt, kannte nur 0815 Update Stmts bisher).
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück