Jemand möchte einen Versuch machen, die Mechanik zu erklären ... diese kleine Eigenart des Abfrageparsers hat mir heute fast schon großen Schaden zugefügt.Wie man versehentlich alle Zeilen in einer Tabelle löscht
Erstellen Sie eine Testtabelle mit 100 Zeilen mit 1-100.
create table test(JobID int primary key);
;with numbers as (
select 1 as n
union all
select n + 1 as n
from numbers
where n < 100
)
insert into test
select n from numbers
erstellen eine temporäre Tabelle mit ganzen Zahlen 1-50 in ihm:
select jobid as number into #deletions
from test
where jobid <= 50
Jetzt löscht ein eine IN
Klausel aber mit den falschen Spaltennamen in der inneren Abfrage:
delete from test where JobID in (select JobID from #deletions)
Diese letzte Löschanweisung, aus dem Aussehen, gibt das Aussehen des Löschens von 50 Zeilen ... Allerdings gibt es keine in #deletions
, so dass ich t Art-of zieht das aus der äußeren Abfrage und endet irgendwie, löscht alle Zeilen im Test.
Meine Frage ist, wie in aller Welt interpretiert es diese innere Abfrage ... #deletions
hat nur 50 Zeilen, also wie zieht es alle 100 IDs aus der äußeren Tabelle? Diese Art von Tippfehler hat mir heute fast schon großen Schaden zugefügt.
Meiner Meinung nach sollte dies eine Art Parsing/Syntaxfehler oder irgendeine Art von Mehrdeutigkeitsfehler werfen.
hier ein SQL Fiddle Demo
Zumindest werden Sie eine Abfrage wie diese nie wieder tun :-) Senden Sie niemals ein 'DELETE' oder' UPDATE', ohne zu testen. Ändern Sie 'DELETE' in' SELECT * 'und sehen Sie, was zurückgegeben wurde. – dnoeth
Hier gibt es keine Mehrdeutigkeit, da JobID nur auf der äußeren "Test" -Tabelle existiert. Sie haben Recht, dass der Umfang nicht offensichtlich ist. Aus diesem Grund ist es eine gute Methode, sich die Aneignung von Spaltennamen mit dem Tabellennamen oder Alias in Abfragen mit mehreren Tabellen anzueignen. –
Immer wenn Sie mit UPDATE/DELETE/MERGE/INSERT zu tun haben, wickeln Sie immer mit BEGIN TRAN und ROLLBACK TRAN. Einer der wichtigsten Ratschläge für die Produktion Ops Jungs. – Greg