SQL:使用2个不同的auto_increment创build一个关系表

我有2个表,都有自己的自动递增的ID,这当然是主键。

当我想创build第三个表来build立这两个表之间的关系时,我总是有一个错误。

首先是你可以只有一个自动递增的列,第二个是我从这两个删除auto_increment语句时发生的,所以sql不允许我把它们作为外键,因为types匹配失败。

有没有办法可以创build一个关系表,而不会丢失自动递增function?

另一个可能的(但不是优先的)解决scheme可能是第一个表中有另一个主键,当然是用户的用户名,而不是自动增量语句。 这是不可避免的吗?

提前致谢。

概念

你误解了一些基本的概念,由此产生了困难。 我们必须首先解决这些概念,而不是像你所感知的那样问题,因此,你的问题就会消失。

自动递增的ID,这当然是主键。

不,他们不是。 这是一个常见的误解。 问题将得到保证。

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

  • 当然,在SQL中,可以将任何字段声明为PRIMARY KEY ,但这不会将其转换为英文,技术或关系意义上的主键。 你可以命名吉娃娃“Rottweiller”,但这并不会变成Rottweiller,它仍然是一个吉娃娃。 像任何语言一样,SQL只是执行你给它的命令,它并不理解PRIMARY KEY来表示关系,它只是在列(或字段)上打一个唯一的索引。

  • 问题是,既然你已经声明ID是一个PRIMARY KEY ,你可以它看作一个主键,并且你可能期望它具有一些主键的特性。 除了ID 的唯一性,它没有任何好处。 它没有一个主键的特性,也没有任何关系键。 这不是英语,技术或关系意义上的关键。 通过声明一个非键是一个键,你只会迷惑自己,你会发现,只有当用户抱怨表中有重复时,才会有一些错误。

关系表必须具有唯一性

ID字段上的PRIMARY KEY不提供唯一性。 因此,它不是一个包含行的关系表,如果不是,那么它就是一个包含logging的文件。 它没有任何完整性或权力(在这个阶段你只会意识到join的力量),或者说关系数据库中的表具有的速度。

执行此代码 (MS SQL 2008)并自行certificate。 请不要简单阅读本文并理解它,然后继续阅读本答复的其余部分, 在进一步阅读之前必须执行此代码 。 它具有治疗价值。

  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 

注意你有重复的 。 关系表需要有唯一的 。 进一步certificate你没有关系表,或者没有关系表的任何一个质量。

注意,在你的报告中唯一唯一的是ID字段,没有用户关心,没有用户看到,因为它不是数据,这是一些非常愚蠢的“老师”告诉你放在一些额外的废话每个文件。 你有logging唯一性,但不是唯一性。

根据数据(真实数据减去无关的加法),数据name_lastname_first可以不存在ID字段。 一个人的名字和姓氏的前额上没有标识。

你使用的第二件事让你感到困惑的是AUTOINCREMENT. 如果您正在实施不具有关系function的logging归档系统,那么确实有帮助,插入logging时不必编写增量。 但是如果你正在实现一个关系型数据库,它根本没有任何用处,因为你永远不会使用它。 SQL中有许多function,大多数人从不使用。

纠正措施

那么,为了获得关系表的一些品质和优势,你如何将那些充满重复行的dumb_file升级,提升到关系表? 这有三个步骤。

  1. 你需要了解钥匙

    • 而且由于我们已经从20世纪70年代的ISAM文件发展到关系模型 ,所以您需要了解关系密钥 。 也就是说,如果您希望获得关系数据库的好处(完整性,function,速度)。

    EF Coo​​d博士在他的RM中宣称:

    一个关键是由数据组成的

    表中的行必须是唯一的

    你的“钥匙”不是由数据组成的。 这是一些额外的非数据寄生虫,是由于您感染了您的“老师”的疾病而引起的。 认识到这一点,并让自己有充分的心智能力,上帝给你(注意,我不要求你孤立或分割或抽象的思想,数据库中的所有元素必须相互融合)。 从数据中构成一个真正的密钥并且只从数据中获得。 在这种情况下,只有一个可能的键: (name_last, name_first).

  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 

    现在我们有行独特性 。 这是大多数人发生的顺序:他们创build一个允许模糊的文件; 他们不知道为什么愚蠢是出现在下降; 用户尖叫; 他们调整文件,并添加一个索引,以防止愚蠢的; 他们去下一个错误修复。 (他们可能正确或不正确,这是一个不同的故事。)

  3. 第二级。 思考那些超越固定思维的人。 既然我们现在有排队的唯一性,那么天堂的名字就是ID字段的目的,我们为什么还要有呢? 哦,因为吉娃娃叫Rotty,我们不敢碰它。

    这是一个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 

    工作得很好,按预期工作,没有多余的字段和索引。

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

假教师

在这些最后时刻,我们会有很多这样的build议。 注意,根据本文的详细证据,传播ID列的“教师”根本不理解关系模型或关系数据库。 尤其是写书的人。

事实certificate,他们被困在1970年前的ISAM技术中。 这就是他们所能理解的,这就是他们所能教的。 他们使用SQL数据库容器,以方便访问,恢复,备份等,但内容是纯粹的logging归档系统,没有关系完整性,功耗或速度。 AFAIC,这是一个严重的欺诈行为。

当然,除了ID字段之外,还有几个关键或不关联的概念,这些概念结合在一起,使我形成了这样一个严重的结论。 这些其他项目超出了这篇文章的范围。

一个特殊的白痴现在正在对第一范式进行攻击。 他们属于庇护所。

回答

现在问题的其余部分。

有没有办法可以创build一个关系表,而不会丢失自动递增function?

这是一个自相矛盾的句子。 我相信你会从我的解释中理解,关系表不需要 AUTOINCREMENT “function”。 如果该文件具有AUTOINCREMENT ,则不是关系表。

AUTOINCREMENT仅适用于一件事情:如果且仅当您希望在SQL数据库容器中创buildExcel电子表格,则在顶部填充名为A, B,C,字段,并在左侧logging数字。 从数据库的angular度来看,这是数据平面化的结果,而不是数据的来源 ,这是组织的(规范化)。

另一个可能的(但不是优先的)解决scheme可能是第一个表中有另一个主键,当然是用户的用户名,而不是自动增量语句。 这是不可避免的吗?

在技​​术工作上,我们并不在乎喜好,因为这是主观的,而且总是在变化。 我们关心技术的正确性,因为这是客观的,而且不会改变。

是的,这是不可避免的。 因为这只是一个时间问题; 错误的数量; “不能做”的号码; 用户尖叫的次数,直到你面对事实,克服你的虚假陈述,并认识到:

  • 要确保用户是唯一的,唯一的方法是声明一个UNIQUE约束

  • 并删除用户文件中的user_idid

  • user_name升级为PRIMARY KEY

是的,因为你的第三张桌子的整个问题,不巧合,然后被淘汰。

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

我正在向你提出警告,因为那些向你教授实现ID字段错误的“老师”教导了在关联表中实现ID字段的错误,正如普通表一样,它是多余的,不起任何作用,介绍重复,造成混乱。 这是多余的,因为提供的两把钥匙已经在那里,把我们盯在脸上。

由于他们不了解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 

请注意,这是不能避免的:您需要查找代码的唯一性和描述的唯一性。 这是防止两列中的每一个重复的唯一方法:

  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定义问题,所以我会给你需要的整个解决scheme作为一个例子(因为你没有给出文件定义):

  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; 没有额外的指标; 没有重复的 ; 没有错误的期望; 没有相应的问题。

数据模型

这里是数据模型去定义。

  • 示例用户体育数据模型

  • 如果你不习惯这个符号,请注意,每一个小刻度,刻度和标记,实线与虚线,正方形与圆angular,都是非常具体的。 请参阅IDEF1X表示法

  • 一张图片胜过千言万语; 在这种情况下,一个标准投诉的图片比这更值得一提; 坏的一个是不值得它所绘制的文件。

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