Tạo khóa chính phụ trong cơ sở dữ liệu cho một số bảng


22

Đối với một số bảng của tôi, tôi muốn thêm "second_primary_key" sẽ là uuid hoặc một số khóa dài ngẫu nhiên. Tôi cần nó vì đối với một số bảng tôi không muốn hiển thị số nguyên cho ứng dụng web của mình. Đó là, trên một trang "/ hóa đơn" Tôi có một danh sách các hóa đơn và liên kết đến "/ Chemicals /: id" trong đó: id là một số nguyên. Tôi không muốn người dùng biết có bao nhiêu hóa đơn trong hệ thống của mình ở đó, do đó thay vì "/ Chemicals / 123" Tôi muốn sử dụng "second_primary_key" để url sẽ là "/ Chemicals / N_8Zk241vNa"

Điều tương tự cũng xảy ra với các bảng khác mà tôi muốn ẩn id thực.

Tôi tự hỏi, đây có phải là một thực tế phổ biến? Cách tốt nhất để thực hiện điều này là gì?

Và kỹ thuật này được gọi là gì sau tất cả, để tôi thực hiện tìm kiếm trên đó?


20
Tại sao không loại bỏ hoàn toàn số nguyên?
larsbe

4
Bạn có thể xác định bao nhiêu khóa / chỉ mục duy nhất tùy thích trên một bảng.
abuzittin gillifirca

2
Có lẽ bạn nên gọi nó là một khóa ứng cử viên phụ. "Chính" chỉ gợi ý một.
Walter Mitty

4
"Chính thứ hai" là một oxymoron. Bạn có một khóa chính và bạn có thể có các khóa phụ.
Ngừng làm hại Monica

7
@RobbieDee có những lý do hợp lệ cho việc không có cơ sở dữ liệu được chuẩn hóa hoàn toàn. Và có một ứng cử viên hoặc khóa phụ không phải là dữ liệu trùng lặp chính xác.
Machado

Câu trả lời:


0

Bạn có thể thêm một cột UUID nhưng bạn thực sự không cần (và không nên). Đây là một mối quan tâm lớp trình bày. Bạn sẽ không mơ ước được nói rằng, lưu trữ một giá trị tiền tệ là $ 1,999 cũng như năm 1999.

Bạn chỉ muốn một số cách che khuất giá trị khi đang bay cho ứng dụng. Bạn có thể làm điều này trong chính ứng dụng hoặc dưới dạng xem cơ sở dữ liệu.

Vì chúng ta chỉ nói về một giá trị duy nhất, có thể nhìn vào mã hóa 2 chiều như AES hoặc tương tự - càng nhẹ thì càng tốt.

Băm có thể là một khả năng khác - nó phụ thuộc vào việc bạn có muốn lấy lại số hóa đơn hay không, vì băm là một cách.


48

Có một "khóa chính thay thế" là một khái niệm nổi tiếng trong mô hình cơ sở dữ liệu quan hệ, nó được gọi là "khóa thay thế", hoặc đôi khi cũng là "khóa phụ". Tập hợp "khóa chính tiềm năng" được gọi là "khóa ứng viên". Xem https://beginnersbook.com/2015/04/alternate-key-in-dbms/

Cách bạn thực hiện điều này hoàn toàn phụ thuộc vào bạn, đặc biệt nếu bạn muốn ẩn tổng số hồ sơ. Không có "cách tốt nhất", bạn nên kiểm tra các yêu cầu của mình như bộ ký tự được phép hoặc hữu ích, độ dài tối đa, nếu bạn muốn ID có phân biệt chữ hoa chữ thường hay không, nếu bạn muốn chúng có thể đọc được trên hóa đơn in, nếu có ai đó phải có khả năng bán lại chúng trên điện thoại mà không gặp lỗi, v.v.


11
Tôi cũng đã thấy các thuật ngữ Khóa tự nhiên so với Khóa thay thế được sử dụng để mô tả kịch bản này.
DanK

2
@Dari: bạn đã hỏi "kỹ thuật này được gọi là gì" - bằng chữ in đậm. Và nếu giải mã AES - có thể đang hoạt động - tạo ra các khóa thuộc loại bạn đang tìm kiếm, hãy sử dụng nó, điều đó không mâu thuẫn với câu trả lời của tôi.
Doc Brown

1
@Dari Bởi vì nó bổ sung một chi phí hoàn toàn không cần thiết cho ứng dụng của bạn
Lamak

1
@RobbieDee Chúng tôi đã nhận được rằng bạn không thích các khóa thay thế, nhưng điều đó không có nghĩa là chúng vô dụng. Tôi thích cách tiếp cận hướng dẫn bởi vì nó đơn giản hóa rất nhiều vấn đề.
T. Sar - Tái lập Monica

1
@RobbieDee Chúng tôi không sử dụng SQL Server. Chúng tôi sử dụng MySql. Và điều đó xảy ra bởi vì ai đó sẽ tạo ra một cái gì đó trên Prod, giả sử với ID 1234. Trên Dev, một cách tự nhiên, chúng tôi tạo ra nhiều thực thể hơn chúng tôi làm trên prod. 1234 đã được thực hiện từ lâu bởi một số thực thể vứt đi để thử nghiệm. Khi chúng tôi phải kiểm tra một thực thể từ prod, chúng tôi phải di chuyển nó trở lại Dev - và khóa chính của nó đã được sử dụng. Việc di chuyển sẽ dễ dàng hơn nhiều nếu các tham chiếu đến thực thể đó dựa trên hướng dẫn. Nhưng ngủ đông hoạt động tốt hơn nhiều với khóa chính là int hoặc dài, vì vậy chúng tôi giữ điều đó. Các nhà phát triển của tôi không lười biếng hay thờ ơ - họ dày dạn kinh nghiệm.
corsiKa

9

Hầu hết các hóa đơn đều có số hóa đơn, bởi hầu hết các quy tắc kế toán cần phải được tuần tự hoặc kế toán viên không được ký vào kết quả năm hoặc IRS (hoặc tương tự ở quốc gia của bạn) có thể muốn thực hiện kiểm toán đầy đủ trên các tab của bạn.

Người dùng có thể suy ra từ số hóa đơn có bao nhiêu khách hàng bạn đã phục vụ hoặc mất bao lâu trước khi bạn thay đổi chiến lược đánh số trên hóa đơn.

Có bao nhiêu hóa đơn được lưu trữ trong cơ sở dữ liệu không phải là thước đo tổng số hóa đơn của bạn. Có nhiều cách khác để tìm ra điều đó, bao gồm yêu cầu báo cáo năm của bạn từ Phòng Thương mại.

Tuy nhiên, tôi sẽ khóa hóa đơn phía sau màn hình đăng nhập của người dùng, vì vậy không phải ai cũng có thể yêu cầu. Sau đó, khi đăng nhập người dùng, họ có thể sử dụng phương pháp ajax để yêu cầu hóa đơn chưa thanh toán của họ, v.v ... Điều này bảo mật dữ liệu của bạn, ẩn URL bằng ajax (thường không ai có thể bận tâm xem chi tiết về cách yêu cầu ajax được xây dựng) và bạn kiểm soát cách hiển thị và cung cấp dữ liệu.


7
Một chiến lược phổ biến được sử dụng trong ngân hàng (có số kiểm tra) là không bắt đầu số tăng dần ở mức 1 mà là một số lớn hơn vì lý do chính xác này.
DanK

Tôi nghĩ đó là lý do tại sao id là khóa chính bổ sung chứ không phải thay thế khóa chính cũ.
Alexander

1
Tôi sẽ không gọi nó là khóa chính. Tôi muốn lấy một con sên, một UUID làm tên, nhưng thực chất nó chỉ là một trường được lập chỉ mục khác trong bảng. Trích dẫn id, số hóa đơn, bất cứ điều gì. Đó là một lĩnh vực, nhưng không phải là một khóa chính. Khóa chính cần phải là duy nhất và có thể được sử dụng nội bộ để ánh xạ quan hệ. Nếu trường trong chỉ mục, nó có thể được tìm kiếm nhanh chóng bằng truy vấn where. userXveryY.where ('billing_number', 'foobarbaz10'). get ();
Tschallacka

1
Bạn đang trả lời một câu hỏi kỹ thuật với một lập luận rằng nó không cần thiết vì đặc thù của Hoa Kỳ (số hóa đơn tuần tự bắt buộc, báo cáo tại Phòng Thương mại). IMO điều này không trả lời tốt câu hỏi.
RemcoGerlich

7

Bạn có thể sử dụng các hàm băm cho việc này, nó được thiết kế để giải quyết chính xác kịch bản này.

Nó sẽ mã hóa ID cơ sở dữ liệu của bạn thành một hàm băm ngắn (tương tự như URL của video YouTube) và nó sẽ không yêu cầu bạn thêm bất kỳ khóa phụ nào vào bảng của mình.


2
Tên có phần sai lệch, vì nó không phải là hàm băm, mà là chức năng đảo ngược. Nhưng nó dường như là giải pháp hoàn hảo cho vấn đề.
Sữa chua điên

2
@CrazyYoghurt Đúng ... họ đã giải quyết lý do đặt tên như họ đã làm ở đây: hashids.org/#why-hashids
Eric King

3

Bạn có thể tạo một khóa duy nhất khác, nhưng bạn không nên. Không phải vì lý do được đưa ra. Có những cách đơn giản hơn để ẩn kích thước bảng.

Lưu trữ N_8Zk241vNachi phí 12 byte mỗi hàng trong bảng và thậm chí nhiều hơn trong chỉ mục. Điều đó khá lãng phí cho những gì bạn cần.

Mã hóa số nguyên idchi phí bạn không có không gian và gần như không có gì trong thời gian chạy. Cách bạn thực hiện tùy thuộc vào ngôn ngữ lập trình và / hoặc cơ sở dữ liệu của bạn.

Lưu ý rằng với AES, bạn nhận được số nguyên 128 bit, có nghĩa là 22 ký tự trong base64, có thể nhiều hơn bạn muốn. Một mật mã có kích thước khối 64 như DES hoặc 3DES cung cấp cho bạn 11 ký tự, giống như bạn muốn.

Sử dụng các phím khác nhau cho các bảng khác nhau.

Nếu tất cả những gì bạn cần là ẩn kích thước bảng, bạn có thể sử dụng một chuỗi chung cho tất cả các bảng. Lưu ý rằng nó có thể bị nghẽn cổ chai nếu thường xuyên chèn vào nhiều bảng của bạn. Với một cái gì đó như Hibernate và thuật toán Hi-Lo, vấn đề này biến mất.


Chính xác - lưu trữ giá trị này chỉ để ẩn cái khác là sai.
Robbie Dee

Điều này có thể hoạt động trong kịch bản này vì ID hóa đơn không thực sự bí mật nhưng theo quy tắc chung sử dụng ID bí mật làm cấu trúc quan hệ trong cơ sở dữ liệu sẽ gây đau đầu cho hoàng gia nếu bạn cần che giấu dữ liệu vào một thời điểm nào đó trong tương lai. Tốt hơn để coi chúng như một thuộc tính.
DanK

Làm thế nào tôi có thể áp dụng aes ở đây?
Dari

@Dari Làm thế nào bạn có thể áp dụng AES cho bất cứ điều gì ? Không biết ngôn ngữ của bạn, không ai có thể nói. Thông thường, AES hoạt động với a byte[], bạn có thể viết idbằng bốn hoặc tám byte, thêm số bảng duy nhất và mã hóa (đầu vào phải chính xác là 16 byte). Nếu có các chế độ để lựa chọn, ECB là đúng.
maaartinus

@DanK Gì? Bạn đang tuyên bố AES là không an toàn? Không biết khóa, không có gì kẻ tấn công có thể làm tốt hơn một thuộc tính được lưu trữ. Không có gì. +++ Tôi đoán, tôi không hiểu bình luận của bạn.
maaartinus

0

IMHO tạo hai khóa chính khác nhau là không thể. Tất nhiên bạn có thể đặt uuid đó trong DB để đặt nó làm "bí danh" cho khóa chính hiện tại. Bạn có thể đặt một chỉ mục phía trên cột đó với ràng buộc duy nhất, nhưng khóa chính là (từ bản chất của nó) trong một bảng duy nhất. Có thể có khóa chính tổng hợp, nhưng đó không phải là những gì bạn đang tìm kiếm.

Vì vậy, tôi đề nghị đặt nó ở đó, nhưng chỉ có nó với chỉ mục. Bạn có thể tạo thành phần xử lý để truy vấn dữ liệu bằng PK cũng như cột duy nhất khác. Khi xử lý yêu cầu "/ Chemicals / ..." chỉ cần kiểm tra tham số - nếu đó là số nguyên, hãy tìm ID, nếu không thì tìm kiếm uuid. Hoặc bạn có thể có tìm kiếm uuid như một dự phòng khi tìm kiếm ID không tìm thấy gì.

Và về việc tạo một số uuids "ngẫu nhiên": Tại sao không phải là "lấy ID, thêm CONSTANT, chuyển đổi thành thập lục phân". Tính duy nhất của ID sẽ cung cấp tính duy nhất của uuid, số thập lục phân khó đọc hơn đối với người bình thường + thêm hằng số sẽ tránh có uuid như 00000001.


1
"Tại sao không phải là" lấy ID, thêm CONSTANT, chuyển đổi thành thập lục phân "- bởi vì điều đó khá dễ để tìm ra - hãy cho tôi một URL và tôi sẽ xem xét tất cả các hóa đơn khác trong hệ thống. IMO không có vấn đề gì rằng điều này thực sự giải quyết, chỉ là những thứ nó có khả năng tạo ra.
CompuChip

" Khi xử lý yêu cầu" / Chemicals / ... "chỉ cần kiểm tra tham số - nếu đó là số nguyên, hãy tìm ID , nếu không tìm kiếm uuid " Toàn bộ điểm (như tôi hiểu câu hỏi) là để ngăn người khác tìm kiếm bằng ID ( /invoices/123, /invoices/124, ...) vì vậy bạn sẽ chỉ tìm kiếm theo UUID từ URL.
TripeHound

Ngoài ra, không phải tất cả các số thập lục phân đều chứa các chữ cái. Không thể luôn luôn phân biệt giữa các số nguyên cơ bản của bạn và các số hex được tạo của bạn.
TRiG

@CompuChip như tôi mong đợi, bạn quan tâm đến máy tính :-) để bạn nhận ra số hex cho cái nhìn đầu tiên. Nhưng Q được viết theo cách không hiển thị trực tiếp số hóa đơn để cho người khác biết có bao nhiêu hóa đơn. Khi tôi đưa một số số hex cho vợ, mẹ, hàng xóm ... họ sẽ không biết "văn bản lạ" đó là gì. Nếu có thông báo về vấn đề bảo mật theo số hóa đơn trong Q, thì tôi sẽ đề xuất một số phương pháp băm phức tạp cho mục đích đó.
Jarda

@TripeHound anh ấy vẫn có thể tìm kiếm bằng ID nội bộ hoặc trong một số điểm nhập cảnh bị hạn chế truy cập ...
Jarda

0

Nếu cả hai khóa đều chỉ vào cùng một thực tế và chúng sẽ không bao giờ va chạm. Tại sao không lấy khóa khác từ khóa gốc bằng cách sử dụng một số hàm vô hướng sẽ tạo mã băm tùy chỉnh của khóa gốc của bạn.

cách khác, bạn có thể tạo một bảng ánh xạ phụ lục, sẽ lưu cả hai phiên bản của khóa. bảng này sẽ hoạt động như một từ điển để tra cứu khóa phụ.

Theo sự hiểu biết của tôi, các khóa là các chỉ mục ngầm định và bạn càng thêm các chỉ mục, các phần chèn sẽ chậm hơn.


+1 Yep, thêm những gì có khả năng là một cột chuỗi lớn với một chỉ mục chắc chắn không phải là hoạt động miễn phí giá trị mà người khác đề xuất. Chi phí lưu trữ sang một bên, khi các chỉ mục được thêm vào, tốc độ chèn bắt đầu giảm.
Robbie Dee

0

Một cách tiếp cận khác cho trường hợp sử dụng cụ thể của bạn là thay vì sửa đổi cơ sở dữ liệu và ứng dụng, bạn chỉ có thể tạo tuyến tùy chỉnh tới hóa đơn để / Chemicals /: f (id) trong đó f (id) là một số chức năng của id.

Tuyến tùy chỉnh có trách nhiệm ánh xạ một yêu cầu đến phía máy chủ hành động chính xác.


0

Đó là một thực tế hoàn toàn có thể chấp nhận được, còn được gọi là 'Khóa thay thế' (AK). Về cơ bản AK là một chỉ số duy nhất hoặc ràng buộc duy nhất.

Bạn thậm chí có thể tạo các ràng buộc khóa ngoại dựa trên AK của bạn.

Trường hợp sử dụng có thể giống như những gì bạn đã giải thích: bạn có một cụm PK trên số nhận dạng ngày càng tăng, nhưng bạn không muốn số này được hiển thị hoặc được sử dụng làm tiêu chí tìm kiếm, vì đơn giản là có thể đoán được. Vì vậy, ngoài ra bạn có số nhận dạng hoặc số tham chiếu duy nhất ngẫu nhiên dưới dạng AK và đó là ID bạn trình bày cho người dùng


0

Có một số loại khóa / chỉ mục. Khóa chính là một chỉ mục duy nhất đặc biệt và như các câu trả lời cho biết bạn chắc chắn có thể tạo một khóa duy nhất khác. Và tôi đồng ý rằng tốt nhất là không để lộ nội bộ cơ sở dữ liệu của bạn trừ khi có một lý do rất chính đáng.

Vì câu hỏi nằm trong ngữ cảnh của hóa đơn và số, nên có thể đáng để nghiên cứu cách ngành kế toán kỳ vọng số hóa đơn sẽ trông như thế nào: http : // smallbusiness. Sync.com/assign-invoice-numbers-52422.html

Có vẻ như lộn xộn khi có id nội bộ là khóa chính và trường duy nhất khác có số hóa đơn hiển thị của ứng dụng / khách hàng. Nhưng nó không quá ô uế khi nói rằng một năm sau, khách hàng muốn áp dụng chương trình đánh số hóa đơn mới. Trong trường hợp đó, bạn sẽ không làm phiền id nội bộ và các mối quan hệ của nó trong các bảng khác để đánh số lại toàn bộ quả bóng sáp. Bạn sẽ giữ id nội bộ của mình như cũ và đánh số lại số hóa đơn không nội bộ.

Lý tưởng nhất là bạn cố gắng không liên kết các bảng với nhau trên các khóa / khóa ngoại có khả năng thay đổi và giữ cho các bảng và quan hệ nội bộ của bạn trong suốt với lớp ứng dụng.


0

Đi cho nó.

Điều này không giống với trường "sên" mà các bài viết trên blog và những thứ tương tự thường có - một cách duy nhất để tham chiếu bản ghi cơ sở dữ liệu tách biệt với khóa chính, phù hợp để sử dụng trong URL. Tôi chưa bao giờ nghe ai tranh cãi với những người đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.