*Markus: Subquery auf selbe Tabelle

Hallo,

wenn ich in MySQL folgendes schreibe....

  
INSERT INTO Themengebiet  
            (beschreibung, version) VALUES(?,  
                                   (SELECT MAX(version)+1 FROM Themengebiet)  
                                                                    );

..bekomme ich folgende Fehlermeldung:

You can't specify target table 'Themengebiet' for update in FROM clause

Daraufhin fand ich das hier (siehe ganz unten)...
http://dev.mysql.com/doc/refman/5.1/de/subquery-errors.html

Aber das ist doch gültiges SQL, oder?
Falls ja, und MySQL kann solche trivialen Dinge nicht, dann verstehe ich, dass MySQL den Ruf einer Spielzeugdatenbank hat.

Markus

--
  1. Hallo,

    wenn ich in MySQL folgendes schreibe....

    welche Version? Etwa den Release Candidate der 5.1, deren Handbuch Du verlinkst.

    INSERT INTO Themengebiet
                (beschreibung, version) VALUES(?,
                                       (SELECT MAX(version)+1 FROM Themengebiet)
                                                                        );

      
    nach diesem fehlerhaften Statement bekommst Du völlig unüberraschend ...  
      
    
    > ..bekomme ich folgende Fehlermeldung:  
    > You can't specify target table 'Themengebiet' for update in FROM clause  
      
    die dazu passende Fehlermeldung.  
      
    
    > Daraufhin fand ich das hier (siehe ganz unten)...  
    > <http://dev.mysql.com/doc/refman/5.1/de/subquery-errors.html>  
      
    Die deutsche Handbuchversion sollte man nach Möglichkeit vermeiden. Sie stiftet mehr Verwirrung als Erleuchtung :-)  
      
    
    > Aber das ist doch gültiges SQL, oder?  
      
    Hmm, nicht für MySQL. Nicht für den MS SQL-Server 2005.  
      
    
    > Falls ja, und MySQL kann solche trivialen Dinge nicht, dann verstehe ich, dass MySQL den Ruf einer Spielzeugdatenbank hat.  
      
    Wenn Du zweimal in einem Statement auf die gleiche Tabelle zugreifst und es sich dabei um zwei verschiedene Aspekte handelt, liegt es nahe einen Aliasnamen zu verwenden. Trivial, nicht wahr?  
      
      
    Freundliche Grüße  
      
    Vinzenz
    
    1. Hello,

      Wenn Du zweimal in einem Statement auf die gleiche Tabelle zugreifst und es sich dabei um zwei verschiedene Aspekte handelt, liegt es nahe einen Aliasnamen zu verwenden. Trivial, nicht wahr?

      Und dann ist es mit MySQL 5.x auch möglich, eine upzudatende Spalte im Subquery vorher mit select abzufragen? Das wäre ja super, wenn das funktioniert.

      Ich muss gestehen, dass ich das jetzt auch nicht hinbekomme mit den zwei Bereichen.
      Wäre nett, wenn Du einsolches Statement für Insert und für Update mit Selbstbezug mal vorführen könntest.

      Ich kriegs nicht hin.

      Liebe Grüße aus Syburg bei Dortmund

      Tom vom Berg

      --
      Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
    2. Hallo,

      Hmm, nicht für MySQL. Nicht für den MS SQL-Server 2005.

      Ich hab das Beispiel jetzt für PostgreSQL nachgebaut. Die Syntax funktioniert. Und ich bilde mir ein, dass ich es auch schon oft so in Oracle gemacht habe. (In der vorher genannten Syntax verbirgt sich zwar ein logischer Fehler, der jetzt aber nichts mit dieser Funktionalität zu tun hat. PostgreSQL hätte auch mein Ursprungsbeispiel ausgeführt.
      Die Abfrage hat allerdings alle version-Fehler aktualisiert, ich will aber nur ein bestimmtes, wodurch ich noch ein WHERE hinten drangehängt habe.
      )
      Dieses Beispiel funktioniert und ist gültiges SQL:

        
      CREATE TABLE Themengebiet  
        
            (t_id                  SERIAL NOT NULL PRIMARY KEY,  
        
             t_beschreibung        VARCHAR(150) NULL,  
             t_version      INTEGER NOT NULL default 0  
        
      );  
        
        
        
      CREATE UNIQUE INDEX XPKThemengebiet  
        
        ON Themengebiet  
        
      (  
        
      t_id  
        
      );  
        
        
        
        
      INSERT INTO Themengebiet (t_beschreibung, t_version) VALUES ('Thema Eins', 0);  
      INSERT INTO Themengebiet (t_beschreibung, t_version) VALUES ('thema Zwei', 0);  
        
        
      UPDATE Themengebiet set t_version = (SELECT t_version+1 FROM Themengebiet WHERE t_id='1') WHERE t_id='1';
      

      Markus

      --
      1. Moin!

        Warum so kompliziert?

        UPDATE Themengebiet set t_version = (SELECT t_version+1 FROM Themengebiet WHERE t_id='1') WHERE t_id='1';

        UPDATE Themengebiet SET t_version = t_version + 1 WHERE t_id = '1';

        Simpel, einfach, kein Subselect. Geht mit MySQL bis Version 3.23.anno!

        - Sven Rautenberg

        1. Hallo,

          UPDATE Themengebiet SET t_version = t_version + 1 WHERE t_id = '1';

          Simpel, einfach, kein Subselect. Geht mit MySQL bis Version 3.23.anno!

          Hmm, stimmt :)

          Markus

          --
        2. yo,

          Simpel, einfach, kein Subselect. Geht mit MySQL bis Version 3.23.anno!

          nur mal den hinweis, das der ursprungspost vom maximalwert der gesamten tabelle ausging und nicht von dem wert des datensatzes, dem ein update wiederfahren soll. das scheint selbt markus aus den augen verloren zu haben. also nichts ist mit einem einfachen update, es sei den, ich habe den sinn der ursprungspost nicht verstanden.

          mir fehlt auch der tipp, dass solche anweisung nicht in der session gekapselt sind.

          Ilja

      2. Hallo,

        Hmm, nicht für MySQL. Nicht für den MS SQL-Server 2005.

        Ich hab das Beispiel jetzt für PostgreSQL nachgebaut. Die Syntax funktioniert.

        ja und. Das sagt nichts für andere SQL-Dialekte aus. Schließe nicht von einem DBMS auf ein anderes.

        Dieses Beispiel funktioniert und ist gültiges SQL:

        Gültig in welchem Dialekt? Begreife bitte, dass die wenigsten nichttrivialen SQL-Statements portabel sind.

        UPDATE Themengebiet set t_version = (SELECT t_version+1 FROM Themengebiet WHERE t_id='1') WHERE t_id='1';[/code]

        zuerst INSERT, jetzt UPDATE? Wie soll ich das verstehen? Was hat es mit Deiner Ausgangsfrage zu tun?

        Die simple Variante für diese Anweisung hat Dir Sven ja bereits aufgezeigt.

        Freundliche Grüße

        Vinzenz