mysql ลบภายใต้เซฟโหมด


92

ฉันมีผู้สอนโต๊ะและฉันต้องการลบบันทึกที่มีเงินเดือนอยู่ในช่วงหนึ่งวิธีที่ใช้งานง่ายมีดังนี้:

delete from instructor where salary between 13000 and 15000;

อย่างไรก็ตามในเซฟโหมดฉันไม่สามารถลบบันทึกได้โดยไม่ต้องระบุคีย์หลัก (ID)

ดังนั้นฉันจึงเขียน sql ต่อไปนี้:

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

อย่างไรก็ตามมีข้อผิดพลาด:

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

ฉันสับสนเพราะเมื่อฉันเขียน

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

มันไม่ก่อให้เกิดข้อผิดพลาด

คำถามของฉันคือ:

  1. ข้อความแสดงข้อผิดพลาดนี้หมายความว่าอย่างไรและเหตุใดรหัสของฉันจึงผิด
  2. จะเขียนโค้ดนี้ใหม่เพื่อให้ทำงานภายใต้เซฟโหมดได้อย่างไร

ขอบคุณ!


คุณต้องการเปิดโหมดปลอดภัยไว้หรือไม่ และคุณใช้ mySql workbench หรือไม่
wribit

คำตอบสำหรับคำถามของคุณทั้งสองคือใช่ และฉันแปลกใจที่เมื่อฉันใช้ jdbc เพื่อลบเร็กคอร์ดในฐานข้อมูล mysql โดยไม่มี PK มันจะไม่เกิดข้อผิดพลาด ดังนั้นเซฟโหมดใช้สำหรับ mysql workbench เท่านั้น?
roland luo

1
ไม่ - ฉันถามเพราะถ้าคุณต้องการปิดใน mySQL workbench ฉันจะบอกคุณได้อย่างไร โดยส่วนตัวแล้วฉันทำงานกับมัน ... การต้องมี ID คือความปลอดภัยที่ดี - แต่การพัฒนาที่ชาญฉลาดฉันพบว่ามันเป็นความเจ็บปวด
wribit

คำตอบ:


233

คำตอบยอดนิยมน่าจะเป็น"ปิดโหมดปลอดภัย" :

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

ถ้าฉันพูดตามตรงฉันไม่สามารถพูดได้ว่าฉันเคยวิ่งในเซฟโหมดมาก่อน ถึงกระนั้นฉันก็ไม่สบายใจกับคำตอบนี้อย่างสิ้นเชิงเนื่องจากเพียงแค่สันนิษฐานว่าคุณควรเปลี่ยนการกำหนดค่าฐานข้อมูลทุกครั้งที่คุณพบปัญหา

ดังนั้นแบบสอบถามที่สองของคุณจึงอยู่ใกล้กับเครื่องหมายมากขึ้น แต่พบปัญหาอื่น: MySQL ใช้ข้อ จำกัด บางประการกับแบบสอบถามย่อยและหนึ่งในนั้นคือคุณไม่สามารถแก้ไขตารางได้ในขณะที่เลือกจากแบบสอบถามย่อย

อ้างจากคู่มือ MySQL ข้อ จำกัด เกี่ยวกับการสืบค้นย่อย :

โดยทั่วไปคุณไม่สามารถแก้ไขตารางและเลือกจากตารางเดียวกันในแบบสอบถามย่อย ตัวอย่างเช่นข้อ จำกัด นี้ใช้กับข้อความในรูปแบบต่อไปนี้:

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

ข้อยกเว้น: ข้อห้ามก่อนหน้านี้ใช้ไม่ได้หากคุณกำลังใช้แบบสอบถามย่อยสำหรับตารางที่แก้ไขในส่วนคำสั่ง FROM ตัวอย่าง:

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

ที่นี่ผลลัพธ์จากการสืบค้นย่อยในส่วนคำสั่ง FROM จะถูกเก็บไว้เป็นตารางชั่วคราวดังนั้นแถวที่เกี่ยวข้องใน t จึงถูกเลือกตามเวลาที่มีการอัปเดตเป็น t

บิตสุดท้ายคือคำตอบของคุณ เลือก ID เป้าหมายในตารางชั่วคราวจากนั้นลบโดยอ้างอิง ID ในตารางนั้น:

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

สาธิต SQLFiddle


6
ขอบคุณสำหรับคำอธิบาย! อย่างไรก็ตามฉันได้ลองใช้โค้ดของคุณใน mysql workbench แล้วและยังแจ้งว่า "คุณกำลังใช้เซฟโหมดอัปเดตและคุณพยายามอัปเดตตารางโดยไม่มี WHERE ที่ใช้คอลัมน์ KEY"
roland luo

ที่ไม่คาดคิด คีย์หลักของคุณอยู่ภายใต้ชื่ออื่นหรือไม่? ผมสังเกตเห็นคำถามของคุณดูเหมือนจะบ่งบอกว่ามันชื่อในขณะที่การใช้คำตอบของฉันID id
rutter

ใช่ฉันเปลี่ยนเป็น ID แต่มันใช้ไม่ได้ ฉันลองลบจากผู้สอนโดยที่ ID = '1' และใช้งานได้ดังนั้น ID จึงเป็นคีย์หลัก
roland luo

1
@rolandluo ฉันรู้ว่ามันเป็นเวลานานแล้ว แต่ฉันอยากรู้ว่าคุณเคยหาวิธีแก้ปัญหาหรือไม่ เห็นได้ชัดว่าวิธีนี้ใช้ได้ผลในสถานการณ์อื่นดังนั้นฉันจึงสงสัยว่าทำไมกรณีของคุณถึงแตกต่างกัน มีบางอย่างเฉพาะสำหรับเซิร์ฟเวอร์หรือเวอร์ชันของคุณหรือไม่
rutter

19

คุณสามารถหลอกให้ MySQL คิดว่าคุณกำลังระบุคอลัมน์คีย์หลัก วิธีนี้ช่วยให้คุณ "ลบล้าง" โหมดปลอดภัยได้

สมมติว่าคุณมีตารางที่มีคีย์หลักตัวเลขที่เพิ่มขึ้นโดยอัตโนมัติคุณสามารถดำเนินการดังต่อไปนี้:

DELETE FROM tbl WHERE id <> 0

12

การปิดเซฟโหมดใน Mysql workbench 6.3.4.0

เมนูแก้ไข => ค่ากำหนด => ตัวแก้ไข SQL: ส่วนอื่น ๆ : คลิกที่ "การอัปเดตที่ปลอดภัย" ... เพื่อยกเลิกการเลือกตัวเลือก

ค่ากำหนดของ Workbench


2
"จะเขียนโค้ดนี้ใหม่เพื่อให้ทำงานในเซฟโหมดได้อย่างไร" ==> คำตอบของคุณจะบอกวิธีปิดการใช้งานเซฟโหมด;)
ByteHamster

2
ขออภัยฉันเข้าใจคำถามผิดทั้งหมด ฉันพบหัวข้อนี้เมื่อฉันไม่สามารถลบออกจากตารางด้วย Mysql workbench และมีคำถามที่คล้ายกันในความคิดเห็นเกี่ยวกับ mysql workbench แต่ฉันไม่สามารถสร้างความคิดเห็นได้ ฉันคิดว่ามันจะเป็นสถานที่ที่ดีที่จะเขียนสิ่งนี้ไว้ที่นี่เพื่อใช้อ้างอิงในอนาคต ...
Peter B

0

ฉันมีวิธีแก้ปัญหาที่ง่ายกว่ามากมันใช้ได้ผลสำหรับฉัน นอกจากนี้ยังเป็นวิธีแก้ปัญหา แต่อาจใช้งานได้และคุณไม่จำเป็นต้องเปลี่ยนการตั้งค่าของคุณ ฉันคิดว่าคุณสามารถใช้ค่าที่จะไม่อยู่ที่นั่นจากนั้นคุณใช้กับคำสั่ง WHERE ของคุณ

ลบจาก MyTable WHERE MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

ฉันไม่ชอบวิธีแก้ปัญหานั้นมากนักนั่นเป็นเหตุผลว่าทำไมฉันถึงมาที่นี่ แต่มันได้ผลและดูเหมือนว่าจะดีกว่าที่ได้รับคำตอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.