xóa mysql trong chế độ an toàn


87

Tôi có một người hướng dẫn bảng và tôi muốn xóa các bản ghi có lương trong một phạm vi Một cách trực quan như sau:

delete from instructor where salary between 13000 and 15000;

Tuy nhiên, ở chế độ an toàn, tôi không thể xóa bản ghi mà không cung cấp khóa chính (ID).

Vì vậy, tôi viết sql sau:

delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

Tuy nhiên, có một lỗi:

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

Tôi bối rối vì khi tôi viết

select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

nó không tạo ra lỗi.

Câu hỏi của tôi là:

  1. thông báo lỗi này thực sự có nghĩa là gì và tại sao mã của tôi sai?
  2. làm thế nào để viết lại mã này để làm cho nó hoạt động ở chế độ an toàn?

Cảm ơn!


bạn có muốn bật chế độ an toàn không? và bạn có đang sử dụng mySql workbench không?
wribit

câu trả lời cho cả hai câu hỏi của bạn là có. Và tôi ngạc nhiên rằng khi tôi sử dụng jdbc để xóa các bản ghi trong cơ sở dữ liệu mysql mà không có PK, nó không tạo ra lỗi. Vì vậy, chế độ an toàn chỉ dành cho bàn làm việc mysql?
roland luo

1
không - tôi đang hỏi vì nếu bạn muốn tắt nó trong bàn làm việc mySQL, tôi có thể cho bạn biết cách làm. Cá nhân tôi làm việc với nó đi ... phải có ID được an toàn tuyệt vời khôn ngoan - nhưng phát triển khôn ngoan, tôi thấy nó là một nỗi đau
wribit

Câu trả lời:


226

Tìm kiếm xung quanh, câu trả lời phổ biến dường như là "chỉ cần tắt chế độ an toàn" :

SET SQL_SAFE_UPDATES = 0;
DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000;
SET SQL_SAFE_UPDATES = 1;

Nếu thành thật mà nói, tôi không thể nói rằng tôi đã từng tạo thói quen chạy ở chế độ an toàn. Tuy nhiên, tôi không hoàn toàn thoải mái với câu trả lời này vì nó chỉ giả định rằng bạn nên thay đổi cấu hình cơ sở dữ liệu của mình mỗi khi bạn gặp sự cố.

Vì vậy, truy vấn thứ hai của bạn gần với dấu hơn, nhưng lại gặp phải một vấn đề khác: MySQL áp dụng một số hạn chế cho các truy vấn con và một trong số đó là bạn không thể sửa đổi bảng trong khi chọn từ nó trong một truy vấn con.

Trích dẫn từ hướng dẫn sử dụng MySQL, Hạn chế về Truy vấn con :

Nói chung, bạn không thể sửa đổi bảng và chọn từ cùng một bảng trong một truy vấn con. Ví dụ: giới hạn này áp dụng cho các câu lệnh thuộc các dạng sau:

DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
{INSERT|REPLACE} INTO t (SELECT ... FROM t ...);

Ngoại lệ: Điều cấm trước không áp dụng nếu bạn đang sử dụng truy vấn con cho bảng đã sửa đổi trong mệnh đề FROM. Thí dụ:

UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);

Ở đây, kết quả từ truy vấn con trong mệnh đề FROM được lưu trữ dưới dạng bảng tạm thời, vì vậy các hàng có liên quan trong t đã được chọn vào thời điểm cập nhật thành t diễn ra.

Đó là chút cuối cùng là câu trả lời của bạn. Chọn các ID mục tiêu trong bảng tạm thời, sau đó xóa bằng cách tham chiếu các ID trong bảng đó:

DELETE FROM instructor WHERE id IN (
  SELECT temp.id FROM (
    SELECT id FROM instructor WHERE salary BETWEEN 13000 AND 15000
  ) AS temp
);

Bản trình diễn SQLFiddle .


6
Cảm ơn bạn đã giải thích của bạn! Tuy nhiên, tôi đã thử mã của bạn trong bàn làm việc mysql và nó vẫn cho biết "Bạn đang sử dụng chế độ cập nhật an toàn và bạn đã cố cập nhật bảng mà không có WHERE sử dụng cột KEY".
roland luo

Thật là bất ngờ. Khóa chính của bạn có tên khác không? Tôi nhận thấy câu hỏi của bạn dường như cho biết nó được đặt tên ID, trong khi câu trả lời của tôi sử dụng id.
rutter

Có, tôi thay đổi nó thành ID và nó không hoạt động. Tôi đã cố gắng xóa từ giảng viên nơi ID = '1' và nó hoạt động rất ID là khóa chính
roland luo

1
@rolandluo Tôi biết đã lâu nhưng tôi tò mò không biết bạn đã bao giờ tìm ra cách giải quyết chưa. Rõ ràng phương pháp này đã hoạt động trong các trường hợp khác, vì vậy tôi tự hỏi tại sao trường hợp của bạn lại khác. Một cái gì đó cụ thể cho máy chủ hoặc phiên bản của bạn, có lẽ?
rutter

19

Bạn có thể lừa MySQL nghĩ rằng bạn đang thực sự chỉ định một cột khóa chính. Điều này cho phép bạn "ghi đè" chế độ an toàn.

Giả sử bạn có một bảng có khóa chính dạng số tự động tăng, bạn có thể làm như sau:

DELETE FROM tbl WHERE id <> 0

12

Tắt chế độ an toàn trong Mysql workbench 6.3.4.0

Edit menu => Preferences => SQL Editor: Phần khác: nhấp vào "Cập nhật an toàn" ... để bỏ chọn tùy chọn

Tùy chọn Bàn làm việc


2
"làm thế nào để viết lại mã này để làm cho nó hoạt động ở chế độ an toàn ?" ==> Câu trả lời của bạn cho biết cách tắt chế độ an toàn;)
ByteHamster

2
Xin lỗi, tôi hoàn toàn hiểu sai câu hỏi. Tôi tìm thấy chủ đề này khi tôi không thể xóa khỏi các bảng bằng Mysql workbench và có một câu hỏi tương tự trong nhận xét với bàn làm việc mysql, nhưng tôi không thể tạo nhận xét. Tôi nghĩ, rằng nó sẽ là một nơi tốt để viết những dòng này vào đây để tham khảo sau này ...
Peter B

0

Tôi có một giải pháp đơn giản hơn nhiều, nó đang làm việc cho tôi; nó cũng là một giải pháp thay thế nhưng có thể sử dụng được và bạn không phải thay đổi cài đặt của mình. Tôi giả sử bạn có thể sử dụng giá trị sẽ không bao giờ có, sau đó bạn sử dụng nó trong mệnh đề WHERE của bạn

XÓA KHỎI MyTable TẠI ĐÂU MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

Tôi cũng không thích giải pháp đó quá, đó là lý do tại sao tôi ở đây, nhưng nó hoạt động và có vẻ tốt hơn những gì nó đã được trả lời

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.