Saya memiliki tabel MySQL dengan koordinat, nama kolomnya adalah X dan Y. Sekarang saya ingin menukar nilai kolom dalam tabel ini, sehingga X menjadi Y dan Y menjadi X. Solusi yang paling jelas adalah mengganti nama kolom, tapi saya tidak ingin membuat perubahan struktur karena saya tidak selalu memiliki izin untuk melakukan itu.
Apakah ini bisa dilakukan dengan UPDATE dalam beberapa cara?Tabel PEMBARUAN SET X = Y, Y = X jelas tidak akan melakukan apa yang saya inginkan.
Sunting: Harap dicatat bahwa pembatasan saya pada izin, yang disebutkan di atas, secara efektif mencegah penggunaan ALTER TABLE atau perintah lain yang mengubah struktur tabel / database. Mengganti nama kolom atau menambahkan yang baru sayangnya bukan opsi.
UPDATE table SET X = Y, Y = X
adalah cara standar untuk melakukannya dalam SQL, hanya perilaku MySQL.Jawaban:
Saya hanya harus berurusan dengan hal yang sama dan saya akan meringkas temuan saya.
Itu
UPDATE table SET X=Y, Y=X
Pendekatan jelas tidak bekerja, karena hanya akan menetapkan kedua nilai untuk Y.Berikut adalah metode yang menggunakan variabel sementara. Terima kasih kepada Antony dari komentar http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ untuk tweak "IS NOT NULL". Tanpanya, kueri bekerja tanpa terduga. Lihat skema tabel di akhir posting. Metode ini tidak menukar nilai jika salah satunya adalah NULL. Gunakan metode # 3 yang tidak memiliki batasan ini.
UPDATE swap_test SET x=y, y=@temp WHERE (@temp:=x) IS NOT NULL;
Metode ini ditawarkan oleh Dipin dalam, sekali lagi, komentar dari http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ . Saya pikir itu solusi yang paling elegan dan bersih. Ia bekerja dengan nilai NULL dan non-NULL.
UPDATE swap_test SET x=(@temp:=x), x = y, y = @temp;
Pendekatan lain yang saya lakukan tampaknya berhasil:
UPDATE swap_test s1, swap_test s2 SET s1.x=s1.y, s1.y=s2.x WHERE s1.id=s2.id;
Pada dasarnya, tabel 1 adalah yang diperbarui dan yang kedua digunakan untuk menarik data lama.
Perhatikan bahwa pendekatan ini membutuhkan kunci utama untuk hadir.
Ini adalah skema pengujian saya:
sumber
Anda bisa mengambil penjumlahan dan mengurangi nilai lawan menggunakan X dan Y
Ini adalah contoh uji (dan ini bekerja dengan angka negatif)
Inilah swap yang dilakukan
Cobalah !!!
sumber
TINYINT
atau banyak sekaliINT
, Anda benar !!!Kode berikut berfungsi untuk semua skenario dalam pengujian cepat saya:
sumber
UPDATE table swap_test
? Bukankah seharusnya begituUPDATE swap_test
?Tabel PEMBARUAN SET X = Y, Y = X akan melakukan persis apa yang Anda inginkan (edit: di PostgreSQL, bukan MySQL, lihat di bawah). Nilai diambil dari baris lama dan ditugaskan ke salinan baru dari baris yang sama, kemudian baris lama diganti. Anda tidak perlu menggunakan tabel sementara, kolom sementara, atau trik swap lainnya.
@ D4V360: Begitu. Itu mengejutkan dan tidak terduga. Saya menggunakan PostgreSQL dan jawaban saya berfungsi dengan benar di sana (saya sudah mencobanya). Lihat dokumen UPDATE PostgreSQL (di bawah Parameter, ekspresi), di mana disebutkan bahwa ekspresi di sisi kanan klausa SET secara eksplisit menggunakan nilai kolom yang lama. Saya melihat bahwa dokumen MySQL UPDATE yang sesuai berisi pernyataan "Penugasan UPDATE tabel tunggal umumnya dievaluasi dari kiri ke kanan" yang menyiratkan perilaku yang Anda uraikan.
Senang mendengarnya.
sumber
Ok, jadi hanya untuk bersenang-senang, Anda bisa melakukan ini! (dengan asumsi Anda menukar nilai string)
Sedikit kesenangan menyalahgunakan proses evaluasi kiri-ke-kanan di MySQL.
Atau, gunakan XOR jika angka. Anda menyebutkan koordinat, jadi apakah Anda memiliki nilai integer yang indah, atau string kompleks?
Sunting: Hal-hal XOR bekerja seperti ini dengan cara:
sumber
Saya percaya memiliki variabel pertukaran perantara adalah praktik terbaik dengan cara seperti itu:
Pertama, selalu berhasil; kedua, ia bekerja terlepas dari tipe data.
Meskipun Keduanya
dan
bekerja biasanya, hanya untuk tipe data nomor by the way, dan itu adalah tanggung jawab Anda untuk mencegah overflow, Anda tidak dapat menggunakan XOR antara ditandatangani dan tidak ditandatangani, Anda juga tidak dapat menggunakan jumlah untuk kemungkinan melimpah.
Dan
tidak berfungsi jika c1 adalah 0 atau NULL atau nol string panjang atau hanya spasi.
Kita perlu mengubahnya
Ini skripnya:
sumber
Dua alternatif 1. Gunakan tabel sementara 2. Selidiki algoritma XOR
sumber
Sesuatu seperti ini?Sunting: Tentang komentar Greg: Tidak, ini tidak berfungsi:
sumber
Ini pasti berhasil! Saya baru saja membutuhkannya untuk menukar kolom harga Euro dan SKK. :)
Di atas tidak akan berfungsi (ERROR 1064 (42000): Anda memiliki kesalahan dalam sintaks SQL Anda)
sumber
Dengan asumsi Anda telah menandatangani bilangan bulat di kolom Anda, Anda mungkin perlu menggunakan CAST (a ^ b AS SIGNED), karena hasil dari operator ^ adalah bilangan bulat 64-bit yang tidak ditandatangani di MySQL.
Jika itu membantu siapa pun, inilah metode yang saya gunakan untuk menukar kolom yang sama antara dua baris yang diberikan:
di mana $ 1 dan $ 2 adalah kunci dari dua baris dan $ 3 adalah hasil dari permintaan pertama.
sumber
Saya belum mencobanya tetapi
Mungkin melakukannya.
Menandai
sumber
Anda dapat mengubah nama kolom, tetapi ini lebih merupakan peretasan. Tapi hati-hati terhadap indeks apa pun yang ada di kolom ini
sumber
Nama tabel adalah pelanggan. bidang is a dan b, tukar nilai menjadi b ;.
PEMERIKSAAN pelanggan SET a = (@ temp: = a), a = b, b = @temp
Saya memeriksa ini berfungsi dengan baik.
sumber
Di SQL Server, Anda dapat menggunakan kueri ini:
sumber
Swapping nilai kolom menggunakan kueri tunggal
UPDATE my_table SET a = @ tmp: = a, a = b, b = @ tmp;
Bersulang...!
sumber
Saya hanya perlu memindahkan nilai dari satu kolom ke yang lain (seperti pengarsipan) dan mengatur ulang nilai kolom asli.
Di bawah ini (referensi # 3 dari jawaban yang diterima di atas) bekerja untuk saya.
sumber
sumber
Contoh ini swap start_date dan END_DATE untuk catatan di mana tanggal adalah cara putaran yang salah (saat melakukan ETL ke menulis ulang utama, saya menemukan beberapa start tanggal lambat mereka akhir tanggal. Bawah, programmer buruk!).
Di situ, saya menggunakan MEDIUMINTs untuk alasan kinerja (seperti hari-hari Julian, tetapi memiliki root 0 dari 1900-01-01), jadi saya OK melakukan kondisi WHERE mdu.start_date> mdu.end_date .
PK berada di ketiga kolom secara individual (untuk alasan operasional / pengindeksan).
sumber
Katakanlah Anda ingin menukar nilai nama depan dan belakang di tb_user.
Yang paling aman adalah:
sumber
Anda dapat menerapkan permintaan di bawah ini, Ini berfungsi sempurna untuk saya.
sumber