コンセプト
あなたはいくつかの基本的な概念を誤解しました、そしてそれから困難が生じます。私たちは、あなたが認識している問題ではなく、最初に概念に取り組む必要があります。その結果、あなたの問題は消えます。
自動インクリメントされたID。もちろん主キーです。
いいえそうではありません。それはよくある誤解です。そして、問題が発生することが保証されています。
ID
フィールドは、英語または技術的またはリレーショナルな意味で主キーにすることはできません。
-
もちろん、SQLでは任意のを宣言できます。
PRIMARY KEY
となるフィールド 、しかし、それは英語、技術、またはリレーショナルの意味で主キーに魔法のように変換されません。チワワに「Rottweiller」という名前を付けることができますが、それはそれをRottweillerに変換せず、チワワのままです。他の言語と同様に、SQLは指定されたコマンドを実行するだけで、PRIMARY KEY
を理解しません。 リレーショナルという意味では、列(またはフィールド)の一意のインデックスをたたくだけです。 -
問題は、宣言しているためです。
ID
PRIMARY KEY
になる 、あなたは考える 主キーとしてのそれの、そしてあなたは期待する 主キーのいくつかの性質を持っていること。 ID値の一意性を除く 、それは何の利益も提供しません。これには、主キーの品質、またはそのことに関するあらゆる種類のリレーショナルキーの品質はありません。これは、英語、技術、または関係の意味での鍵ではありません。非キーをキーとして宣言することで、混乱するだけで、ユーザーがテーブルの重複について不満を言った場合にのみ、ひどく間違っていることがわかります。
リレーショナルテーブルには行が必要です 独自性
PRIMARY KEY
ID
で フィールドは行を提供しません 独自性。したがって、これは行を含むリレーショナルテーブルではなく、そうでない場合は、レコードを含むファイルです。リレーショナルデータベースのテーブルが持つ整合性、パワー(この段階では、結合パワーのみに気付くでしょう)、または速度はありません。
このコードを実行します (MS SQL 2008)そしてそれをあなた自身に証明してください。単にこれを読んで理解してから、この回答の残りの部分を読んでください。このコードは、さらに読む前に実行する必要があります。 。治療的価値があります。
CREATE TABLE dumb_file (
id INT NOT NULL IDENTITY PRIMARY KEY,
name_first CHAR(30) NOT NULL,
name_last CHAR(30) NOT NULL
)
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds, but not intended
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds, but not intended
SELECT * FROM dumb_file
行が重複していることに注意してください 。リレーショナルテーブルには、一意の行が必要です。 。リレーショナルテーブル、またはリレーショナルテーブルの品質がないことのさらなる証明。
レポートで一意なのはID
だけであることに注意してください データではないため、ユーザーが気にしないフィールド、ユーザーが表示しないフィールドは、非常に愚かな「教師」がすべてのファイルを挿入するように指示したことは、さらにナンセンスです。 記録があります 一意性はあるが行ではない 独自性。
データ(実際のデータから余分な追加を差し引いたもの)に関しては、データname_last
およびname_first
ID
がなくても存在できます 分野。人の額にはIDが刻印されていない、名前と名前があります。
混乱させる2番目に使用しているのは、AUTOINCREMENT.
です。 リレーショナル機能のないレコードファイリングシステムを実装している場合は、確かに便利です。レコードを挿入するときに増分をコーディングする必要はありません。ただし、リレーショナルデータベースを実装している場合は、使用することはないため、まったく目的がありません。 SQLには、ほとんどの人が決して使用しない多くの機能があります。
是正措置
では、リレーショナルテーブルの品質と利点のいくつかを取得するために、重複行でいっぱいのdumb_fileをリレーショナルテーブルにアップグレード、昇格するにはどうすればよいでしょうか。これには3つのステップがあります。
-
キーを理解する必要があります
- そして、1970年代のISAMファイルから、リレーショナルモデルに移行しました。 、リレーショナルキーを理解する必要があります 。つまり、リレーショナルデータベースの利点(整合性、パワー、速度)を取得したい場合です。
EFCood博士のRM 、次のように宣言しました:
キーはデータから構成されています
および
テーブルの行は一意である必要があります
あなたの「鍵」はデータから構成されていません。これは、「教師」の病気に感染したことによって引き起こされる、データ以外の追加の寄生虫です。それをそのように認識し、神があなたに与えた完全な精神的能力を自分自身に与えてください(私はあなたに孤立した、断片化された、または抽象的な用語で考えるように求めないことに注意してください、データベース内のすべての要素は互いに統合されなければなりません)。 データから実際のキーを作成します そしてデータからのみ。この場合、可能なキーは
(name_last, name_first).
の1つだけです。 -
このコードを試してください 、宣言 データに対する一意の制約:
CREATE TABLE dumb_table ( id INT NOT NULL IDENTITY PRIMARY KEY, name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT UK UNIQUE ( name_last, name_first ) ) INSERT dumb_table VALUES ( "Mickey", "Mouse" ) -- succeeds INSERT dumb_table VALUES ( "Mickey", "Mouse" ) -- fails, as intended INSERT dumb_table VALUES ( "Minnie", "Mouse" ) -- succeeds SELECT * FROM dumb_table
これで、行の一意性が得られました 。これがほとんどの人に起こるシーケンスです。彼らは複製を許可するファイルを作成します。ドロップダウンに重複が表示されている理由がわかりません。ユーザーが悲鳴を上げる。ファイルを微調整し、重複を防ぐためにインデックスを追加します。彼らは次のバグ修正に進みます。 (彼らは正しくそうするかもしれないし、そうでないかもしれない、それは別の話です。)
-
2番目のレベル。修正を超えて考える人々を考えるために-その。行の一意性が得られたので、天国の名前にあるのは
ID
の目的です。 フィールド、なぜ私たちはそれを持っているのですか?ああ、チワワはロッティという名前で、触るのが怖いからです。PRIMARY KEY
であるという宣言 は誤りですが、それは残り、混乱と誤った期待を引き起こします。唯一の本物のキーは、(name_last, name_fist),
です。 これは代替キーです この時点で。したがって、
ID
フィールドは完全に不要です。それをサポートするインデックスもそうです。愚かなAUTOINCREMENT
もそうです;PRIMARY KEY
であるという誤った宣言も同様です。;そして、あなたがそれに対して抱くかもしれないどんな期待も誤りです。したがって、不要な
ID
を削除してください 分野。 このコードを試してください :CREATE TABLE honest_table ( name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT PK PRIMARY KEY ( name_last, name_first ) ) INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- succeeds INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- fails, as intended INSERT honest_table VALUES ( "Minnie", "Mouse" ) -- succeeds SELECT * FROM honest_table
余分なフィールドやインデックスがなくても、問題なく機能し、意図したとおりに機能します。
これを覚えて、毎回正しく実行してください。
偽の教師
これらの終わりの時に、アドバイスされているように、私たちはそれらの多くを持っています。よく注意してください、ID
を伝播する「教師」 この投稿の詳細な証拠により、列は単にリレーショナルモデルを理解していません。 またはリレーショナルデータベース。特にそれについて本を書く人。
証明されているように、それらは1970年以前のISAMテクノロジーで立ち往生しています。彼らが理解しているのはそれだけであり、彼らが教えることができるのはそれだけです。アクセス、リカバリ、バックアップなどを容易にするためにSQLデータベースコンテナを使用しますが、コンテンツは、リレーショナル整合性、パワー、または速度のない純粋なレコードファイリングシステムです。 AFAIC、それは深刻な詐欺です。
ID
に加えて もちろん、フィールドには、重要な関係かどうかの概念であるいくつかの項目があり、それらを組み合わせることで、私はそのような重大な結論を形成します。これらの他の項目は、この投稿の範囲を超えています。
ある特定の馬鹿のペアは、現在、第一正規形への攻撃を開始しています。彼らは亡命に属しています。
回答
残りの質問です。
自動インクリメント機能を失うことなくリレーショナルテーブルを作成する方法はありますか?
それは自己矛盾する文です。私の説明から理解していただけると思います。リレーショナルテーブルは必要ありません AUTOINCREMENT
の場合 "特徴";ファイルにAUTOINCREMENT
がある場合 、リレーショナルテーブルではありません。
AUTOINCREMENT
SQLデータベースコンテナにExcelスプレッドシートを作成する場合に限り、A,
という名前のフィールドを入力します。 B,
およびC,
上部を横切って、左側に番号を記録します。データベース用語では、それが結果です SELECTの、データのフラット化されたビュー、つまり ソース 整理された(正規化された)データの。
別の可能な(ただし推奨されない)解決策は、最初のテーブルに別の主キーがある場合があります。これは、もちろん、自動増分ステートメントではなく、ユーザーのユーザー名です。必然ですか?
技術的な仕事では、それは主観的であり、常に変化するため、好みは気にしません。技術的な正確さは客観的であり、変わらないため、私たちは技術的な正確さを重視しています。
はい、それは避けられません。それは時間の問題だからです。バグの数; 「できない」の数;あなたが事実に直面し、あなたの誤った宣言を克服し、そしてそれを理解するまで、ユーザーの悲鳴の数:
-
ユーザーが行であることを確認する唯一の方法 一意であり、user_namesが一意であるということは、
UNIQUE
を宣言することです。 それに対する制約 -
user_id
を削除します またはid
ユーザーファイル内 -
user_name
を宣伝しますPRIMARY KEY
へ
はい。偶然ではなく、3番目のテーブルに関する問題全体が解消されるためです。
その3番目のテーブルは連想テーブルです 。必要な唯一のキー(主キー)は、2つの親主キーの複合です。これにより、行の一意性が保証されます 、IDs.
ID
の実装の誤りを教えてくれたのと同じ「教師」がいるので、それについて警告します。 フィールドで、ID
の実装のエラーを教えます 連想テーブルのフィールド。通常のテーブルと同様に、不要で、目的を果たさず、重複が発生し、混乱を招きます。そして、それは二重に不必要です。なぜなら、提供する2つのキーがすでにそこにあり、私たちを正面から見つめているからです。
彼らはRMを理解していないので 、または関係用語では、連想テーブルを「リンク」または「マップ」テーブルと呼びます。 ID
がある場合 フィールド、それらは実際にはファイルです。
ルックアップテーブル
ID
フィールドは特に愚かなことです ルックアップテーブルまたは参照テーブルの場合。それらのほとんどには認識可能なコードがあり、コードは一意である(必要がある)ため、コードのリストを列挙する必要はありません。
さらに、子テーブルのコードをFKとして持つことは良いことです。コードははるかに意味があり、多くの場合、不要な結合を節約できます。
SELECT ...
FROM child_table -- not the lookup table
WHERE gender_code = "M" -- FK in the child, PK in the lookup
代わりに:
SELECT ...
FROM child_table
WHERE gender_id = 6 -- meaningless to the maintainer
またはそれ以上:
SELECT ...
FROM child_table C -- that you are trying to determine
JOIN lookup_table L
ON C.gender_id = L.gender_id
WHERE L.gender_code = "M" -- meaningful, known
これは避けられないことであることに注意してください。ルックアップコードのおよびに一意性が必要です。 説明の一意性。これが、各での重複を防ぐ唯一の方法です。 2つの列の:
CREATE TABLE gender (
gender_code CHAR(2) NOT NULL,
name CHAR(30) NOT NULL
CONSTRAINT PK
PRIMARY KEY ( gender_code )
CONSTRAINT AK
UNIQUE ( name )
)
完全な例
質問の詳細から、SQL構文とFK定義の問題があると思われるので、例として必要なソリューション全体を示します(ファイル定義を指定していないため):
CREATE TABLE user ( -- Typical Identifying Table
user_name CHAR(16) NOT NULL, -- Short PK
name_first CHAR(30) NOT NULL, -- Alt Key.1
name_last CHAR(30) NOT NULL, -- Alt Key.2
birth_date DATE NOT NULL -- Alt Key.3
CONSTRAINT PK -- unique user_name
PRIMARY KEY ( user_name )
CONSTRAINT AK -- unique person identification
PRIMARY KEY ( name_last, name_first, birth_date )
)
CREATE TABLE sport ( -- Typical Lookup Table
sport_code CHAR(4) NOT NULL, -- PK Short code
name CHAR(30) NOT NULL -- AK
CONSTRAINT PK
PRIMARY KEY ( sport_code )
CONSTRAINT AK
PRIMARY KEY ( name )
)
CREATE TABLE user_sport ( -- Typical Associative Table
user_name CHAR(16) NOT NULL, -- PK.1, FK
sport_code CHAR(4) NOT NULL, -- PK.2, FK
start_date DATE NOT NULL
CONSTRAINT PK
PRIMARY KEY ( user_name, sport_code )
CONSTRAINT user_plays_sport_fk
FOREIGN KEY ( user_name )
REFERENCES user ( user_name )
CONSTRAINT sport_occupies_user_fk
FOREIGN KEY ( sport_code )
REFERENCES sport ( sport_code )
)
そこで、PRIMARY KEY
宣言は正直で、主キーです。 ID;
はありません AUTOINCREMENT;
はありません 追加のインデックスはありません。重複する行はありません;誤った期待はありません。結果として生じる問題はありません。
データモデル
定義に使用するデータモデルは次のとおりです。
-
表記法に慣れていない場合は、小さな目盛り、ノッチ、マーク、実線と破線、四角と丸い角はすべて、非常に特殊な意味を持っていることに注意してください。 IDEF1X表記を参照してください。 。
-
写真は千の言葉の価値があります。この場合、標準的な苦情の写真はそれ以上の価値があります。悪いものはそれが描かれた紙の価値がありません。
-
動詞句を注意深く確認してください。これらは述語のセットで構成されています。残りの述語は、モデルから直接決定できます。これが明確でない場合は、お問い合わせください。