Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Sistem penandaan:Pertanyaan solusi toksik

Pertama-tama "toxi" bukanlah istilah standar. Selalu tentukan istilah Anda! Atau setidaknya berikan tautan yang relevan.

Dan sekarang ke pertanyaan itu sendiri...

Tidak, Anda akan memiliki 3 tabel.

Anda cukup banyak berada di jalur yang benar, dengan pengecualian bahwa Anda dapat menggunakan sifat set berbasis SQL untuk "menggabungkan" banyak langkah ini. Misalnya, menandai item 1 dengan tag:'tag1', 'tag2', dan 'tag3' dapat dilakukan seperti ini...

INSERT IGNORE INTO tagmap (item_id, tag_id)
SELECT 1, tag_id FROM tags WHERE tag_text IN ('tag1', 'tag2', 'tag3');

IGNORE memungkinkan ini berhasil meskipun item sudah terhubung ke beberapa tag ini.

Ini mengasumsikan semua tag yang diperlukan sudah ada di tags . Dengan asumsi tag.tag_id adalah peningkatan otomatis, Anda dapat melakukan sesuatu seperti ini untuk memastikannya:

INSERT IGNORE INTO tags (tag_text) VALUES ('tag1'), ('tag2'), ('tag3');

Tidak ada sihir. Jika "item terhubung ke tag tertentu" adalah bagian dari pengetahuan yang ingin Anda rekam, maka itu akan memiliki untuk memiliki semacam representasi fisik dalam database.

Maksud Anda menandai ulang item (bukan mengubah tag itu sendiri)?

Untuk menghapus semua tag yang tidak ada dalam daftar, lakukan sesuatu seperti ini:

DELETE FROM tagmap
WHERE
    item_id = 1
    AND tag_id NOT IN (
        SELECT tag_id FROM tags
        WHERE tag_text IN ('tag1', 'tag3')
    );

Ini akan memutuskan item dari semua tag kecuali 'tag1' dan 'tag3'. Jalankan INSERT di atas dan DELETE ini satu demi satu untuk "menutupi" menambahkan dan menghapus tag.

Anda dapat memainkan semua ini di SQL Fiddle .

Benar. Titik akhir turunan dari FK tidak akan memicu tindakan referensial (seperti ON DELETE CASCADE), hanya induk yang akan memicu.

BTW, Anda menggunakan skema ini karena Anda ingin bidang tambahan di tags (di samping tag_text ), Baik? Jika Anda melakukannya, tidak kehilangan data tambahan ini hanya karena semua koneksi terputus adalah perilaku yang diinginkan.

Tetapi jika Anda hanya menginginkan tag_text , Anda akan menggunakan skema yang lebih sederhana di mana menghapus semua koneksi akan sama dengan menghapus tag itu sendiri:

Ini tidak hanya menyederhanakan SQL, tetapi juga menyediakan pengelompokan yang lebih baik .

Sepintas, "toxi" mungkin terlihat seperti menghemat ruang, tetapi dalam praktiknya mungkin tidak demikian, karena memerlukan tabel dan indeks tambahan (dan tag cenderung pendek).

Ukur sebelum Anda memutuskan untuk melakukan sesuatu seperti ini. Fiddle SQL saya yang disebutkan di atas menggunakan urutan bidang yang sangat disengaja di tagmap PK, jadi data dikelompokkan dengan cara yang sangat bersahabat dengan penghitungan semacam ini (ingat:Tabel InnoDB dikelompokkan ). Anda harus memiliki item dalam jumlah yang sangat besar (atau membutuhkan kinerja yang luar biasa tinggi) sebelum ini menjadi masalah.

Bagaimanapun, ukur pada jumlah data yang realistis!




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PDO - Kesalahan fatal:Panggilan ke fungsi anggota fetch() pada non-objek

  2. Setara dengan Kolom IDENTITAS MSSQL di MySQL

  3. Instal MySQL di Ubuntu 14.04

  4. Bagaimana saya bisa menyalin satu baris/catatan dari satu instance MySQL ke yang lain?

  5. javax.naming.NoInitialContextException dengan mysql DataSource