Markus: Oarcle - löschen von doppelten Datensätzen

hallo zusammen,

ich habe eine Tabelle mit zwei spalten und will nachträglich einen Primary Key definieren. Somit muß ich die doppelten Werte entfernen.
Hat vielleicht jemand eine kleine delete-Anweisung, die dies bewerkstelligt...

Vielen Dank für Eure Postings.

MfG,
Markus.

  1. yo,

    mach doch erst einmal eine neue tablle mit einer zusätzlichen spalte als ID feld (autoincrement) und lege darüber den primary key. dann kann man die datensätze auch unterscheiden und die überflüssigen datensätze auch löschen. so wie es jetzt ist kannst du ja die gleichen datensätze nicht unterschieden und somit auch nicht einzeln ansprechen.

    Ilja

    1. hey,
      danke für Deine Antwort, aber eine weitere Tabelle (z. B. temporär) will ich umgehen... ich bräuchte schon eine delete-anweisung mit entsprechender Unterabfrage!

      MfG,
      Markus.

      1. Servus,

        delete table tab where tab.id = (select max(id) from talbe tab1 where (select count(*) from tab1 ) > 1;

        So in etwa müsste es klappen.
        Auf Syntatkische Richtigkeit gebe ich wegen Zeitmangels keine Garantie.

        Gruss Matze

        1. Servus,
          danke, aber das isses noch ned ganz... Vielleicht hilft mir dies auch schon weiter :)
          Ich muß vielleicht dazu sagen, dass "gleiche Datensätze" wie folgt aussehen:

          Spalte1    |  Spalte2
          -----------------------
          ANALYSE    |  test
          ANALYSE    |  test
          ANALYSE    |  test

          Nun soll nur noch ein Datensatz stehen bleiben:
          Spalte1    |  Spalte2
          -----------------------
          ANALYSE    |  test

          Danke weiterhin...

          MfG,
          Markus.

          1. Servus,

            Spalte1    |  Spalte2

            ANALYSE    |  test
            ANALYSE    |  test
            ANALYSE    |  test

            Nun soll nur noch ein Datensatz stehen bleiben:
            Spalte1    |  Spalte2

            ANALYSE    |  test

            In dem fall gibt es 2 Möglichkeiten.
            entweder Du verwendest anstatt meiner Id die Rowid, die Oracle ohnehin liefert.
            Oder Du schreibst ein Scriopt drum herum, dass einmal alle gleichen Einträge ausliest, dann löscht und nur noch einmal diesen Entrag wieder in die Tabelle schreibt.

            Erkunde Dich mal darüber, wie man Datensätze bzw. Tabellen dazu zwingt keine Doppelten Datensätze zu erkauben.

            Gruss Matze

            1. hey,

              entweder Du verwendest anstatt meiner Id die Rowid, die Oracle ohnehin liefert.

              danke, das müßte klappen... :)

              Erkunde Dich mal darüber, wie man Datensätze bzw. Tabellen dazu zwingt keine Doppelten Datensätze zu erkauben.

              das ist nicht das Problem, sondern das Ziel.

              Vielen Dank auf jedenfall nochmal.

              MfG,
              Markus.

      2. Hallo,

        ich bezweifle, dass es mit einer einzelnen (adHoc) Delete-Anweisung (mit oder ohne SubSelect) funktionieren würde aus einer Quelle von variabel (mal 2, mal 1, ...) duplikativen Datensätzen (Duplikatseigenschaft erstreckt sich auch evt. über mehrere Spalten der Quelltabelle) immer nur die duplikate zu entfernen, sprich nur einen immer eindeutigen Datensatz von allen übrig zulassen.

        Oracle sollte doch wirklich temporäre Tabellen innerhalb einer Stored Procedure unterstützen, die danach wieder automatisch weg sind.

        Willst du das Datenbank-intern lösen -> dann führt wohl kein vernünftiger Weg an PL/SQL und einer StoredProcedure vorbei.
        Datenbank-extern, also eine "Sprache" wie PHP oder ASP interagiert mit der DB, gibt es auch sicher einen Weg, zwar imho nicht mit _einem_ adHoc Delete-Statement aber evt. mit einem Array, da dürfte es dann maximal eine Frage der Performance sein, falls das sehr oft vorkommen sollte.

        Wichtig bleibt aber dennoch, dass sich die Duplikate eindeutig identifizieren lassen müssen (über eine ID, nicht über die duplikativen Spalten)

        Gruß, Frank

        1. hey,
          vielen Dank für Deine ausführliche Anweisung...
          hab mir auch schon gedacht, dass es über ein einzelnes Stmt. nicht möglich ist, dies zu bewerkstelligen.
          Werde dann wohl oder übel eine temporäre Tabelle verwenden...

          Vielen Dank.

          MfG, Markus.

          1. yo markus,

            hast du überhaupt gelesen und die anweisung ausgeführt ???

            damit sollte es gehen....

            Ilja

            1. hey Ilja,

              hab ich natürlich gemacht... :(

              MfG,
              Markus.

              1. yo,

                und was ist bei der anweisung passiert, die ich dir gesagt habe über die rowid ?

                Ilja

                1. ohh... das Posting hab ich wohl übersehen... hab ich nicht getestet, sieht aber gut aus...
                  Vielen Dank.

                  MfG,
                  Markus.

                2. hey nochmal,

                  hat funktioniert... VIELEN Dank !

                  MfG,
                  Markus.

      3. yo,

        dann musst du über die rowid gehen, in etwa so.

        delete from tabelle where rowid not in (select min(rowid) from tabelle group by spalte1,spalte2);

        aber nicht vergessen, voher sichern. ;-)

        Ilja

      4. Hi Markus

        Wichtig, entweder an Testdaten ausprobieren oder vorher ein Backup machen! Ich hab es mangels Oracle (und im moment auch anderen Datenbanken) nicht getestet.

        DELETE
          FROM tabelle AS a
          WHERE 1 < (SELECT count(*)
                       FROM tabelle AS b
                       WHERE a.id = b.id)

        müsste es eigentlich tun. Das ganze löscht einen Datensatz wenn noch mindestens 2 mit der selben ID vorhanden sind. 2 deshalb, weil der aktuelle Datensatz ja schon einer ist und nur wenn noch ein zweiter gefunden wird, der hier gelöscht werden soll. Das ganze funktioniert nur, wenn es wirklich egal ist, welcher der Datensätze gelöscht werden soll.

        Gruss Daniela