ORCALE 8 - doppelte Einträge

Hallo zusammen,

ich suche nach Möglichkeiten, mittels SQL doppelte Einträge aus Tabellen zu entfernen.

Bsp.:

Constraints sind nicht gesetzt, ein neuer Datensatz wird mit INSERT eingefügt, das INSERT-Statement wird mehrmals ausgeführt, Commit

Nun möchte ich mit einem Skript all jene Datensätze löschen, die doppelte Eingaben darstellen.

Gruß
JStefan

Hallo,

schau Dir mal die Statements an und probier sie aus.

Ciao, Uwe

Sätze anzeigen

select knr,aufnr
from auftrag_tmp
group by knr,aufnr
having count(*) > 1
;

Sätze löschen

Um auch eine DELETE Anweisung zu generieren, ist es möglich sich die MIN(ROWID) mitanzeigen zu lassen. Es wird vorausgesetzt, daß der erste Satz der gültige ist. Die DELETE Anweisung könnte wie folgt generiert werden:

select ‚delete from auftrag_tmp where aufnr = ’ ||
aufnr || ’ and rowid ‚‘‘ || min(rowid) || ‚‘’;’ as delete_record
from auftrag_tmp
group by knr,aufnr
having count(*) > 1
;


[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo zusammen,

Uwe hat den wesentlichen Trick schon beschrieben:

  • doppelte Datensätze mit GROUP BY identifizieren
  • den Datensatz mit MIN (ROWID) als „überlebenden“ verwenden

Geht auch in einem Aufwasch:

DELETE FROM beipielrelation
WHERE ROWID NOT IN
(SELECT MIN (ROWID)
FROM beipielrelation
GROUP BY attribut1, attribut2, …);

ciao,
Bernhard

Nochmal hallo!

Hier ein PL/SQL-Script (mit SQL*Plus ausführen), das entsprechende SQL-Statements für alle Tabellen des aktuellen User-Schemas kreiert…

ciao, Bernhard

------------------------------------------------------------------- Löschen von Tupelduplikaten im gesamten User-Schema

CREATE TABLE update_statements (
statement VARCHAR2 (2000)
)
/

DECLARE
v_statement VARCHAR2 (2000);
v_columns VARCHAR2 (2000);
v_firstcolumn BOOLEAN;
BEGIN
FOR cur_table IN (SELECT * FROM user_tables) LOOP
v_firstcolumn := TRUE;
FOR cur_columns IN
(SELECT * FROM user_tab_columns
WHERE table_name = cur_table.table_name
ORDER BY column_id) LOOP
IF v_firstcolumn THEN
v_firstcolumn := FALSE;
v_columns := cur_columns.column_name;
ELSE
v_columns := v_columns || ', ’ || cur_columns.column_name;
END IF;
END LOOP; – FOR cur_columns IN…

v_statement :=
'DELETE FROM ’ || cur_table.table_name ||
’ WHERE ROWID NOT IN (SELECT MIN (ROWID) FROM ’ || cur_table.table_name ||
’ GROUP BY ’ || v_columns || ‚);‘;

INSERT INTO update_statements VALUES (v_statement);
END LOOP; – FOR cur_table IN…
COMMIT;
END;
/

SET LINESIZE 2000
SET PAGESIZE 0
SET TRIMSPOOL ON
SPOOL c:\temp\update.sql
SELECT * FROM update_statements;
SPOOL OFF

Rem Jetzt c:\temp\update.sql anschauen & editieren, gfs. Einträge löschen
Rem Alles Ok? Dann Script ausführen…
Rem @c:\temp\update.sql