MySQL, perbarui beberapa tabel dengan satu permintaan

132

Saya memiliki fungsi yang memperbarui tiga tabel, tetapi saya menggunakan tiga pertanyaan untuk melakukan ini. Saya ingin menggunakan pendekatan yang lebih nyaman untuk praktik yang baik.

Bagaimana saya bisa memperbarui beberapa tabel di MySQL dengan satu permintaan?

Adamski
sumber
3
dapatkah Anda memberikan contoh kode yang dihasilkan? Apakah ada kunci umum di antara tabel?
Jonathan Day

Jawaban:

451

Ambil kotak dua tabel, Booksdan Orders. Jika kita menambah jumlah buku dalam urutan tertentu dengan Order.ID = 1002dalam Orderstabel maka kita juga perlu mengurangi bahwa jumlah total buku yang tersedia di stok kita dengan jumlah yang sama dalam Bookstabel.

UPDATE Books, Orders
SET Orders.Quantity = Orders.Quantity + 2,
    Books.InStock = Books.InStock - 2
WHERE
    Books.BookID = Orders.BookID
    AND Orders.OrderID = 1002;
Irfan
sumber
Jika saya ingin memasukkan "LIMIT" ke SQL Query, apakah saya harus mengatakan LIMIT 1 atau LIMIT 2?
Bluedayz
2
Apa keuntungan melakukan ini vs transaksi? Terima kasih!
paulkon
2
@ Paulkon, saya berasumsi bahwa ketika menggunakan transaksi, ada banyak overhead yang terlibat karena roll-back harus tersedia jika ada prosedur dalam transaksi gagal.
Thijs Riezebeek
27
Peringatan umum saat menggunakan kueri ini. Klausa WHERE dievaluasi secara terpisah untuk setiap tabel. The Books.BookID = Orders.BookID sangat penting, tanpa itu Pembaruan tabel Buku akan terjadi pada semua baris dan tidak hanya untuk baris dengan id yang ditentukan. Beberapa pelajaran dipelajari dengan cara yang sulit, yang ini dipelajari dengan cara yang mengerikan.
nheimann1
1
@ nheimann1 Dan itulah mengapa saya selalu merekomendasikan orang menggunakan sintaks "inner join" ANSI. Ini terlalu mudah untuk melupakan kondisi itu dan malah mendapatkan bergabung penuh dengan Cartesian.
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';

Untuk melihat apa yang akan diperbarui, Anda dapat mengonversinya menjadi pernyataan pilihan, misalnya:

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';

Contoh menggunakan tabel yang sama dengan jawaban lainnya:

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;

EDIT:

Hanya untuk bersenang-senang, mari tambahkan sesuatu yang sedikit lebih menarik.

Katakanlah Anda memiliki tabel booksdan tabel authors. Anda bookspunya author_id. Tetapi ketika database awalnya dibuat, tidak ada batasan kunci asing yang diatur dan kemudian bug dalam kode front-end menyebabkan beberapa buku ditambahkan dengan author_ids yang tidak valid . Sebagai seorang DBA Anda tidak ingin harus melalui semua ini booksuntuk memeriksa apa yang author_idseharusnya, sehingga keputusan dibuat bahwa penangkap data akan memperbaiki booksuntuk menunjuk ke kanan authors. Tetapi ada terlalu banyak buku untuk dibaca masing-masing dan katakanlah Anda tahu bahwa orang-orang yang memiliki author_idyang sesuai dengan yang sebenarnya authorsudah benar. Hanya yang tidak adaauthor_ids yang tidak valid. Sudah ada antarmuka bagi pengguna untuk memperbarui detail buku dan pengembang tidak ingin mengubahnya hanya untuk masalah ini. Tetapi antarmuka yang ada melakukan INNER JOIN authors, sehingga semua buku dengan penulis yang tidak valid dikecualikan.

Yang dapat Anda lakukan adalah ini: Masukkan catatan penulis palsu seperti "Penulis tidak dikenal". Kemudian perbarui author_idsemua catatan buruk untuk menunjuk ke penulis tidak dikenal. Kemudian penangkap data dapat mencari semua buku dengan penulis disetel ke "Penulis tidak dikenal", mencari penulis yang benar dan memperbaikinya.

Bagaimana Anda memperbarui semua catatan buruk yang mengarah ke penulis tidak dikenal? Seperti ini (dengan asumsi penulis tidak dikenal author_idadalah 99999):

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

Di atas juga akan memperbarui books yang memiliki NULL author_idke penulis Tidak Dikenal. Jika Anda tidak menginginkannya, tentu saja Anda dapat menambahkan AND books.author_id IS NOT NULL.

Wodin
sumber
35

Anda juga dapat melakukan ini dengan satu permintaan juga menggunakan gabungan seperti:

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

Dan kemudian kirimkan saja pertanyaan ini, tentu saja. Anda dapat membaca lebih lanjut tentang bergabung di sini: http://dev.mysql.com/doc/refman/5.0/id/join.html . Ada juga beberapa batasan untuk memesan dan membatasi beberapa pembaruan tabel yang dapat Anda baca di sini: http://dev.mysql.com/doc/refman/5.0/en/update.html (cukup ctrl + f "gabung").

Stephen Searles
sumber
Agak murah untuk menyebut bahwa "gabung" ;-)
underscore_d
2

Untuk itulah biasanya prosedur tersimpan: untuk mengimplementasikan beberapa pernyataan SQL secara berurutan. Dengan menggunakan rollback, Anda dapat memastikan bahwa mereka diperlakukan sebagai satu unit kerja, yaitu apakah semuanya dijalankan atau tidak ada di antaranya, untuk menjaga data tetap konsisten.

SteveCav
sumber
di mana saya akan menulis prosedur? bisakah Anda memberikan contoh?
Adamski
1
Dipilih untuk menjelaskan perlunya atomisitas - penting juga untuk menyadari bahwa menggunakan prosedur tersimpan tidak sendirian menjamin konsistensi, Anda masih perlu menggunakan transaksi; juga, transaksi dapat dilakukan tanpa menggunakan prosedur yang tersimpan, asalkan dilakukan melalui koneksi yang sama. Dalam hal ini, penggunaan pembaruan multi-tabel bahkan lebih baik.
Duncan
2

Ketika Anda mengatakan beberapa kueri maksud Anda beberapa pernyataan SQL seperti pada:

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

Atau beberapa fungsi panggilan permintaan seperti pada:

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

Yang pertama dapat dilakukan dengan menggunakan satu panggilan mySqlQuery jika itu yang ingin Anda capai, cukup panggil fungsi mySqlQuery dengan cara berikut:

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

Ini akan menjalankan ketiga kueri dengan satu panggilan mySqlQuery ().

code_burgar
sumber
mySqlQuery () adalah fungsi khusus atau fungsi bawaan? Saya ingin tahu lebih banyak tentang ini.
Debashis
3
Tidak ada perbedaan yang signifikan antara mengirim tiga kueri secara individual atau sebagai beberapa kueri, kecuali mungkin jika fungsi kueri Anda membuka koneksi baru setiap kali. Dari sudut pandang eksekusi sisi server, itu adalah hal yang sama
Duncan