Announcement

Collapse
No announcement yet.

ORA-01427: single-row subquery returns more than one row

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • ORA-01427: single-row subquery returns more than one row

    Hallo liebe SQL Gemeinde,

    ich habe das im Titel genannte Problem:
    ORA-01427: single-row subquery returns more than one row

    Was dieser Fehler bedeutet, ist mir an sich klar. Mein UPDATE-Statemant erhält mind. zwei Werte zurück und weis daher nicht welches es verwerten soll.

    Wie kann ich mein update derart einschränken, damit ich dieses Problem nicht mehr Habe?

    Hier Meine Fall Beschreibung:
    ERLÄUTERUNG:

    In der Tabelle GST_ZEITEN habe ich Vereinsmitglieder gespeichert. Aktive-Mitglieder (MNR_STAMM) und Familienmitglieder/Fördermitglieder (NR_intern) die einem Aktivien-Mitglied angehören.
    Für das Aktive_Mitglied(MNR_STAMM) gibt es eine Tätigkeits-Nummer (GST) mit den jeweiligen Zeiten (BEG_DATUM, END_DATUM) zu denen er diese Tätigkeit ausgeübt hat. Für die Familienmitglieder (NR_intern) gibt es bisher keinen GST Eintrag. Dies möchte ich ändern, in dem ich die GST des MNR_STAMM für den entsprechenden Zeitraum einem NR_intern zuorde.
    Hierzu habe ich eine temporäre Tabelle (tmp_gst_zeiten) erstellt, die eine Kopie der GST_ZEITEN ist.

    Die Tabllen enthalten jeweisl beide Mitglieder und sehen etwa so aus:
    für MNR_STAMM
    NR_intern = einmalige Mitgliedsnummer
    MNR_STAMM = 1 (Da selbst MNR_STAMM)
    GST = z.B. 4711
    BEG_DATUM = Beginn der Tätigkeit
    END_DATUM = Ende der Tätigkeit (kann auch NULL sein für aktuell)

    für NR_intern
    NR_intern = einmalige Mitgliedsnummer
    MNR_STAMM = Mitgliedsnummer des MNR_STAMM
    GST = 1 (da unbekannt)
    BEG_DATUM = Beginn der Tätigkeit
    END_DATUM = Ende der Tätigkeit (kann auch NULL sein für aktuell)


    SQL
    UPDATE GST_ZEITEN a
    set a.GST=
    (
    select DISTINCT tmp_gst_zeiten.GST from tmp_gst_zeiten
    where
    a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN AND
    tmp_gst_zeiten.MNR_STAMM like '1' AND
    tmp_gst_zeiten.GST <= '99999' AND
    (
    (a.END_DATUM IS NOT NULL AND
    tmp_gst_zeiten.END_DATUM IS NOT NULL AND
    a.END_DATUM >= tmp_gst_zeiten.BEG_DATUM AND a.END_DATUM <= tmp_gst_zeiten.END_DATUM)
    OR
    (a.END_DATUM IS NOT NULL AND
    tmp_gst_zeiten.END_DATUM IS NULL AND
    a.BEG_DATUM >= (SELECT DISTINCT max(tmp_gst_zeiten.BEG_DATUM) from tmp_gst_zeiten
    where a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN AND tmp_gst_zeiten.END_DATUM is NULL))
    OR
    (a.END_DATUM IS NULL AND
    tmp_gst_zeiten.END_DATUM IS NULL AND
    a.BEG_DATUM >= (SELECT DISTINCT max(tmp_gst_zeiten.BEG_DATUM) from tmp_gst_zeiten
    where a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN AND tmp_gst_zeiten.END_DATUM is NULL))
    OR
    (a.END_DATUM IS NULL AND
    tmp_gst_zeiten.END_DATUM IS NOT NULL AND
    a.BEG_DATUM >= tmp_gst_zeiten.BEG_DATUM AND a.BEG_DATUM <= tmp_gst_zeiten.END_DATUM)
    )
    )
    where a.GST = '1';




    PS: Wenn ich den Quelltext derart umgestallte, werden die Daten zwar aktuallisiert, allerdings allerdings falsch. Das GST der betreffenden Personen wird nicht von 1 auf das korekte GST gesetzt, sondern mit NULL überschrieben.

    UPDATE GST_ZEITEN a
    set a.GST=
    (
    select DISTINCT tmp_gst_zeiten.GST from tmp_gst_zeiten
    where
    a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN AND
    tmp_gst_zeiten.MNR_STAMM like '1' AND
    tmp_gst_zeiten.GST <= '99999' AND
    (
    (a.END_DATUM >= tmp_gst_zeiten.BEG_DATUM AND a.END_DATUM <= tmp_gst_zeiten.END_DATUM
    AND tmp_gst_zeiten.END_DATUM is not NULL)
    OR
    (tmp_gst_zeiten.END_DATUM is NULL AND
    a.BEG_DATUM = (SELECT max(tmp_gst_zeiten.BEG_DATUM) from tmp_gst_zeiten))
    )
    )
    where a.GST = '1';



    KANN MIR JEMAND HELFEN ????????????
    BITTE !!!

  • #2
    Was soll das Staement genau machen,?

    Comment


    • #3
      Das Statement soll den GST Schlüssel (Tätigkeit) der Familienmitglieder, welcher derzeit unbekannt ist und daher auf 1 steht updaten. Und zwar mit dem Inhalt der Spalte GST des dazugehörigen Hauptmitglieds.

      Comment


      • #4
        Das Problem deiner Abfrage ist, daß mehrere Datensätze als Antwort kommen könnten auch wenn es in der Praxis nicht vorkommt. Gruppiere doch die Ergebnisse (im deinem Fall deas eine Ergebnis).

        Comment


        • #5
          Originally posted by Rennfrikadelle View Post
          Das Statement soll den GST Schlüssel (Tätigkeit) der Familienmitglieder, welcher derzeit unbekannt ist und daher auf 1 steht updaten. Und zwar mit dem Inhalt der Spalte GST des dazugehörigen Hauptmitglieds.
          Hallo Rennfrikadelle,

          dann bräuchtest du doch nur eine Referenz über die Fremdschlüsselbeziehung (MNR_STAMM.NR_intern / NR_intern.MNR_STAMM) herstellen. Diese sollte dann natürlich eindeutig sein!
          Du hast allerdings noch eine Menge Bedingungen an die Felder END_DATUM und BEG_DATUM geknüpft (Die genaue Bedeutung hab ich noch nicht entschlüsselt). Also offensichtlich spielen diese beiden Felder für das Update auch eine Rolle.
          Du solltest dir mal ansehen, welche DS hier den ORA-01427 auslösen und dann überprüfen ob evtl. die Daten nicht ganz stimmig sind und korrigiert werden müssen oder ob deine Logik noch einer Ergänzung bedarf. Alles andere ist stochern im Nebel. (Ich zumindest hab keine Lust in deiner WHERE-Bedingung nach einem Fehler zu suchen ohne zu wissen was sie gewünschterweise liefern soll und welche Daten wann wie NULL sind (sein dürfen) oder nicht. )

          Gruß Falk
          Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

          Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

          Comment


          • #6
            Wie meinst du das mit Gruppieren?

            So wie das "Group by" bislang kenne habe ich es gerade versucht und den gleichen Effeckt erziehlt. Und mit dem Zusatz HEAVING weiss ich nicht, wie ich es auch nicht besser eingeschränken könnte. Das GST-Feld beinhaltet ja nur einen Schlüssel (also ein nomial skaliertes Merkmal und kein metrisches).

            Zudem:
            Eine merfach Aufzählung eines Ergebnisses dachte ich wird durch DISTINCT bereits unterdrückt.

            Und damit kein unterschiedliches Ergebnis herauskommt z.B. 4711 und 0815 habe ich die vier Möglichkeiten der Datumszuordnung in vier Klammern und der OR Verknüpfung abgearbeitet und die kritischen Fälle mit der Funktion max() abgefangen.

            denke ich zumindest.

            Comment


            • #7
              Hallo Falk,

              1.)
              Das mit dem Fremdschlüssel ist Aufgrund der von dir angesprochen Felder BEG_DAUTUM und END_DATUM nicht so einfach.
              Denn diese beiden Datumsfelder sind ebenfalls wie du schon sagst relevant.
              -> näheres in der Erläuterung (siehe unten)

              2).
              Die ORA_01427 wird mir angezeigt für:

              select DISTINCT tmp_gst_zeiten.GST from tmp_gst_zeiten
              *
              FEHLER in Zeile 4:
              ORA-01427: single-row subquery returns more than one row


              Mehr kann ich dazu auch noch nicht sagen.

              3.)
              Die Grunddaten habe ich bereits überprüft und doppelte Einträge eleminiert. Ansonsten sind diese stimmig.


              Vieleicht hilft diese Erläuterung:

              z.B. ein Hauptmitglied verschiedene Tätigkeiten zu verschieden Zeiten ausgeübt haben kann 01.01.2006 bis 31.03.2006 Tätigkeit A und vom 01.04.06 bis heute (also mit Wert NULL) Tätigkeit B.

              Das Familienmitglied kann zu unterschiedlichen Zeiten Mitglied gewesen z.B. 10.01.2006 bis 28.05.2006 und 05.08.2006 bis heute (also wieder Wert NULL)

              In diesem Fall hätte ich gerne das dem Familienmitglied für jeden. Zeitraum des Familienmitglieds die Tätigkeit der Hauptmitglieds zugeordnet , die dies zu ende der Mitgliedschaft des Famielenmitglieds ausgeübt hat. In diesm Beispiel wäre es für beide Zeiträume des Familienmitglieds die Tätigkeit aus dem Zeitraum 31.03.2006 bis heute des Hauptmitglieds.

              ---------------
              !?! Ich weis das ist alles etwas umständlich und ich erwarte garnicht, das mir jemand die Lösung fertig hintippt. Aber Anregungen an die man selbst noch nicht dachte helfen ja bereits manchmal.
              ---------------

              DANKE!

              Comment


              • #8
                Hallo Rennfrikadelle,

                jetzt kommen wir der Sache doch schon näher

                Originally posted by Rennfrikadelle View Post
                2).
                Die ORA_01427 wird mir angezeigt für:

                select DISTINCT tmp_gst_zeiten.GST from tmp_gst_zeiten
                *
                FEHLER in Zeile 4:
                ORA-01427: single-row subquery returns more than one row
                Das es um dieses Statement geht war mir klar, viel wichtiger ist an der Stelle: Welche DATEN sind da betroffen. Mglws. ist dein Statement unter den gen. Voraussetzungen richtig nur die Daten halten sich nicht daran

                Ich würde folgendes Machen:
                [highlight=sql]
                select tmp_gst_zeiten.GST
                from tmp_gst_zeiten,
                GST_ZEITEN a
                where a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN
                AND tmp_gst_zeiten.MNR_STAMM like '1'
                AND tmp_gst_zeiten.GST <= '99999'
                AND ((a.END_DATUM IS NOT NULL
                AND tmp_gst_zeiten.END_DATUM IS NOT NULL
                AND a.END_DATUM >= tmp_gst_zeiten.BEG_DATUM
                AND a.END_DATUM <= tmp_gst_zeiten.END_DATUM)
                OR (a.END_DATUM IS NOT NULL
                AND tmp_gst_zeiten.END_DATUM IS NULL
                AND a.BEG_DATUM >= (
                SELECT DISTINCT max(tmp_gst_zeiten.BEG_DATUM)
                from tmp_gst_zeiten
                where a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN
                AND tmp_gst_zeiten.END_DATUM is NULL))
                OR (a.END_DATUM IS NULL
                AND tmp_gst_zeiten.END_DATUM IS NULL
                AND a.BEG_DATUM >= (
                SELECT DISTINCT max(tmp_gst_zeiten.BEG_DATUM)
                from tmp_gst_zeiten
                where a.MNR_STAMM = tmp_gst_zeiten.NR_INTERN
                AND tmp_gst_zeiten.END_DATUM is NULL))
                OR (a.END_DATUM IS NULL
                AND tmp_gst_zeiten.END_DATUM IS NOT NULL
                AND a.BEG_DATUM >= tmp_gst_zeiten.BEG_DATUM
                AND a.BEG_DATUM <= tmp_gst_zeiten.END_DATUM)
                )
                GROUP BY tmp_gst_zeiten.GST
                HAVING COUNT(*) > 1
                [/highlight]
                Da sollten jetzt der oder die Datensätze (DS) rauskommen, die für den ORA-01427 verantwortlich sind. Diese müßtest du dir mal genauer ansehen und dann entscheiden was a) an den Daten oder b) an deiner Abfrage falsch ist.

                Gruß Falk
                Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

                Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

                Comment

                Working...
                X