Membuat kunci primer sekunder dalam database untuk beberapa tabel

22

Untuk beberapa tabel saya, saya ingin menambahkan "second_primary_key" yang akan menjadi uuid atau kunci panjang acak. Saya membutuhkannya karena untuk beberapa tabel saya tidak ingin mengekspos bilangan bulat ke aplikasi web saya. Yaitu, pada halaman "/ faktur" Saya memiliki daftar faktur dan tautan ke "/ faktur /: id" di mana: id adalah bilangan bulat. Saya tidak ingin pengguna tahu berapa banyak faktur di sistem saya di sana, karena itu alih-alih "/ faktur / 123" Saya ingin menggunakan "second_primary_key" sehingga urlnya adalah "/ faktur / N_8Zk241vNa"

Hal yang sama berlaku untuk tabel lain di mana saya ingin menyembunyikan id asli.

Saya bertanya-tanya, apakah ini praktik yang biasa? Apa cara terbaik untuk mengimplementasikan ini?

Lagi pula, apa teknik ini, sehingga saya melakukan pencarian?

Dari
sumber
20
Mengapa tidak menyingkirkan bilangan bulat sama sekali?
larsbe
4
Anda dapat menentukan kunci / indeks unik sebanyak yang Anda suka di atas meja.
abuzittin gillifirca
2
Mungkin Anda harus menyebutnya kunci kandidat sekunder. "Primer" hanya menyarankan satu.
Walter Mitty
4
"Primer kedua" adalah sebuah oxymoron. Anda memiliki kunci utama, dan Anda dapat memiliki kunci sekunder.
Stop Harming Monica
7
@RobbieDee ada alasan sah untuk tidak memiliki basis data sepenuhnya dinormalisasi. Dan memiliki kandidat atau kunci sekunder bukan duplikat data.
Machado

Jawaban:

0

Anda dapat menambahkan kolom UUID tetapi Anda benar-benar tidak perlu (dan tidak seharusnya). Ini adalah masalah lapisan presentasi. Anda tidak akan bermimpi mengatakan, menyimpan nilai mata uang sebagai $ 1.999 dan juga 1999.

Anda hanya ingin beberapa cara mengaburkan nilai dengan cepat untuk aplikasi. Anda bisa melakukan ini di aplikasi itu sendiri atau sebagai tampilan basis data.

Karena kita hanya berbicara tentang nilai tunggal, mungkin melihat enkripsi 2 arah seperti AES atau serupa - semakin ringan semakin baik.

Hashing bisa menjadi kemungkinan lain - itu tergantung pada apakah Anda ingin mendapatkan nomor faktur kembali, karena hashing adalah salah satu cara.

Robbie Dee
sumber
48

Memiliki "kunci primer alternatif" adalah konsep yang dikenal baik dalam pemodelan basis data relasional, itu disebut "kunci alternatif", atau kadang-kadang juga "kunci sekunder". Himpunan "kunci primer potensial" disebut "kunci kandidat". Lihat https://beginnersbook.com/2015/04/alternate-key-in-dbms/

Cara Anda menerapkan ini sepenuhnya terserah Anda, terutama jika Anda ingin menyembunyikan jumlah total catatan. Tidak ada "cara terbaik", Anda harus memeriksa persyaratan Anda seperti set karakter yang diizinkan atau berguna, panjang maksimum, jika Anda ingin ID-nya peka huruf besar-kecil atau tidak, jika Anda ingin itu dapat dibaca pada faktur cetak, jika seseorang harus dapat menjualnya kembali di telepon tanpa kesalahan, dan sebagainya.

Doc Brown
sumber
11
Saya juga melihat istilah Natural key vs. Key pengganti yang digunakan untuk menggambarkan skenario ini.
DanK
2
@Dari: Anda bertanya "apa teknik ini disebut" - dalam huruf tebal. Dan jika dekripsi AES - mungkin on the fly - menghasilkan kunci dari jenis yang Anda cari, gunakan, itu tidak bertentangan dengan jawaban saya.
Doc Brown
1
@Dari Karena itu menambahkan overhead yang sama sekali tidak perlu ke aplikasi Anda
Lamak
1
@RobbieDee Kami sudah mengerti bahwa Anda tidak suka kunci alternatif, tetapi itu tidak berarti mereka tidak berguna. Saya suka pendekatan panduan karena menyederhanakan banyak masalah.
T. Sar - Pasang kembali Monica
1
@RobbieDee Kami tidak menggunakan SQL Server. Kami menggunakan MySql. Dan itu terjadi karena seseorang akan membuat sesuatu pada Prod, katakanlah dengan ID 1234. Pada Dev, tentu saja, kita membuat lebih banyak entitas daripada yang kita lakukan pada prod. 1234 telah lama diambil oleh beberapa entitas yang dibuang untuk pengujian. Ketika kita harus menguji suatu entitas dari prod, kita harus memindahkannya kembali ke Dev - dan kunci utamanya sudah digunakan. Migrasi akan jauh lebih mudah jika referensi ke entitas tersebut berdasarkan pedoman. Tapi hibernate bekerja jauh lebih baik dengan kunci primer yang panjang atau int, jadi kami menyimpannya. Devs saya tidak malas atau bodoh - mereka berpengalaman.
corsiKa
9

Sebagian besar faktur memiliki nomor faktur, yang oleh sebagian besar aturan akuntansi harus berurutan atau akuntan mungkin tidak menandatangani hasil tahun atau IRS (atau serupa di negara Anda) mungkin ingin melakukan audit penuh pada tab Anda.

Seorang pengguna dapat menyimpulkan dari nomor faktur berapa banyak pelanggan yang telah Anda layani, atau berapa lama sebelum Anda mengubah strategi penomoran pada faktur.

Berapa banyak faktur yang disimpan dalam basis data bukan ukuran total total faktur Anda. Ada cara lain untuk mengetahuinya, termasuk meminta laporan tahun Anda dari Kamar Dagang.

Namun, saya akan mengunci faktur di balik layar masuk pengguna, jadi tidak semua orang bisa memintanya. Kemudian pada saat login pengguna, mereka dapat menggunakan metodologi ajax untuk meminta faktur mereka yang luar biasa, dll. Ini mengamankan data Anda, menyembunyikan URL dengan ajax (tidak ada yang bisa diganggu untuk melihat rincian bagaimana permintaan ajax dibangun) , dan Anda mengontrol cara data ditampilkan dan ditawarkan.

Tschallacka
sumber
7
Strategi umum yang digunakan dalam perbankan (dengan nomor cek) adalah tidak memulai hitungan tambahan pada 1 tetapi beberapa angka yang lebih besar untuk alasan yang tepat ini.
DanK
Saya pikir itu sebabnya id harus menjadi kunci primer tambahan, bukan pengganti kunci primer lama.
Alexander
1
Saya tidak akan menyebutnya kunci primer. Saya akan mencari siput, UUID sebagai nama, tetapi pada dasarnya itu hanya bidang lain yang diindeks dalam tabel. Id kutipan, nomor faktur, apa pun. Ini adalah bidang, tetapi bukan kunci utama. Kunci utama harus unik, dan dapat digunakan secara internal untuk pemetaan relasional. Jika bidang dalam indeks ini dapat dicari dengan cepat oleh kueri tempat. userXveryY.where ('invoice_number', 'foobarbaz10'). get ();
Tschallacka
1
Anda menjawab pertanyaan teknis dengan argumen yang tidak diperlukan karena kekhasan AS (nomor faktur berurutan yang diperlukan, laporan di Kamar Dagang). IMO ini tidak menjawab pertanyaan dengan baik.
RemcoGerlich
7

Anda mungkin dapat menggunakan hashids untuk ini, ini dirancang untuk menyelesaikan skenario ini dengan tepat.

Ini akan menyandikan ID basis data Anda ke dalam hash pendek (mirip dengan URL video YouTube), dan itu tidak akan mengharuskan Anda untuk menambahkan kunci sekunder ke tabel Anda.

mitchdav
sumber
2
Nama agak menyesatkan, karena tidak hash, tetapi fungsinya dapat dibalik. Tapi itu tampaknya menjadi solusi sempurna untuk masalah tersebut.
Crazy Yoghurt
2
@CrazyYoghurt Benar ... mereka membahas alasan penamaan seperti yang mereka lakukan di sini: hashids.org/#why-hashids
Eric King
3

Anda dapat membuat kunci unik lain, tetapi Anda seharusnya tidak. Bukan karena alasan yang diberikan. Ada cara sederhana untuk menyembunyikan ukuran tabel.

Menyimpan N_8Zk241vNabiaya 12 byte per baris dalam tabel dan bahkan lebih banyak lagi dalam indeks. Itu cukup boros untuk apa yang Anda butuhkan.

Mengenkripsi integer membuat idAnda kehilangan ruang dan hampir tidak ada dalam waktu berjalan. Bagaimana Anda melakukannya tergantung pada bahasa pemrograman Anda dan / atau database Anda.

Perhatikan bahwa dengan AES Anda mendapatkan integer 128 bit, yang berarti 22 karakter di base64, mungkin lebih dari yang Anda inginkan. Sebuah sandi dengan ukuran blok 64 seperti DES atau 3DES memberi Anda 11 karakter, seperti yang Anda inginkan.

Gunakan tombol yang berbeda untuk tabel yang berbeda.

Jika yang Anda butuhkan adalah menyembunyikan ukuran tabel, Anda dapat menggunakan urutan umum untuk semua tabel. Perhatikan bahwa ini mungkin menjadi hambatan jika ada banyak penyisipan di banyak tabel Anda. Dengan sesuatu seperti Hibernate dan algoritma Hi-Lo, masalah ini menghilang.

maaartinus
sumber
Tepat - menyimpan nilai ini hanya untuk menyembunyikan yang lain adalah salah.
Robbie Dee
Ini dapat berfungsi dalam skenario ini sebagai ID faktur tidak benar-benar rahasia tetapi sebagai aturan umum menggunakan ID rahasia karena struktur relasional dalam database akan menyebabkan sakit kepala kerajaan jika Anda perlu menutupi data di beberapa titik di masa mendatang. Lebih baik memperlakukan mereka sebagai atribut.
DanK
bagaimana saya bisa menerapkan aes di sini?
Dari
@Dari Bagaimana Anda bisa menerapkan AES pada apa pun ? Tanpa mengetahui bahasa Anda, tidak ada yang tahu. Biasanya, AES bekerja dengan a byte[], Anda dapat menulis iddalam empat atau delapan byte, menambahkan nomor tabel unik, dan mengenkripsi (input harus tepat 16 byte). Jika ada mode untuk dipilih, ECB benar.
maaartinus
@DanK Apa? Apakah Anda mengklaim AES tidak aman? Tanpa mengetahui kuncinya, tidak ada yang bisa dilakukan penyerang selain untuk atribut yang disimpan. Tidak ada. +++ Saya kira, saya tidak mengerti komentar Anda.
maaartinus
0

IMHO membuat dua kunci utama yang berbeda tidak dimungkinkan. Tentu saja Anda dapat memasukkan uuid itu ke dalam DB untuk menjadikannya sebagai "alias" untuk kunci utama saat ini. Anda bisa meletakkan indeks di atas kolom itu dengan batasan unik, tetapi kunci utama adalah (dari esensinya) satu dalam satu tabel. Mungkin ada kunci primer komposit, tetapi bukan itu yang Anda cari.

Jadi saya sarankan meletakkannya di sana, tetapi hanya dengan indeks. Anda dapat membuat komponen penanganan untuk meminta data dengan PK dan juga kolom unik lainnya. Saat menangani permintaan "/ faktur / ..." cukup periksa parameter - jika bilangan bulat, cari ID, jika tidak, cari uuid. Atau Anda dapat menjadikan pencarian uuid sebagai cadangan jika pencarian ID tidak menemukan apa pun.

Dan tentang menghasilkan beberapa uuids "acak": Mengapa bukan sesuatu seperti "ambil ID, tambahkan KONSTAN, konversikan ke heksadesimal". Kesalahan ID akan memberikan keunikan uuid, angka heksadesimal lebih sulit dibaca untuk manusia normal + menambahkan konstanta akan menghindari memiliki uuid seperti 00000001.

Jarda
sumber
1
"Mengapa bukan sesuatu seperti" ambil ID, tambahkan KONSTAN, konversikan ke heksadesimal "- karena itu cukup mudah diketahui - beri saya URL dan saya akan melihat semua faktur lain dalam sistem. IMO tidak ada masalah bahwa ini benar-benar memecahkan, hanya yang berpotensi menciptakan
CompuChip
" Ketika menangani permintaan untuk" / faktur / ... "cukup periksa parameter - jika integer, cari ID , jika tidak gunakan uuid " Intinya (seperti yang saya mengerti pertanyaannya) adalah untuk mencegah seseorang mencari dengan ID ( /invoices/123, /invoices/124, ...) jadi Anda hanya akan mencari berdasarkan UUID dari URL.
TripeHound
Juga, tidak semua angka heksadesimal mengandung huruf. Tidak mungkin untuk selalu membedakan antara bilangan bulat yang mendasari Anda dan angka hex yang dihasilkan.
TRiG
@ CompuChip seperti yang saya harapkan, Anda tertarik pada komputer :-) sehingga Anda mengenali nomor hex untuk pandangan pertama. Tetapi Q ditulis dengan cara tidak menunjukkan nomor faktur secara langsung untuk memberi tahu orang lain berapa banyak faktur yang ada. Ketika saya menunjukkan beberapa nomor hex kepada istri, ibu, tetangga saya ... mereka tidak akan tahu apa "teks aneh" itu. Jika akan ada pemberitahuan tentang masalah keamanan menurut nomor faktur dalam Q, maka saya akan menyarankan beberapa metode hashing yang kompleks untuk tujuan itu.
Jarda
@ TripeHound dia masih dapat mencari dengan ID secara internal atau dalam beberapa titik masuk yang dibatasi akses ...
Jarda
0

Jika kedua kunci menunjuk ke fakta yang sama, dan mereka tidak akan pernah bertabrakan. Mengapa tidak mengambil kunci lain dari yang asli menggunakan beberapa fungsi skalar yang akan membuat kode hash kustom kunci asli Anda.

sebagai alternatif, Anda dapat membuat tabel pemetaan lampiran, yang akan menyimpan kedua versi kunci. tabel ini akan bertindak sebagai kamus untuk mencari kunci sekunder.

Menurut pemahaman saya, kunci adalah indeks implisit, dan semakin Anda menambahkan indeks, semakin lambat sisipan.

A.Rashad
sumber
+1 Yap, menambahkan apa yang berpotensi kolom string besar dengan indeks tentu bukan nilai operasi bebas yang disarankan orang lain. Menyingkirkan overhead penyimpanan, saat indeks ditambahkan, kecepatan penyisipan mulai menurun.
Robbie Dee
0

Pendekatan lain untuk kasus penggunaan khusus Anda adalah bahwa alih-alih memodifikasi database dan aplikasi, Anda bisa membuat rute kustom ke faktur sehingga / faktur /: f (id) di mana f (id) adalah beberapa fungsi dari id.

Rute khusus bertanggung jawab untuk memetakan permintaan ke sisi server tindakan yang benar.


sumber
0

Ini adalah praktik yang sepenuhnya dapat diterima, juga disebut 'Kunci Alternatif' (AK). Pada dasarnya AK adalah indeks unik atau kendala unik lainnya.

Anda bahkan dapat membuat batasan kunci asing berdasarkan AK Anda.

Case use yang mungkin adalah seperti yang Anda jelaskan: Anda memiliki PK berkerumun di nomor identitas yang terus meningkat, tetapi Anda tidak ingin nomor ini ditampilkan atau digunakan sebagai kriteria pencarian, karena itu hanya dapat ditebak. Jadi selain itu Anda memiliki pengidentifikasi unik acak atau nomor referensi sebagai AK, dan itu adalah ID yang Anda berikan kepada pengguna

Alex Schievink
sumber
0

Ada beberapa jenis kunci / indeks. Kunci utama adalah indeks unik khusus, dan sebagai jawaban mengatakan Anda tentu dapat membuat kunci unik lain. Dan saya setuju bahwa yang terbaik adalah tidak mengekspos internal database Anda kecuali ada alasan yang sangat bagus.

Karena pertanyaannya adalah dalam konteks faktur dan angka, mungkin ada baiknya untuk meneliti bagaimana industri akuntansi mengharapkan angka faktur terlihat: http://smallbusiness.chron.com/assign-invoice-numbers-52422.html

Tampaknya berantakan memiliki id internal yang merupakan kunci utama dan bidang unik lainnya dengan nomor faktur terlihat aplikasi / pelanggan. Tapi itu tidak begitu kotor ketika, katakanlah setahun, pelanggan ingin mengadopsi skema penomoran faktur baru. Dalam hal ini Anda tidak akan mengganggu id internal dan hubungannya di tabel lain untuk menomori ulang seluruh bola lilin. Anda akan mempertahankan id internal Anda apa adanya dan memberi nomor ulang nomor faktur non-internal.

Idealnya Anda berusaha keras untuk tidak mengikat tabel bersama pada kunci / kunci asing yang kemungkinan akan berubah, dan menjaga agar tabel internal dan relasi Anda transparan ke lapisan aplikasi.

Thomas Carlisle
sumber
0

Lakukan untuk itu.

Ini tidak berbeda dengan bidang "siput" yang sering dimiliki artikel blog dan sejenisnya - cara unik untuk merujuk ke catatan basis data yang terpisah dari kunci utama, cocok untuk digunakan dalam URL. Saya tidak pernah mendengar ada yang membantah hal itu.

RemcoGerlich
sumber