none
MS SQLServer Bug ? RRS feed

  • Frage

  • Hallo liebe Gemeinde,

     

    ich habe heute von einem Kollegen einen Hinweis auf einen möglichen SQLServer Bug bekommen. Es geht um folgendes Skript:

    CREATE TABLE Test (
    	my_id  VARCHAR(512)
    )
    INSERT INTO Test VALUES ('12345')
    INSERT INTO Test VALUES ('23456')
    
    
    CREATE TABLE Test_ToDelete (
    	my_key  INTEGER
    )
    INSERT INTO Test_ToDelete VALUES (100)
    INSERT INTO Test_ToDelete VALUES (101)
    INSERT INTO Test_ToDelete VALUES (102)
    INSERT INTO Test_ToDelete VALUES (103)
    INSERT INTO Test_ToDelete VALUES (104)
    
    

     

    Führt man nun die folgende Anweisung aus, stößt man richtigerweise auf einen Fehler:

    SELECT DISTINCT my_key FROM Test
    
    

     

    Will man aber fälschlicherweise ein DELETE auf die andere Tabelle machen und verwendet dasselbe Statement in einem Sub-Select, so wird kein Fehler ausgegeben:

    DELETE FROM Test_ToDelete WHERE my_key IN (
    	SELECT DISTINCT my_key FROM Test
    )
    

     

    Das erschreckende Ergebnis hiervon ist, dass alle Datensätze in der Tabelle "Test_ToDelete" kommentarlos gelöscht werden. Und das ist natürlich nicht das von mir erwartete Ergebnis. Wählt man einen anderen Spaltennamen als "my_key" (einen, den es in der Tabelle ebenfalls nicht gibt), so erscheint die Ausschrift, dass die Spalte in der Tabelle "Test" nicht vorhanden ist - was ja auch richtig ist...

     

    Kennt jemand dieses Problem?

     

    Dienstag, 17. August 2010 08:11

Antworten

  • Hallo,

    dabei handelt es sich um ein in SQL korrektes Verhalten,
    denn Verweise auf die äußere Tabelle sind für Unterabfragen zulässig -
    sonst wären sie weitgehend nutzlos.

    Deine Abfrage als SELECT wäre:

    SELECT * FROM Test_ToDelete
    WHERE my_key IN (SELECT DISTINCT Test_ToDelete.my_key FROM Test)
    
    
    (qualifiziert mit dem Tabellennamen, um es deutlicher zu machen).

    DELETE macht da keine Ausnahme - nur weils schmerzen könnte ;-)

    Sicherer ist es mit qualifzierten Spaltennamen zu arbeiten, wie oben gezeigt,
    oder auch mit EXISTS

    SELECT * FROM Test_ToDelete
    WHERE EXISTS (SELECT * FROM Test WHERE Test_ToDelete.my_key = Test.my_id)
    
    
    
    Gruß Elmar

    • Als Antwort vorgeschlagen Uwe RickenMVP Dienstag, 17. August 2010 09:20
    • Als Antwort markiert tanimania Dienstag, 17. August 2010 09:29
    Dienstag, 17. August 2010 09:00
    Beantworter

Alle Antworten

  • Hallo Tanimania,

    wow - ich kann den Fehler - genau, wie von Dir beschrieben - nachvollziehen.
    Ich lösche zwar nie Daten mittels SubSelect (ich verwende JOINS), dennoch sollte man da höllisch aufpassen.

    Eventuell hat ja tatsächlich noch jemand eine rationale Erklärung für dieses Phänomen.

    Ich würde Dir empfehlen, diese Information auch in das folgende Forum zu posten:

    http://social.microsoft.com/Forums/de-DE/partnersqlserver/threads

    Dort kümmert sich das MSFT in USA um solche Dinge.


    Uwe Ricken
    Microsoft Certified Database Administrator SQL Server 2005
    db Berater GmbH
    http://www.db-berater.de
    Dienstag, 17. August 2010 08:29
  • Hallo Uwe,

     

    ich komme leider in das Forum nicht rein. Er bringt mir diese freundliche Mitteilung:

    Sie sind nicht berechtigt, diese Aktion durchzuführen.



    :-)
    Dienstag, 17. August 2010 08:33
  • Hallo!

    Uwe Ricken schrieb:

    Eventuell hat ja tatsächlich noch jemand eine rationale Erklärung für dieses Phänomen.

    Bei folgender SQL-Anweisung wird es zu einer Fehlermeldung kommen:
      DELETE FROM Test_ToDelete   WHERE my_key IN (SELECT DISTINCT T.my_key FROM Test T)

    Wenn bei my_key im die Quelle nicht angegeben ist, könnte ich mir
    vorstellen, dass dort dann der Wert aus Test_ToDelete.my_key landet.

    ungefähr so:
    select    Test_ToDelete.my_key,    (SELECT DISTINCT my_key FROM Test T) as X from    Test_ToDelete

    mfg
    Josef

    Dienstag, 17. August 2010 08:58
  • Hallo,

    dabei handelt es sich um ein in SQL korrektes Verhalten,
    denn Verweise auf die äußere Tabelle sind für Unterabfragen zulässig -
    sonst wären sie weitgehend nutzlos.

    Deine Abfrage als SELECT wäre:

    SELECT * FROM Test_ToDelete
    WHERE my_key IN (SELECT DISTINCT Test_ToDelete.my_key FROM Test)
    
    
    (qualifiziert mit dem Tabellennamen, um es deutlicher zu machen).

    DELETE macht da keine Ausnahme - nur weils schmerzen könnte ;-)

    Sicherer ist es mit qualifzierten Spaltennamen zu arbeiten, wie oben gezeigt,
    oder auch mit EXISTS

    SELECT * FROM Test_ToDelete
    WHERE EXISTS (SELECT * FROM Test WHERE Test_ToDelete.my_key = Test.my_id)
    
    
    
    Gruß Elmar

    • Als Antwort vorgeschlagen Uwe RickenMVP Dienstag, 17. August 2010 09:20
    • Als Antwort markiert tanimania Dienstag, 17. August 2010 09:29
    Dienstag, 17. August 2010 09:00
    Beantworter
  • Alles klar. Hab ich verstanden. Damit ist das Problem vom Tisch!

     

    Danke und Grüße,

    Daniel

    Dienstag, 17. August 2010 09:18
  • Hallo,

    dabei handelt es sich um ein in SQL korrektes Verhalten,
    denn Verweise auf die äußere Tabelle sind für Unterabfragen zulässig -
    sonst wären sie weitgehend nutzlos.

    Deine Abfrage als SELECT wäre:

     

    SELECT * FROM Test_ToDelete
    
    WHERE my_key IN (SELECT DISTINCT Test_ToDelete.my_key FROM Test)
    
    
    
    
    (qualifiziert mit dem Tabellennamen, um es deutlicher zu machen).

     

    DELETE macht da keine Ausnahme - nur weils schmerzen könnte ;-)

    Sicherer ist es mit qualifzierten Spaltennamen zu arbeiten, wie oben gezeigt,
    oder auch mit EXISTS

     

    SELECT * FROM Test_ToDelete
    
    WHERE EXISTS (SELECT * FROM Test WHERE Test_ToDelete.my_key = Test.my_id)
    
    
    
    
    
    
    Gruß Elmar

     


    Hallo Elmar,

    herzlichen Dank für die Info - ich habe mir Ähnliches schon gedacht - konnte es nur nicht begründen.
    Dennoch - da glaubt man nach 12 Jahren bereits alles zu wissen und lernt dann doch immer wieder Neues ;-)

     


    Uwe Ricken
    Microsoft Certified Database Administrator SQL Server 2005
    db Berater GmbH
    http://www.db-berater.de
    Dienstag, 17. August 2010 09:22