MySQL, tek bir sorgu ile birden çok tabloyu güncelleyin


132

Üç tabloyu güncelleyen bir işlevim var, ancak bunu gerçekleştirmek için üç sorgu kullanıyorum. İyi uygulama için daha uygun bir yaklaşım kullanmak istiyorum.

MySQL'de birden çok tabloyu tek bir sorgu ile nasıl güncelleyebilirim?


3
üretilen kodun bir örneğini verebilir misiniz? Tablolar arasında ortak bir anahtar var mı?
Jonathan Day

Yanıtlar:


451

İki tablonun durumunu ele alalım Booksve Orders. Durumda, ile belirli bir sırayla kitap sayısını artırmak Order.ID = 1002üzere Orderso zaman da azaltmak için gereken tabloda aynı sayısına göre stoklarımızda mevcut kitapların toplam sayısı o Booksmasaya.

UPDATE Books, Orders
SET Orders.Quantity = Orders.Quantity + 2,
    Books.InStock = Books.InStock - 2
WHERE
    Books.BookID = Orders.BookID
    AND Orders.OrderID = 1002;

SQL Sorgusuna "LIMIT" i eklemek istersem, LIMIT 1 veya LIMIT 2 demem gerekir mi?
Bluedayz

2
Bir işleme göre bunu yapmanın avantajı nedir? Teşekkürler!
paulkon

2
@paulkon, işlemleri kullanırken, işlemdeki herhangi bir prosedür başarısız olursa geri alma işlemlerinin mevcut olması gerektiğinden çok fazla ek yük olduğunu varsayıyorum.
Thijs Riezebeek

27
Bu sorguyu kullanırken genel uyarı. WHERE yan tümcesi her tablo için ayrı ayrı değerlendirilir. Books.BookID = Orders.BookID çok önemlidir, onsuz Books tablo güncellemesi yalnızca belirtilen kimliğe sahip satır için değil tüm satırlarda olur. Bazı dersler zor yoldan öğrenildi, bu dehşet verici bir şekilde öğrenildi.
nheimann1

1
@ nheimann1 İşte bu yüzden insanlara her zaman ANSI "iç birleştirme" sözdizimini kullanmalarını öneriyorum. Bu koşulu unutmak ve bunun yerine tam bir Kartezyen birleştirme elde etmek çok kolaydır.
fool4jesus

77
UPDATE t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
SET t1.a = 'something',
    t2.b = 42,
    t3.c = t2.c
WHERE t1.a = 'blah';

Bunun neyi güncelleyeceğini görmek için, bunu bir seçme ifadesine dönüştürebilirsiniz, örneğin:

SELECT t2.t1_id, t2.t3_id, t1.a, t2.b, t2.c AS t2_c, t3.c AS t3_c
FROM t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
WHERE t1.a = 'blah';

Diğer cevapla aynı tabloları kullanan bir örnek:

SELECT Books.BookID, Orders.OrderID,
    Orders.Quantity AS CurrentQuantity,
    Orders.Quantity + 2 AS NewQuantity,
    Books.InStock AS CurrentStock,
    Books.InStock - 2 AS NewStock
FROM Books
INNER JOIN Orders ON Books.BookID = Orders.BookID
WHERE Orders.OrderID = 1002;

UPDATE Books
INNER JOIN Orders ON Books.BookID = Orders.BookID
SET Orders.Quantity = Orders.Quantity + 2,
    Books.InStock = Books.InStock - 2
WHERE Orders.OrderID = 1002;

DÜZENLE:

Sırf eğlenmek için biraz daha ilginç bir şey ekleyelim.

Diyelim ki bir masanız booksve bir masanız var authors. Sizin booksbir var author_id. Ancak veritabanı başlangıçta oluşturulduğunda, hiçbir yabancı anahtar kısıtlaması ayarlanmadı ve daha sonra ön uç kodundaki bir hata, bazı kitapların geçersiz author_ide- postalarla eklenmesine neden oldu . Bir DBA olarak, booksne olması author_idgerektiğini kontrol etmek için tüm bunları gözden geçirmek zorunda kalmak istemezsiniz , bu nedenle veri yakalayıcıların bookssağa işaret edecek şekilde düzelteceklerine karar verilir authors. Ama her biri geçmesi ve Diyelim ki bir sahip olanlar olduğunu biliyoruz diyelim çok fazla kitap bulunuyor author_idgerçek ile karşılık bu authordoğrudur. Sadece var olmayanlarauthor_idgeçersiz olanlar. Kullanıcıların kitap detaylarını güncellemeleri için zaten bir arayüz var ve geliştiriciler bunu sadece bu problem için değiştirmek istemiyorlar. Ancak mevcut arayüz bir yapar INNER JOIN authors, bu nedenle geçersiz yazarlara sahip tüm kitaplar hariç tutulur.

Yapabilecekleriniz şudur: "Bilinmeyen yazar" gibi sahte bir yazar kaydı ekleyin. Ardından author_id, tüm kötü kayıtları Bilinmeyen yazarı gösterecek şekilde güncelleyin . Daha sonra veri yakalayıcılar, yazarı "Bilinmeyen yazar" olarak ayarlanmış tüm kitapları arayabilir, doğru yazarı arayabilir ve düzeltebilir.

Tüm kötü kayıtları Bilinmeyen yazarı gösterecek şekilde nasıl güncellersiniz? Şöyle (Bilinmeyen yazarın author_id99999 olduğu varsayılarak ):

UPDATE books
LEFT OUTER JOIN authors ON books.author_id = authors.id
SET books.author_id = 99999
WHERE authors.id IS NULL;

Yukarıdakiler , bilinmeyen yazara bookssahip NULL author_idolanları da güncelleyecektir . Bunu istemiyorsan tabii ki ekleyebilirsiniz AND books.author_id IS NOT NULL.


35

Bunu aynı zamanda bir birleşim kullanarak tek bir sorgu ile de yapabilirsiniz:

UPDATE table1,table2 SET table1.col=a,table2.col2=b
WHERE items.id=month.id;

Ve sonra tabii ki bu tek sorguyu gönderin. Birleştirmeler hakkında daha fazla bilgiyi burada bulabilirsiniz: http://dev.mysql.com/doc/refman/5.0/en/join.html . Ayrıca, burada okuyabileceğiniz birden çok tablo güncellemesinin sıralanması ve sınırlandırılması için birkaç kısıtlama vardır: http://dev.mysql.com/doc/refman/5.0/en/update.html (sadece ctrl + f "join").


Buna "katıl" demek biraz cömertçe ;-)
undercore_d

2

Genellikle saklı yordamlar bunun içindir: bir sırayla birkaç SQL deyimi uygulamak. Geri dönüşleri kullanarak, verilerin tutarlı olmasını sağlamak için bunların tek bir iş birimi olarak ele alınmasını sağlayabilirsiniz, yani bunların tümü yürütülür veya hiçbiri yürütülmez.


prosedürü nereye yazacağım? lütfen bir örnek verebilir misiniz?
Adamski

1
Atomikliğin gerekliliğini açıklamak için oylama yapıldı - saklanan prosedürleri kullanmanın tek başına tutarlılığı garanti etmediğini, yine de işlemleri kullanmanız gerektiğini anlamak önemlidir; aynı şekilde işlemler, aynı bağlantı üzerinden gerçekleştirilmeleri koşuluyla, saklı yordam kullanılmadan da gerçekleştirilebilir. Bu durumda, çoklu tablo güncellemesinin kullanılması daha da iyidir.
Duncan

2

Birden çok sorgu dediğinizde, aşağıdaki gibi birden çok SQL ifadesini mi kastediyorsunuz:

UPDATE table1 SET a=b WHERE c;
UPDATE table2 SET a=b WHERE d;
UPDATE table3 SET a=b WHERE e;

Veya aşağıdaki gibi birden çok sorgu işlevi çağırır:

mySqlQuery(UPDATE table1 SET a=b WHERE c;)
mySqlQuery(UPDATE table2 SET a=b WHERE d;)
mySqlQuery(UPDATE table3 SET a=b WHERE e;)

İlki, tek bir mySqlQuery çağrısı kullanılarak yapılabilir, eğer elde etmek istediğiniz buysa, mySqlQuery işlevini aşağıdaki şekilde çağırmanız yeterlidir:

mySqlQuery(UPDATE table1 SET a=b WHERE c; UPDATE table2 SET a=b WHERE d; UPDATE table3 SET a=b WHERE e;)

Bu, üç sorguyu da bir mySqlQuery () çağrısıyla yürütecektir.


mySqlQuery () özel bir işlev mi yoksa yerleşik bir işlev mi? Bunun hakkında daha fazla bilgi edinmek istiyorum.
Debashis

3
Belki de sorgu işlevinizin her seferinde yeni bir bağlantı açması dışında, üç sorguyu tek tek veya birden çok sorgu olarak göndermek arasında önemli bir fark yoktur. Sunucu tarafı yürütme açısından da aynı şey
Duncan
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.