一部のテーブルのデータベースにセカンダリ主キーを作成する


22

いくつかのテーブルに、「second_primary_key」を追加します。これは、uuidまたはランダムな長いキーになります。一部のテーブルでは整数をWebアプリケーションに公開したくないため、必要です。つまり、「/ invoices」ページには、請求書のリストと「/ invoices /:id」へのリンクがあります。ここで、:idは整数です。ユーザーにシステム内の請求書の数を知らせたくないので、「/ invoices / 123」の代わりに「second_primary_key」を使用して、URLが「/ invoices / N_8Zk241vNa」になるようにします。

同じことが、実際のIDを非表示にする他のテーブルにも当てはまります。

これは一般的な慣習ですか?これを実装する最良の方法は何ですか?

結局のところ、この手法は何と呼ばれていますか?


20
整数を完全に削除してみませんか?
larsbe

4
テーブルには、好きなだけユニークなキー/インデックスを定義できます。
abuzittin gillifirca

2
おそらく、あなたはそれを二次候補キーと呼ぶべきです。「プライマリ」は1つだけを示しています。
ウォルターミッティ

4
「2番目のプライマリ」は矛盾表現です。プライマリキーがあり、セカンダリキーを持つことができます。
ハーミングモニカを停止

7
@RobbieDeeデータベースが完全に正規化されていない正当な理由があります。また、候補キーまたは2次キーを持つことは、データを正確に複製することではありません。
マチャド

回答:


0

UUID列を追加することもできますが、実際には必要ありません(する必要はありません)。これは、プレゼンテーション層の問題です。たとえば、1999年だけでなく1,999ドルの通貨値を格納することも夢ではありません。

アプリケーションの実行中に値を不明瞭にする何らかの方法が必要です。これは、アプリケーション自体で行うことも、データベースビューとして行うこともできます。

単一の値についてのみ説明しているため、AESなどの2方向の暗号化を検討することをお勧めします-軽量であるほど良いでしょう。

ハッシュは別の可能性もあります-ハッシュは一方向であるため、請求書番号を取り戻すかどうかに依存します。


48

「代替主キー」を持つことは、リレーショナルデータベースモデリングでよく知られている概念であり、「代替キー」または「副キー」とも呼ばれます。「潜在的な主キー」のセットは「候補キー」と呼ばれます。https://beginnersbook.com/2015/04/alternate-key-in-dbms/を参照してください

これをどのように実装するかは、特にレコードの総数を非表示にする場合は完全にユーザー次第です。「最善の方法」はありません。IDで大文字と小文字を区別するかどうか、印刷された請求書で読み取り可能にする場合、許可されているまたは有用な文字セット、最大長などの要件を確認してくださいエラーなしで電話でそれらを再スペルできる必要があります。


11
また、このシナリオを説明するために使用されるナチュラルキーサロゲートキーという用語を見てきました。
じめじめ

2
@Dari:あなたは「このテクニックは何と呼ばれていますか」と尋ねました-太字で。そして、AES復号化が(おそらくオンザフライで)探している種類のキーを生成し、使用すれば、それは私の答えと矛盾しません。
Doc Brown

1
@Dariアプリに完全に不要なオーバーヘッドが追加されるため
Lamak

1
@RobbieDeeあなたは代替キーが好きではないことをすでに知っていますが、それはそれらが役に立たないという意味ではありません。多くの問題を単純化するため、guidアプローチが好きです。
T.サー-モニカーの復活

1
@RobbieDee SQL Serverは使用していません。MySqlを使用します。そして、それは誰かがProdで何かを作成するために起こります。例えばID 1234で。例えば、Devでは、prodで行うよりも多くのエンティティを作成します。1234は、かなり前に、テストのために使い捨てのエンティティによって取得されました。prodからエンティティをテストする必要がある場合、それをDevに移行する必要があります。そのプライマリキーは既に使用されています。そのエンティティへの参照がGUIDベースである場合、移行ははるかに簡単です。ただし、休止状態は主キーがintまたはlongである場合にはるかにうまく機能するため、それを維持します。私の開発者は怠け者でも無知でもありません-彼らは経験豊富です。
corsiKa

9

ほとんどの請求書には請求書番号があります。ほとんどの会計規則では、会計結果が年の結果にサインオフしなかったり、IRS(または同様の国)がタブで完全な監査を行いたい場合があります。

ユーザーは、請求書番号から、サービスを提供した顧客の数、または請求書の番号付​​け戦略を変更するまでの期間を推測できます。

データベースに保存されている請求書の数は、請求書の総計の測定値ではありません。商工会議所に年度報告書を要求するなど、それを見つける他の方法があります。

ただし、ユーザーのログイン画面の背後で請求書をロックするため、誰もがリクエストできるわけではありません。その後、ユーザーのログイン時に、ajax方法論を使用して未処理の請求書などを要求できます。これにより、データが保護され、URLがajaxで隠されます(通常、ajaxリクエストの作成方法の詳細を確認することはできません) 、データの表示方法と提供方法を​​制御します。


7
銀行業務で使用される一般的な戦略(小切手番号付き)は、増分カウントを1から開始するのではなく、この正確な理由からいくつかのより大きな数で開始することです。
じめじめ

だからこそ、idは古いプライマリキーの代わりではなく、追加のプライマリキーになるはずです。
アレクサンダー

1
主キーとは呼びません。私はスラッグ、名前としてUUIDを探しますが、本質的にはテーブル内の別のインデックスフィールドです。引用ID、請求書番号、何でも。これはフィールドですが、主キーではありません。主キーは一意である必要があり、リレーショナルマッピングに内部的に使用できます。インデックス付きのフィールドの場合、whereクエリですばやく検索できます。userXveryY.where( 'invoice_number'、 'foobarbaz10')。get();
チャラッカ

1
あなたは、米国の特殊性のために必要ではないという主張で技術的な質問に答えています(連続した請求書番号、商工会議所での報告が必要です)。IMOこれは質問にうまく答えられません。
-RemcoGerlich

7

このためにハッシュIDを使用できる場合がありますが、これはまさにこのシナリオを解決するように設計されています。

データベースIDを短いハッシュにエンコードし(YouTubeビデオのURLと同様)、テーブルにセカンダリキーを追加する必要はありません。


2
名前はハッシュではなく、可逆関数であるため、やや誤解を招く可能性があります。しかし、それは問題の完璧な解決策のようです。
クレイジーヨーグルト

2
@CrazyYoghurt True ...彼らはここで名前を付けた理由に対処しました:hashids.org/#why-hashids
Eric King

3

別の一意のキーを作成できますが、作成しないでください。指定された理由ではありません。テーブルサイズを非表示にするより簡単な方法があります。

格納にN_8Zk241vNaは、テーブルの行ごとに12バイト、さらにインデックスにコストがかかります。それはあなたが必要とするものにとってはかなり無駄です。

整数を暗号化するidと、実行時にスペースが不要になり、ほとんどゼロになります。その方法は、プログラミング言語やデータベースによって異なります。

AESを使用すると128ビット整数が得られることに注意してください。これは、おそらくbase64の22文字を意味します。DESや3DESのようなブロックサイズが64の暗号は、希望どおりに11文字を提供します。

テーブルごとに異なるキーを使用します。

必要なのがテーブルのサイズを隠すことだけであれば、すべてのテーブルに共通のシーケンスを使用できます。テーブルの多くに頻繁に挿入がある場合、ボトルネックになる可能性があることに注意してください。HibernateとHi-Loアルゴリズムのようなものを使用すると、この問題はなくなります。


正確に-別の値を隠すためだけにこの値を保存するのは間違っています。
ロビーディー

このシナリオでは、請求書IDの機密性はあまり高くありませんが、将来のある時点でデータをマスクする必要がある場合、データベース内のリレーショナル構造として機密IDを使用する一般的な規則により、大きな頭痛の種になります。それらを属性として扱う方が良いです。
じめじめ

ここでaesを適用するにはどうすればよいですか?
ダリ

@DariはどのようにAESを適用することができます?あなたの言語を知らないと、誰にもわかりません。通常、AESはで動作し、4バイトまたは8バイトでbyte[]書き込みid、一意のテーブル番号を追加して暗号化できます(入力は正確に16バイトでなければなりません)。選択できるモードがある場合は、ECBが適切です。
maaartinus

@DanK何?AESは安全でないと主張していますか?キーを知らなければ、攻撃者は保存された属性よりも良い方法はありません。なし。+++私はあなたのコメントを理解していないと思います。
maaartinus

0

2つの異なるプライマリキーを作成することはできません。もちろん、そのuuidをDBに入れて、現在の主キーの「エイリアス」として使用することができます。一意制約を使用してその列の上にインデックスを配置できますが、主キーは(本質的に)単一のテーブル内の単一のキーです。複合主キーを使用できますが、それはあなたが探しているものではありません。

そこで、それをそこに置くことをお勧めしますが、それはインデックスでのみ持つことです。PKおよび他の一意の列によってデータをクエリするための処理コンポーネントを作成できます。「/ invoices / ...」のリクエストを処理するときは、パラメータを確認するだけです。整数の場合はIDを検索し、そうでない場合はuuidを検索します。または、ID検索で何も見つからなかった場合の代替としてuuid検索を使用できます。

そして、いくつかの「ランダムな」UUIDの生成について:「IDを取得し、定数を追加し、16進数に変換する」などの理由はありません。IDの一意性はuuidの一意性を提供し、16進数は通常の人間にとって読みにくい+定数を追加すると、0000001のようなuuidが回避されます。


1
「「IDを取得し、定数を追加し、16進数に変換する」のようなものではない-それは非常にわかりやすいので-URLを教えてください。システム内の他のすべての請求書を確認します。IMOは問題ありませんこの実際に解き、ただものでは潜在的に作成すること。
CompuChip

/ invoices / ...」のリクエストを処理するときは、パラメータを確認するだけです。整数の場合はIDを検索し、そうでない場合はuuidを検索します/invoices/123/invoices/124、...)したがって、URLからUUIDのみで検索します。
TripeHound

また、すべての16進数に文字が含まれているわけではありません。基になる整数と生成された16進数を常に区別することは不可能です。
TRIG

@CompuChip予想通り、コンピューターに興味があります:-)そのため、一目で16進数を認識できます。しかし、Qは請求書番号を直接表示しないように書かれており、請求書の数を他の人に知らせることができます。妻、母親、隣人に16進数を示すと、彼らはその「奇妙なテキスト」が何であるかを知りません。Q内の請求書番号に従ってセキュリティの問題について通知がある場合は、その目的のために複雑なハッシュ方法をお勧めします。
ハルダ

@TripeHound彼はまだ...いくつかのアクセス制限のエントリポイント内で内部またはIDで検索することができるかもしれない
Jarda

0

両方のキーが同じ事実を指しており、それらが衝突しない場合。元のキーのカスタムハッシュコードを作成するスカラー関数を使用して、元のキーから他のキーを派生しないのはなぜですか。

または、別のマッピングテーブルを作成して、両方のバージョンのキーを保存することもできます。このテーブルは、セカンダリキーを検索するための辞書として機能します。

私の理解では、キーは暗黙的なインデックスであり、インデックスを追加するほど挿入が遅くなります。


+1はい、インデックスを持つ潜在的に大きな文字列列を追加することは、他の人が提案する値のない操作ではありません。ストレージのオーバーヘッドは別として、インデックスが追加されると、挿入速度が低下し始めます。
ロビーディー

0

特定のユースケースのもう1つのアプローチは、データベースとアプリケーションを変更する代わりに、請求書へのカスタムルートを作成して、/ invoices /:f(id)を作成することです。f(id)はidの関数です。

カスタムルートは、リクエストを正しいアクションサーバー側にマッピングする役割を果たします。


0

これは、「代替キー」(AK)とも呼ばれる、完全に受け入れられる方法です。基本的に、AKは別の一意のインデックスまたは一意の制約です。

AKに基づいて外部キー制約を作成することもできます。

可能なユースケースは、説明したようなものです。増え続けるID番号にクラスター化されたPKがありますが、この番号を表示したり、検索条件として使用したりしたくないのです。それに加えて、ランダムな一意の識別子またはAKとしての参照番号があり、それがユーザーに提示するIDです


0

キー/インデックスにはいくつかの種類があります。主キーは特別な一意のインデックスであり、答えが言うように、確かに別の一意のキーを作成できます。そして、非常に正当な理由がない限り、データベース内部を公開しないことが最善であることに同意します。

質問は請求書と番号のコンテキストにあるので、会計業界が請求書番号がどのように見えるかを調査する価値があるかもしれません:http : //smallbusiness.chron.com/assign-invoice-numbers-52422.html

主キーである内部IDと、アプリケーション/顧客に見える請求書番号を持つ別の一意のフィールドを持つのは面倒に思えるかもしれません。しかし、たとえば1年先に、顧客が新しい請求書番号付けスキームを採用することを望むとき、それはそれほど汚くないわけではありません。その場合、他のテーブルの内部IDとその関係を乱すことなく、ワックスのボール全体の番号を付け直します。内部IDをそのままにして、非内部請求書番号の番号を付け直します。

理想的には、変更される可能性のあるキー/外部キーでテーブルを結び付けないように努力し、内部テーブルとリレーションをアプリレイヤーに対して透過的にします。


0

頑張れ。

これは、ブログ記事などによくある「スラッグ」フィールドとは異なりません。URLでの使用に適した主キーとは別にデータベースレコードを参照するユニークな方法です。私は誰もがそれらに反論するのを聞いたことがない。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.