Juergen: Update und Select in einer Anweisung

kurz und bündig, aber es geht nicht:

UPDATE tabelle1 SET ok=2, gemeindeschluessel_neu= (SELECT SUBSTRING(gemeindeschluessel,1,5) FROM tabelle1)

ich möchte etwas abfragen und sofort wieder in die Tabelle schreiben.

  1. Hallo Juergen,

    UPDATE tabelle1 SET ok=2, gemeindeschluessel_neu= (SELECT SUBSTRING(gemeindeschluessel,1,5) FROM tabelle1)
    

    Anders rum

    SELECT SUBSTRING(gemeindeschluessel,1,5) AS s FROM tabelle1 FOR UPDATE;
    UPDATE tabelle1 SET ok = 2, gemeindeschluessel_neu = s;
    

    ungetestet.

    Aber im allgemeinen ist das keine gute Idee, denn du hast jetzt redundante Daten vorliegen.

    Bis demnächst
    Matthias

    --
    Rosen sind rot.
    1. Aber leider kommt beim testen dann: Unknown column 's' in 'field list'

      1. Wenn ich allerdings das s gegen einen bekannten Spaltennamen austausche geht es. Do die Anweisung des SUBSTRING wird nicht ausgeführt, so als sie der Befehl überhaupt nicht da

        SELECT SUBSTRING(gemeindeschluessel,1,5) AS gemeindeschluessel FROM tabelle1 FOR UPDATE;
        UPDATE tabelle1 SET ok = 2, gemeindeschluessel_neu = gemeindeschluessel;
        
  2. Tach!

    kurz und bündig, aber es geht nicht:

    UPDATE tabelle1 SET ok=2, gemeindeschluessel_neu= (SELECT SUBSTRING(gemeindeschluessel,1,5) FROM tabelle1)
    

    Geht nicht, weil da nur ein einzelner Wert erwartet wird, das SELECT aber mehrere Zeilen liefert. Es ginge, wenn da eine Korrelation zur Haupttabelle wäre, aus der sich eine 1:1-Beziehung ergäbe.

    ich möchte etwas abfragen und sofort wieder in die Tabelle schreiben.

    In dem Fall ist das aber anders und einfacher, wenn du jede Zeile der Tabelle bearbeiten möchtest:

    UPDATE tabelle1 SET ok=2, gemeindeschluessel_neu= SUBSTRING(gemeindeschluessel,1,5);

    dedlfix.

    1. UPDATE at_orte SET ok=4, gemeindeschluessel_neu= SUBSTRING(gemeindeschluessel,1,5);

      und hier geht der Befehl SUBSTRING auch wieder.

      Super Danke

    2. UPDATE tabelle1 SET ok=2, gemeindeschluessel_neu= SUBSTRING(gemeindeschluessel,1,5);

      das ist wirklich die einfachste Lössung wenn es um ein Feld geht. Wenn aber das Feld aus einer anderen Tabelle kommt, geht es wiederum nicht. Ich denke der richtige Weg ist dann doch der erste…

      SELECT SUBSTRING(gemeindeschluessel,1,5) AS gemeindeschluessel FROM tabelle1 FOR UPDATE;
      UPDATE tabelle1 SET ok = 2, gemeindeschluessel_neu = gemeindeschluessel;
      

      und zwar dann wenn die SELECT Abfrage komplexer wird (für mich jedenfalls)

      SELECT b.ortschafts_kennziffer AS ortschafts_kennziffer  FROM tabelle1 a, tabelle2 b WHERE a.ok=4 AND a.gemeindeschluessel=b.gemeinde_kennziffer AND a.ort=b.ortschaftsname FOR UPDATE;
      UPDATE tabelle1 SET ok = 5, ort_schluessel = ortschafts_kennziffer;
      

      Nur zur besseren Verstehen! In der zweiten Tabelle sind auch die Ortsschluessel. Jeder Gemeinde hat eine Gemeindekennziffer, jede Gemeinde hat mehrere dazugehörige Orte, die unterschiedliche Ortsnummern, aber gemeinsamme Gemeindenummern haben.

      1. Tach!

        Wenn aber das Feld aus einer anderen Tabelle kommt, geht es wiederum nicht. Ich denke der richtige Weg ist dann doch der erste…

        Ja, aber wenn du eine Subquery mit Korrelation zur Hauptquery estellst, darf da nur genau ein Wert in der Subquery entstehen. Alternativ kann man auch Joinen. Aber da ergibt es auch keinen Sinn, wenn in der gejointen Tabelle mehrere Datensätze zu einem Datensatz der Haupttabelle verknüpft werden können.

        Allgemein kann ich noch den Tipp geben, statt Update zunächst ein SELECT zusammenzubauen, das all die Daten erst einmal auflistet, die geändert werden sollen. An der Ergebnismenge kannst du sehen, ob nicht etwa zu viel oder zu wenig oder falsche Daten genommen werden. Wenn das soweit gut aussieht, dann erst solltest du das Statement auf UPDATE umbauen.

        dedlfix.

      2. Könnt ihr mir bitte mal erklären, was ihr da treibt?

        Ich sehe dazwei Statements, das erste liefert ein Mengenergebnis, das zweite macht einen Mengen-Update. Ich bin mit IBM DB2 und MS SQL Server groß geworden, bei den beiden wäre es mir zumindest mal neu, dass

        • ein SELECT col AS name automatisch eine Variable anlegt (dafür braucht es DECLARE und vor allem eine Procedure bzw. Function). Mit AS name definiert man lediglich einen Column-Name für berechnete Ergebnisspalten.
        • diese Variable auch noch eine TABLE sein kann - das wäre in eurem Beispiel nötig, um alle Treffer aus dem SELECT in den UPDATE mitzunehmen
        • diese Table, die in der Variablen steht, 1:1 in einem Update-Statement für einen Mengen-Update verwendet werden kann (dazu müsste per WHERE eine Korrelation hergestellt werden).

        Aber ich könnte ja auch keine Ahnung von MySQL haben (hab ich bestimmt auch nicht). Also habe ich es ausprobiert (mit MySQL 5.6). Wie erwartet sagt mir der Update, dass er gemeindeschluessel nicht kennt. Entweder habe ich was übersehen (also WIRKLICH keine Ahnung), oder ihr philosophiert da über merkwürdige Dinge.

        Meine Antwort wäre diese gewesen:

        Um ein Feld in Tabelle A basierend auf Daten aus Tabelle B zu updaten, brauche ich eine SELECT Query, die mir aus einem Satz in Tabelle A eindeutig einen Satz in Tabelle B liefert. Wenn meine Zielspalte nullable ist, brauche ich weiter nichts zu tun. Ist sie es nicht, muss ich noch einen COALESCE drumherum setzen um einen Default zu haben.

        UPDATE tabelle1 a 
           SET ok = 5, 
               ort_schluessel = (SELECT ortschafts_kennziffer 
                                 FROM tabelle2 b
                                 WHERE a.gemeindeschluessel = b.gemeinde_kennziffer 
                                   AND a.ort = b.ortschaftsname)
        WHERE ok = 4
        

        Dieses Statement setzt voraus, dass der WHERE für tabelle2 maximal eine Row selektiert, andernfalls gibt's einen SQL Fehler.

        Rolf

  3. Moin Juergen,

    ich möchte etwas abfragen und sofort wieder in die Tabelle schreiben.

    wieso?

    Viele Grüße
    Robert