güvenli modda mysql sil


92

Bir masa eğitmenim var ve maaşı belli aralıkta olan kayıtları silmek istiyorum Sezgisel bir yol şu şekildedir:

delete from instructor where salary between 13000 and 15000;

Ancak, güvenli modda, bir birincil anahtar (kimlik) sağlamadan bir kaydı silemiyorum.

Bu yüzden aşağıdaki sql'yi yazıyorum:

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

Ancak bir hata var:

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

Kafam karıştı çünkü yazdığımda

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

bir hata oluşturmaz.

Sorum şu:

  1. bu hata mesajı gerçekten ne anlama geliyor ve kodum neden yanlış?
  2. güvenli modda çalışmasını sağlamak için bu kodu nasıl yeniden yazabilirim?

Teşekkürler!


güvenli modu açık tutmak istediniz mi? ve mySql çalışma tezgahını kullanıyor musunuz?
wribit

her iki sorunun da cevabı evet. Ve PK olmadan mysql veritabanlarındaki kayıtları silmek için jdbc kullandığımda, bunun bir hata üretmemesine şaşırdım. Yani güvenli mod sadece mysql tezgahı için mi?
roland luo

1
hayır - diye soruyordum çünkü mySQL çalışma tezgahında kapatmak isteseydiniz, size nasıl yapılacağını söyleyebilirdim. Şahsen bununla çalışıyorum ... kimliklere sahip olmak büyük bir güvenlik açısından - ama geliştirme açısından, bunu bir acı olarak buldum
wribit

Yanıtlar:


233

Google'da gezinirken, popüler yanıt "sadece güvenli modu kapat" gibi görünüyor :

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

Dürüst olursam, güvenli modda çalışmayı hiç alışkanlık haline getirdiğimi söyleyemem. Yine de, her sorunla karşılaştığınızda veritabanı yapılandırmanızı değiştirmeniz gerektiğini varsaydığı için bu yanıttan tamamen memnun değilim.

Bu nedenle, ikinci sorgunuz işarete daha yakın, ancak başka bir soruna çarpıyor: MySQL, alt sorgulara birkaç kısıtlama uyguluyor ve bunlardan biri, bir alt sorguda bir tabloyu seçerken bir tabloyu değiştirememenizdir.

MySQL kılavuzundan alıntı yapmak , Alt Sorgularla İlgili Kısıtlamalar :

Genel olarak, bir tabloyu değiştiremez ve bir alt sorudaki aynı tablodan seçim yapamazsınız. Örneğin, bu sınırlama aşağıdaki biçimlerdeki ifadeler için geçerlidir:

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

İstisna: Önceki yasak, FROM yan tümcesinde değiştirilmiş tablo için bir alt sorgu kullanıyorsanız geçerli değildir. Misal:

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

Burada, FROM yan tümcesindeki alt sorgunun sonucu geçici bir tablo olarak saklanır, bu nedenle t'deki ilgili satırlar, t'ye güncelleme yapıldığında zaten seçilmiştir.

Bu son parça senin cevabın. Geçici bir tablodaki hedef kimlikleri seçin, ardından bu tablodaki kimlikleri referans alarak silin:

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

SQLFiddle demosu .


6
Açıklamanız için teşekkürler! Ancak, kodunuzu mysql çalışma tezgahında denedim ve hala "Güvenli güncelleme modunu kullanıyorsunuz ve bir tabloyu KEY sütunu kullanan bir WHERE olmadan güncellemeye çalıştınız" diyor.
roland luo

Bu beklenmedik. Birincil anahtarınız farklı bir ad altında mı? IDCevabım kullanılırken sorunuzun adlandırıldığını gösteriyor gibi göründüğünü fark ettim id.
Rutter

Evet, ID olarak değiştiriyorum ve çalışmıyor. Ben eğitmenden silme çalıştı nerede kimliği = '1' ve kimliği birincil anahtar yani çalışır
Roland luo

1
@rolandluo Uzun zaman geçtiğini biliyorum ama bir çözüm bulup bulmadığınızı merak ediyorum. Açıkçası bu yöntem başka durumlarda işe yaradı, bu yüzden davanızın neden farklı olduğunu merak ediyorum. Sunucunuza veya sürümünüze özel bir şey olabilir mi?
Rutter

19

MySQL'i, aslında bir birincil anahtar sütunu belirttiğinizi düşünerek kandırabilirsiniz. Bu, güvenli modu "geçersiz kılmanıza" olanak tanır.

Otomatik artan sayısal birincil anahtara sahip bir tablonuz olduğunu varsayarsak, aşağıdakileri yapabilirsiniz:

DELETE FROM tbl WHERE id <> 0

12

Mysql çalışma tezgahı 6.3.4.0'da güvenli modu kapatma

Düzenle menüsü => Tercihler => SQL Düzenleyici: Diğer bölüm: seçeneğin işaretini kaldırmak için "Güvenli güncellemeler" e tıklayın ...

Workbench Tercihleri


2
" Güvenli modda çalışması için bu kodu nasıl yeniden yazabilirim ?" ==> Cevabınız güvenli modun nasıl devre dışı
bırakılacağını

2
Üzgünüm, soruyu tamamen yanlış anladım. Mysql workbench ile tablolardan silemediğimde bu konuyu buldum ve mysql workbench ile bir yorumda benzer bir soru vardı ancak yorum oluşturamıyorum. İleride başvurmak için bunu buraya yazmanın iyi bir yer olacağını düşündüm ...
Peter B

0

Çok daha basit bir çözümüm var, benim için çalışıyor; bu aynı zamanda bir geçici çözümdür, ancak kullanılabilir olabilir ve ayarlarınızı değiştirmeniz gerekmez. Asla orada olmayacak değeri kullanabileceğinizi varsayıyorum, sonra onu WHERE cümlenizde kullanıyorsunuz

MyField'in IS_NOT_EQUAL OLDUĞU YERDE MyTable'dan SİL AnyValueNoItemOnMyFieldWillEverHave

Bu çözümü de çok sevmiyorum, bu yüzden buradayım ama işe yarıyor ve yanıtlandığından daha iyi görünüyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.