2015-05-25 16 views
6

Ai đó muốn có một đâm vào giải thích các cơ chế này ... này quirk ít của các phân tích cú pháp truy vấn gần như gây ra thiệt hại lớn cho tôi ngày hôm nay.Làm thế nào để vô tình xóa tất cả các hàng trong một bảng

Tạo bảng thử nghiệm có 100 hàng, với 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 

Tạo một bảng tạm thời với số nguyên 1-50 trong đó:

select jobid as number into #deletions 
from test 
where jobid <= 50 

Bây giờ làm một xóa bằng một IN khoản nhưng với tên cột sai trong truy vấn bên trong:

delete from test where JobID in (select JobID from #deletions) 

Tuyên bố xóa cuối cùng, từ lần xuất hiện, cho hình thức xóa 50 hàng ... Tuy nhiên, không có JobID trong #deletions, vì vậy tôi t loại kéo từ truy vấn bên ngoài và kết thúc bằng cách nào đó, xóa tất cả các hàng trong thử nghiệm.

Câu hỏi của tôi là, làm cách nào để giải thích truy vấn bên trong đó ... #deletions chỉ có 50 hàng, vậy làm cách nào để kéo tất cả 100 id từ bảng ngoài? Loại lỗi đánh máy/sai lầm này gần như đã gây ra thiệt hại lớn cho tôi hôm nay.

Theo ý kiến ​​của tôi, điều này sẽ ném một số loại lỗi phân tích cú pháp/cú pháp hoặc một số loại lỗi mơ hồ.

Dưới đây là một SQL Fiddle Demo

+1

Ít nhất bạn sẽ không thực hiện truy vấn như thế này nữa :-) Không bao giờ gửi 'DELETE' hoặc' UPDATE' mà không kiểm tra. Thay đổi 'DELETE' thành' SELECT * 'và xem cái gì được trả về. – dnoeth

+1

Không có sự mơ hồ ở đây vì JobID chỉ tồn tại trên bảng 'test' bên ngoài. Bạn đúng là phạm vi đó không rõ ràng, đó là lý do tại sao việc thực hiện thói quen của các tên cột đủ điều kiện với tên bảng hoặc bí danh trong các truy vấn nhiều bảng là một cách hay. –

+0

Bất cứ khi nào bạn đang lộn xộn với UPDATE/DELETE/MERGE/INSERT, luôn luôn bọc với BEGIN TRAN và ROLLBACK TRAN. Một trong những lời khuyên quan trọng nhất cho sản xuất Ops guys. – Greg

Trả lời

10

Nếu bạn sử dụng bí danh bảng, logic sẽ được rõ ràng. Bạn nghĩ rằng bạn đang viết:

delete from test 
    where test.JobID in (select d.JobID from #deletions d); 

Điều đó làm cho ý nghĩa, nhưng nó sẽ tạo ra một lỗi cú pháp vì JobId không tồn tại trong #deletions. Vì vậy, nguyên tắc xác định phạm vi của SQL đi đến cấp độ tiếp theo để tìm JobId và giải thích các truy vấn như:

delete from test 
    where test.JobID in (select test.JobID from #deletions d); 

này sẽ xóa tất cả các giá trị NULL của JobId.

Đạo đức: Luôn sử dụng tên cột đủ điều kiện.

+0

Lỗi logic trong kịch bản làm sạch đơn giản là rất khó phát hiện. May mắn thay, nó chỉ xóa dữ liệu khỏi một bảng không quan trọng nhưng tôi hơi hoang mang một lúc cho đến khi tôi phát hiện ra vấn đề. Tôi sẽ luôn luôn sử dụng bí danh từ bây giờ, hoặc sử dụng một JOIN cho xóa hơn là một mệnh đề IN. –

Các vấn đề liên quan