sql >> データベース >  >> RDS >> Mysql

SQL:2つの異なるauto_incrementを使用してリレーションテーブルを作成する

    コンセプト

    あなたはいくつかの基本的な概念を誤解しました、そしてそれから困難が生じます。私たちは、あなたが認識している問題ではなく、最初に概念に取り組む必要があります。その結果、あなたの問題は消えます。

    自動インクリメントされた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つのステップがあります。

    1. キーを理解する必要があります

      • そして、1970年代のISAMファイルから、リレーショナルモデルに移行しました。 、リレーショナルキーを理解する必要があります 。つまり、リレーショナルデータベースの利点(整合性、パワー、速度)を取得したい場合です。

      EFCood博士のRM 、次のように宣言しました:

      キーはデータから構成されています

      および

      テーブルの行は一意である必要があります

      あなたの「鍵」はデータから構成されていません。これは、「教師」の病気に感染したことによって引き起こされる、データ以外の追加の寄生虫です。それをそのように認識し、神があなたに与えた完全な精神的能力を自分自身に与えてください(私はあなたに孤立した、断片化された、または抽象的な用語で考えるように求めないことに注意してください、データベース内のすべての要素は互いに統合されなければなりません)。 データから実際のキーを作成します そしてデータからのみ。この場合、可能なキーは(name_last, name_first).の1つだけです。

    2. このコードを試してください 宣言 データに対する一意の制約:

           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
      

      これで、行の一意性が得られました 。これがほとんどの人に起こるシーケンスです。彼らは複製を許可するファイルを作成します。ドロップダウンに重複が表示されている理由がわかりません。ユーザーが悲鳴を上げる。ファイルを微調整し、重複を防ぐためにインデックスを追加します。彼らは次のバグ修正に進みます。 (彼らは正しくそうするかもしれないし、そうでないかもしれない、それは別の話です。)

    3. 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表記を参照してください。

    • 写真は千の言葉の価値があります。この場合、標準的な苦情の写真はそれ以上の価値があります。悪いものはそれが描かれた紙の価値がありません。

    • 動詞句を注意深く確認してください。これらは述語のセットで構成されています。残りの述語は、モデルから直接決定できます。これが明確でない場合は、お問い合わせください。




    1. SSHからのデータベースのバックアップ/エクスポート

    2. SQL ServerでFILEPROPERTY()を使用する方法

    3. XMLをSQLServerに挿入するときにエンコードエラーを切り替えることができない問題を解決する方法

    4. PDOステートメントが機能しない