SQL:创建具有 2 个不同 auto_increment 的关系 table

SQL: Creating a Relational table with 2 different auto_increment

我有 2 个 table,每个都有自己的自动递增 IDs,它们当然是主键。

当我想创建第 3 个 table 来建立这 2 个 table 之间的关系时,我总是出错。

第一个是你只能有 1 个自动递增的列,第二个是当我从这 2 个中删除 auto_increment 语句时发生的,因此 AQL 不允许我将它们设为外键,因为类型匹配失败。

有没有一种方法可以在不丢失自动递增功能的情况下创建关系 table?

另一种可能(但不是首选)的解决方案可能是在第一个 table 中有另一个主键,它是用户的用户名,当然不是 auto_increment 语句。难不成table?

提前致谢。

1 个概念

你误解了一些基本概念,困难由此而来。我们必须首先解决概念,而不是您认为的问题,因此,您的问题就会消失。

auto incremented IDs, which are of course primary keys.

不,他们不是。这是一个常见的误解。问题肯定会接踵而至。

ID 字段不能是英语或技术或关系意义上的主键。

  • 当然,在 SQL 中,您可以将 任何 字段声明为 PRIMARY KEY,但这不会神奇地转换它变成英语、技术或关系意义上的主键。您可以将吉娃娃命名为“罗威纳犬”,但这并不能将其变成罗威纳犬,它仍然是吉娃娃犬。像任何语言一样,SQL 只是执行你给它的命令,它不理解 PRIMARY KEY 是关系的意思,它只是在列(或字段)上创建一个唯一索引。

  • 问题是,既然你已经声明 IDPRIMARY KEY,你认为 作为主键,您可能 期望 它具有主键的某些特性。除了 ID value 的唯一性外,它没有任何好处。它具有 none 的主键或任何类型的关系键的特性。它不是英语、技术或关系意义上的密钥。通过将非键声明为键,您只会让自己感到困惑,只有当用户抱怨 table.

    中存在重复项时,您才会发现存在严重错误。

2 关系模型

2.1 关系 table 必须具有 唯一性

ID 字段上的 PRIMARY KEY 不提供 唯一性。因此它不是包含行的关系 table,如果不是,那么它是一个包含记录的文件。它没有关系数据库中 table 所具有的任何完整性或功能(在此阶段您将只知道连接功能)或速度。

  • 执行this code(MSSQL)并证明给自己看。请不要简单地阅读并理解它,然后继续阅读本答案的其余部分,在进一步阅读之前必须执行此代码。有疗效。

    -- [1] Dumb, broken file
    -- Ensures unique RECORDS, allows duplicate ROWS
    
    CREATE TABLE dumb_file (
         id         INT       IDENTITY PRIMARY KEY, 
         name_first CHAR(30), 
         name_last  CHAR(30)
         )
    
    INSERT dumb_file VALUES
         ( 'Mickey', 'Mouse' ),
         ( 'Mickey', 'Mouse' ),
         ( 'Mickey', 'Mouse' )
    
    SELECT *
         FROM dumb_file
    

请注意您有重复的 。关系 table 需要具有唯一的 。进一步证明你没有关系table,或任何一个的品质。

注意,在你的报告中,唯一独特的是ID字段,没有用户关心,没有用户看到,因为它不是数据,是一些额外的废话,一些非常愚蠢的“老师”让你把每个文件都放进去。您有 record 唯一性但没有 row 唯一性。

就数据而言(真实数据减去多余的添加),数据name_lastname_first可以在没有ID字段的情况下存在。一个人有名字和姓氏,额头上没有印上身份证。

您正在使用的第二件让您感到困惑的事情是 AUTOINCREMENT. 如果您正在实施一个没有关系功能的记录归档系统,当然,它很有帮助,您不必编写增量代码插入记录时。但是如果你正在实现一个关系数据库,它就没有任何用处,因为你永远不会使用它。 SQL 中有许多大多数人从未使用过的功能。

2.2 纠正措施

那么如何将充满重复行的 dumb_file 升级、提升到关系 table,以获得关系 [=328] 的一些品质和优势=] ?这需要三个步骤。

  1. 你需要了解Keys

    而且由于我们已经从 1970 年代的 ISAM 文件发展到关系模型,您需要了解关系键。也就是说,如果您希望获得关系数据库的好处(完整性、功能、速度)。

    在 Codd 的关系模型中

    根据数据组成key

    table 中的行必须是唯一的

    你的“钥匙”不是由数据组成的。它是一些额外的、非数据的寄生虫,是由于你感染了你的“老师”的疾病而引起的。如此认识它,并允许自己发挥上帝赋予你的全部心智能力(注意,我不要求你以孤立、支离破碎或抽象的方式思考,数据库中的所有元素必须相互集成)。

    根据数据 并且仅根据数据构成真正的密钥。在这种情况下,只有一个可能的Key:(name_last, name_first).

  2. Try this code, 声明对数据的唯一约束:

    -- [2] dumb_file fixed, elevated to table, prevents duplicate rows
    -- still dumb
    CREATE TABLE dumb_table (
        id         INT       IDENTITY PRIMARY KEY, 
        name_first CHAR(30), 
        name_last  CHAR(30),
        CONSTRAINT UK
            UNIQUE  ( name_last, name_first )
        )
    INSERT dumb_table VALUES
        ( 'Mickey', 'Mouse' ),
        ( 'Minnie', 'Mouse' )
    
    SELECT *
        FROM dumb_table
    
    INSERT dumb_table VALUES
        ( 'Mickey', 'Mouse' )
    

    现在我们有行唯一性。这就是发生在大多数人身上的顺序:他们创建一个允许欺骗的文件;他们不知道为什么下拉列表中会出现受骗者;用户尖叫;他们调整文件并添加索引以防止重复;他们去下一个错误修复。 (他们可能这样做正确与否,那是另一回事。)

  3. 第二关。对于思考超出固定范围的思考的人。既然我们现在有了行唯一性,天哪,ID 字段的目的是什么,我们为什么还要拥有它???哦,因为吉娃娃叫Rotty,我们不敢碰它。

    它是 PRIMARY KEY 的声明是错误的,但它仍然存在,导致混淆和错误的期望。唯一真正的密钥是 (name_last, name_fist),,此时它是 备用密钥

    因此 ID 字段是完全多余的;支持它的索引也是如此;笨蛋也是AUTOINCREMENT;虚假声明也是 PRIMARY KEY;你对它的任何期望都是错误的。

    因此删除多余的 ID 字段。 Try this code:

    -- [3] Relational Table
    -- Now that we have prevented duplicate data, the id field 
    -- AND its additional index serves no purpose, it is superfluous,
    -- like an udder on a bull.  If we remove the field AND the 
    -- supporting index, we obtain a Relational table.
    
    CREATE TABLE relational_table (
        name_first CHAR(30), 
        name_last  CHAR(30),
        CONSTRAINT PK
            PRIMARY KEY ( name_last, name_first )
        )
    
    INSERT relational_table VALUES
        ( 'Mickey', 'Mouse' ),
        ( 'Minnie', 'Mouse' )
    
    SELECT *
        FROM relational_table
    
    INSERT relational_table VALUES
        ( 'Mickey', 'Mouse' )
    

工作正常,按预期工作,没有无关的字段和索引。

请记住这一点,并每一次都做对。

2.3 假教师

在这些末世,正如所建议的那样,我们将有很多。请注意,凭借此 post 中的详细证据,宣传 ID 列的“老师”根本不了解 关系模型 或关系数据库.尤其是那些写书的人。

证据表明,它们停留在 1970 年以前的 ISAM 技术中。这就是他们所了解的一切,这就是他们所能教导的一切。他们使用 SQL 数据库容器,以便于访问、恢复、备份等,但内容是纯粹的记录归档系统,没有关系完整性、功能或速度。 AFAIC,这是一个严重的欺诈行为。

当然,除了 ID 字段之外,还有几项是关系或非关系的关键概念,综合起来,使我得出如此严肃的结论。那些其他项目超出了本 post.

的范围

一对特别的白痴目前正在对第一范式发起攻击。他们属于收容所。

3 解决方案

现在回答你剩下的问题。

3.1 答案

Is there a way that I can create a relational table without losing auto increment features?

这是一句自相矛盾的话。我相信您会从我的解释中理解,关系 tables 不需要 AUTOINCREMENT “功能”;如果文件有 AUTOINCREMENT,则它不是关系 table.

AUTOINCREMENTIDENTITY 仅适用于一件事:当且仅当您要在 SQL 数据库容器中创建 Excel 电子表格时,在顶部填满名为 A, B,C, 的字段,并在左侧记录数字。在数据库术语中,即 result of a SELECT,数据的扁平视图,即 not the source 数据,已组织(规范化)。

Another possible (but not preferred) solution may be there is another primary key in the first table, which is the username of the user, not with an auto increment statement, of course. Is it inevitable?

在技术工作中,我们不关心偏好,因为那是主观的,而且它一直在变化。我们关心技术正确性,因为那是 objective,它不会改变。

是的,这是必然的table。因为这只是时间问题;错误数量; “不能做”的次数;用户尖叫的数量,直到你面对事实,克服你的虚假声明,并意识到:

  • 确保用户 是唯一的,user_names 是唯一的唯一方法是声明一个 UNIQUE 约束在上面

  • 并删除用户文件中的user_idid

  • user_name提升为PRIMARY KEY

是的,因为你与第三个 table 的整个问题都被排除了,这并非巧合。

第三个 table 是一个 关联 Table。唯一需要的键(主键)是两个父主键的组合。这确保了 的唯一性,它们由它们的键标识,而不是它们的 IDs.

我警告你这一点,因为教你实施 ID 字段错误的“老师”,教你在关联 Table 中实施 ID 字段的错误, 其中,就像普通的 table 一样,它是多余的,毫无用处,引入重复项并引起混淆。而且它是双重多余的,因为提供的两个键已经在那里,盯着我们看。

由于他们不理解 RM 或关系术语,他们将关联 Tables 称为“link”或“地图”table秒。如果它们有一个 ID 字段,它们实际上是文件。

3.2 查找 Tables

ID 字段特别是 愚蠢的事情 用于查找或参考 table。大部分都有可识别的代码,没必要一一列举里面的代码,因为代码是(应该)唯一的。

ENUM 同样愚蠢,但出于不同的原因:它将您锁定在反 SQL 方法中,这是不合规的“SQL 中的一个“特征” ".

此外,将子 table 中的代码作为 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

请注意,这是无法避免的事情:您需要查找代码的唯一性 和描述的 的唯一性。这是防止两列的 each 重复的唯一方法:

        CREATE TABLE gender (
            gender_code  CHAR(2)  NOT NULL,
            name         CHAR(30) NOT NULL

            CONSTRAINT PK 
                PRIMARY KEY ( gender_code )

            CONSTRAINT AK 
                UNIQUE ( name )
            )

3.3 完整示例

根据你问题的细节,我怀疑你有 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; 没有额外的索引;没有重复的 ;没有错误的期望;没有后续问题。

3.4 关系数据模型

这是符合定义的数据模型。

  • 作为 PDF

  • 如果您不习惯使用符号,请注意每一个小刻度、刻痕和标记,实线与虚线,方角与圆角,都表示非常具体的含义。参考IDEF1X Notation.

  • 一图胜千言;在这种情况下,标准投诉图片的价值不止于此;坏的抵不上画纸的价值。

  • 请仔细检查动词短语,它们包含一组谓词。 Predicates 的其余部分可以直接从模型中确定。如果不清楚,请询问。