Saya memiliki Competitions
tabel hasil yang memuat nama anggota tim dan peringkat mereka di satu sisi.
Di sisi lain saya perlu mempertahankan daftar nama-nama pesaing yang unik :
CREATE TABLE Competitors (cName nvarchar(64) primary key)
Sekarang saya memiliki sekitar 200.000 hasil di tabel 1 dan ketika tabel pesaing kosong saya bisa melakukan ini:
INSERT INTO Competitors SELECT DISTINCT Name FROM CompResults
Dan permintaan hanya membutuhkan waktu 5 detik untuk memasukkan sekitar 11.000 nama.
Sejauh ini ini bukan aplikasi kritis sehingga saya dapat mempertimbangkan memotong tabel Kompetitor sebulan sekali, ketika saya menerima hasil kompetisi baru dengan sekitar 10.000 baris.
Tapi apa praktik terbaik ketika hasil baru ditambahkan, dengan pesaing baru DAN yang ada? Saya tidak ingin memotong tabel pesaing yang ada
Saya perlu melakukan pernyataan INSERT hanya untuk pesaing baru dan tidak melakukan apa pun jika ada.
sumber
NVARCHAR(64)
kolom kunci utama Anda (dan dengan demikian: pengelompokan) !! Pertama-tama - ini adalah kunci yang sangat luas - hingga 128 byte; dan kedua itu ukuran variabel - lagi: tidak optimal ... Ini tentang pilihan terburuk yang dapat Anda miliki - kinerja Anda akan sangat buruk, dan fragmentasi tabel dan indeks akan berada di 99,9% setiap saat .....cName
Gagal Anda dalam tiga dari empat kategori .... (tidak sempit, mungkin tidak statis, dan jelas tidak pernah meningkat)Jawaban:
Semantik Anda bertanya "masukkan Pesaing di tempat yang belum ada":
sumber
Opsi lain adalah dengan bergabung dengan tabel Hasil Anda dengan pesaing Anda yang ada Tabel dan menemukan pesaing baru dengan memfilter catatan berbeda yang tidak cocok dengan bergabung:
Sintaks baru MERGE juga menawarkan cara yang ringkas, elegan, dan efisien untuk melakukan itu:
sumber
Tidak tahu mengapa orang lain belum mengatakan ini;
NORMALISASI.
Anda punya meja yang menjadi model kompetisi? Kompetisi terdiri dari Pesaing? Anda memerlukan daftar berbeda Pesaing dalam satu atau lebih Kompetisi ......
Anda harus memiliki tabel berikut ini .....
Dengan Kendala pada Kompetisi Pesaing. Kompetisi ID dan Pesaing ID menunjuk pada tabel lainnya.
Dengan struktur tabel seperti ini - kunci Anda semuanya INTS sederhana - sepertinya tidak ada KUNCI ALAMI yang baik yang akan cocok dengan model jadi saya pikir KUNCI SURROGATE sangat cocok di sini.
Jadi jika Anda memiliki ini maka untuk mendapatkan daftar pesaing yang berbeda dalam kompetisi tertentu Anda dapat mengeluarkan pertanyaan seperti ini:
Dan jika Anda ingin skor untuk setiap kompetisi ada pesaing:
Dan ketika Anda memiliki kompetisi baru dengan pesaing baru maka Anda cukup memeriksa mana yang sudah ada di tabel Pesaing. Jika sudah ada maka Anda tidak memasukkan ke dalam Pesaing untuk Pesaing tersebut dan melakukan penyisipan untuk yang baru.
Kemudian Anda memasukkan Kompetisi baru di Kompetisi dan akhirnya Anda hanya membuat semua tautan di Kompetitor Kompetisi.
sumber
Anda harus bergabung dengan tabel bersama dan mendapatkan daftar pesaing unik yang belum ada
Competitors
.Ini akan menyisipkan catatan unik.
Mungkin ada saatnya penyisipan ini harus dilakukan dengan cepat tanpa bisa menunggu pemilihan nama-nama unik. Dalam hal ini, Anda bisa memasukkan nama-nama unik ke dalam tabel sementara, dan kemudian menggunakan tabel sementara itu untuk memasukkan ke dalam tabel asli Anda. Ini berfungsi dengan baik karena semua pemrosesan terjadi pada saat Anda memasukkan ke tabel sementara, sehingga tidak mempengaruhi tabel asli Anda. Kemudian ketika Anda memiliki semua pemrosesan selesai, Anda melakukan memasukkan cepat ke tabel sebenarnya. Saya bahkan mungkin membungkus bagian terakhir, di mana Anda memasukkan ke dalam tabel nyata, di dalam suatu transaksi.
sumber
Jawaban di atas yang berbicara tentang normalisasi sangat bagus! Tetapi bagaimana jika Anda menemukan diri Anda dalam posisi seperti saya di mana Anda tidak diizinkan menyentuh skema atau struktur basis data sebagaimana adanya? Misalnya, DBA adalah 'dewa' dan semua revisi yang disarankan menuju / dev / null?
Dalam hal itu, saya merasa seperti ini telah dijawab dengan posting Stack Overflow ini juga dalam hal semua pengguna di atas memberikan contoh kode.
Saya memposting ulang kode dari INSERT VALUES WHERE NOT EXISTS yang paling membantu saya karena saya tidak bisa mengubah tabel database yang mendasarinya:
Kode di atas menggunakan bidang yang berbeda dari yang Anda miliki, tetapi Anda mendapatkan inti umum dengan berbagai teknik.
Perhatikan bahwa sesuai jawaban asli pada Stack Overflow, kode ini disalin dari sini .
Pokoknya poin saya adalah "praktik terbaik" sering kali mengarah pada apa yang Anda bisa dan tidak bisa lakukan serta teori.
Semoga berhasil!
sumber
Normalisasi tabel operasional Anda seperti yang disarankan oleh Transact Charlie, adalah ide yang baik, dan akan menghemat banyak sakit kepala dan masalah seiring waktu - tetapi ada hal-hal seperti tabel antarmuka , yang mendukung integrasi dengan sistem eksternal, dan tabel pelaporan , yang mendukung hal-hal seperti analitis pengolahan; dan tipe-tipe tabel itu tidak harus dinormalisasi - pada kenyataannya, sangat sering itu jauh, jauh lebih nyaman dan berkinerja bagi mereka untuk tidak .
Dalam hal ini, saya pikir proposal Transact Charlie untuk tabel operasional Anda adalah yang baik.
Tapi saya akan menambahkan indeks (tidak harus unik) ke CompetitorName di tabel Pesaing untuk mendukung sambungan efisien di CompetitorName untuk keperluan integrasi (memuat data dari sumber eksternal), dan saya akan menempatkan tabel antarmuka ke dalam campuran: CompetitionResults.
CompetitionResults harus berisi data apa pun yang dimiliki hasil kompetisi Anda di dalamnya. Maksud dari tabel antarmuka seperti ini adalah untuk membuatnya secepat dan semudah mungkin untuk memotong dan memuatnya kembali dari lembar Excel atau file CSV, atau dalam bentuk apa pun Anda menyimpan data tersebut.
Tabel antarmuka itu tidak boleh dianggap sebagai bagian dari set tabel operasional yang dinormalisasi. Kemudian Anda dapat bergabung dengan CompetitionResults seperti yang disarankan oleh Richard, untuk menyisipkan catatan ke dalam Pesaing yang belum ada, dan memperbarui yang ada (misalnya jika Anda benar-benar memiliki informasi lebih lanjut tentang pesaing, seperti nomor telepon atau alamat email mereka).
Satu hal yang ingin saya catat - dalam kenyataannya, Nama Pesaing, bagi saya, tampaknya sangat unik dalam data Anda . Dalam 200.000 pesaing, Anda mungkin memiliki 2 atau lebih David Smiths, misalnya. Jadi saya sarankan Anda mengumpulkan lebih banyak informasi dari pesaing, seperti nomor telepon atau alamat email mereka, atau sesuatu yang lebih cenderung unik.
Tabel operasional Anda, Pesaing, seharusnya hanya memiliki satu kolom untuk setiap item data yang berkontribusi terhadap kunci alami komposit; misalnya harus memiliki satu kolom untuk alamat email utama. Tetapi tabel antarmuka harus memiliki slot untuk nilai lama dan baru untuk alamat email utama, sehingga nilai lama dapat digunakan untuk mencari catatan di Pesaing dan memperbarui bagian itu ke nilai baru.
Jadi CompetitionResults harus memiliki beberapa bidang "lama" dan "baru" - oldEmail, newEmail, oldPhone, newPhone, dll. Dengan begitu Anda dapat membentuk kunci komposit, di Pesaing, dari Nama Pesaing, Email, dan Telepon.
Kemudian ketika Anda memiliki beberapa hasil kompetisi, Anda dapat memotong dan memuat kembali tabel CompetitionResults Anda dari lembar excel Anda atau apa pun yang Anda miliki, dan menjalankan satu, penyisipan efisien untuk memasukkan semua pesaing baru ke dalam tabel Pesaing, dan pembaruan tunggal, efisien untuk memperbarui semua informasi tentang pesaing yang ada dari Hasil Kompetisi. Dan Anda dapat melakukan satu penyisipan untuk menyisipkan baris baru ke dalam tabel CompetitionCompetitors. Hal-hal ini dapat dilakukan dalam prosedur tersimpan ProcessCompetitionResults, yang dapat dieksekusi setelah memuat tabel CompetitionResults.
Itu semacam deskripsi yang belum sempurna dari apa yang saya lihat dilakukan berulang-ulang di dunia nyata dengan Aplikasi Oracle, SAP, PeopleSoft, dan daftar cucian suite perangkat lunak perusahaan lainnya.
Satu komentar terakhir yang saya buat adalah komentar yang pernah saya buat di SO: Jika Anda membuat kunci asing yang memastikan bahwa ada Pesaing di tabel Pesaing sebelum Anda dapat menambahkan baris dengan Pesaing di dalamnya ke Pesaing Pesaing, pastikan bahwa kunci asing diatur untuk membuat pembaruan dan menghapus . Dengan begitu jika Anda perlu menghapus pesaing, Anda bisa melakukannya dan semua baris yang terkait dengan pesaing itu akan dihapus secara otomatis. Jika tidak, secara default, kunci asing akan meminta Anda untuk menghapus semua baris terkait dari CompetCompetitors sebelum itu akan membiarkan Anda menghapus Pesaing.
(Beberapa orang berpikir kunci asing non-kaskade adalah tindakan pencegahan keamanan yang baik, tetapi pengalaman saya adalah bahwa mereka hanya rasa sakit yang luar biasa di pantat yang lebih sering daripada tidak hanya akibat dari pengawasan dan mereka membuat banyak pekerjaan. untuk DBA. Berurusan dengan orang-orang yang secara tidak sengaja menghapus hal-hal adalah mengapa Anda memiliki hal-hal seperti dialog "apakah Anda yakin" dan berbagai jenis cadangan reguler dan sumber data yang berlebihan. Jauh, jauh lebih umum untuk benar-benar ingin menghapus pesaing, yang datanya semua misalnya kacau, daripada menghapus secara tidak sengaja dan kemudian pergi "Oh tidak! Saya tidak bermaksud melakukan itu! Dan sekarang saya tidak memiliki hasil kompetisi mereka! Aaaahh!" Yang terakhir ini tentu cukup umum, jadi , Anda harus siap untuk itu, tetapi yang pertama jauh lebih umum,jadi cara termudah dan terbaik untuk mempersiapkan yang pertama, imo, adalah dengan hanya membuat pembaruan dan menghapus kunci asing.)
sumber
Ok, ini ditanyakan 7 tahun yang lalu, tapi saya pikir solusi terbaik di sini adalah melepaskan meja baru sepenuhnya dan hanya melakukan ini sebagai tampilan khusus. Dengan begitu Anda tidak menggandakan data, tidak ada kekhawatiran tentang data unik, dan itu tidak menyentuh struktur database yang sebenarnya. Sesuatu seperti ini:
Barang-barang lain dapat ditambahkan di sini seperti bergabung di tabel lain, klausa WHERE, dll. Ini kemungkinan besar solusi yang paling elegan untuk masalah ini, karena Anda sekarang hanya dapat meminta tampilan:
... dan tambahkan klausa WHERE, IN, atau EXISTS apa pun ke kueri tampilan.
sumber