Benutzer mit den meisten Antworten
MS SQLServer Bug ?

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?
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:(qualifiziert mit dem Tabellennamen, um es deutlicher zu machen).SELECT * FROM Test_ToDelete WHERE my_key IN (SELECT DISTINCT Test_ToDelete.my_key FROM Test)
DELETE macht da keine Ausnahme - nur weils schmerzen könnte ;-)
Sicherer ist es mit qualifzierten Spaltennamen zu arbeiten, wie oben gezeigt,
oder auch mit EXISTSGruß ElmarSELECT * FROM Test_ToDelete WHERE EXISTS (SELECT * FROM Test WHERE Test_ToDelete.my_key = Test.my_id)
- Als Antwort vorgeschlagen Uwe RickenMVP Dienstag, 17. August 2010 09:20
- Als Antwort markiert tanimania Dienstag, 17. August 2010 09:29
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 -
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_ToDeletemfg
Josef -
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:(qualifiziert mit dem Tabellennamen, um es deutlicher zu machen).SELECT * FROM Test_ToDelete WHERE my_key IN (SELECT DISTINCT Test_ToDelete.my_key FROM Test)
DELETE macht da keine Ausnahme - nur weils schmerzen könnte ;-)
Sicherer ist es mit qualifzierten Spaltennamen zu arbeiten, wie oben gezeigt,
oder auch mit EXISTSGruß ElmarSELECT * FROM Test_ToDelete WHERE EXISTS (SELECT * FROM Test WHERE Test_ToDelete.my_key = Test.my_id)
- Als Antwort vorgeschlagen Uwe RickenMVP Dienstag, 17. August 2010 09:20
- Als Antwort markiert tanimania Dienstag, 17. August 2010 09:29
-
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)
DELETE macht da keine Ausnahme - nur weils schmerzen könnte ;-)
Sicherer ist es mit qualifzierten Spaltennamen zu arbeiten, wie oben gezeigt,
oder auch mit EXISTSSELECT * FROM Test_ToDelete WHERE EXISTS (SELECT * FROM Test WHERE Test_ToDelete.my_key = Test.my_id)
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