Ahm*_*tan 6 mysql sql relational-database auto-increment
我有2个表,都有自己的自动递增ID,这当然是主键.
当我想创建第3个表来建立这两个表之间的关系时,我总是有一个错误.
第一个是关于你只能有一个自动递增的列,第二个是当我从那些2中删除auto_increment语句时发生的,因此sql不允许我将它们作为外键,因为类型匹配失败.
有没有办法可以创建关系表而不会丢失自动增量功能?
另一种可能的(但不是优选的)解决方案可能是第一个表中有另一个主键,当然是用户的用户名,而不是自动增量语句.这是不可避免的吗?
提前致谢.
Per*_*DBA 15
你误解了一些基本概念,并且由此产生了困难.我们必须首先解决这些概念,而不是你所认识到的问题,因此,你的问题就会消失.
自动递增的ID,当然是主键.
不,他们不是.这是一种常见的误解.并且保证问题随之而来.
一个ID字段不能以英文或技术或关系感官主键.
当然,在SQL中,您可以将任何字段声明为a PRIMARY KEY,但这并不会将其神奇地转换为英语,技术或关系意义上的主键.你可以将奇瓦瓦命名为"Rottweiller",但这并没有将它变成罗威威尔,它仍然是奇瓦瓦.像任何语言一样,SQL只是执行你给它的命令,它不能理解PRIMARY KEY为关系,它只是在列(或字段)上敲击一个唯一索引.
问题是,既然你已经宣布的ID是一个PRIMARY KEY,你认为它作为一个主键,你可以期望它有一些主键的特质.除了ID 值的唯一性之外,它没有任何好处.它没有主键的任何特性,也没有任何关系密钥.它不是英语,技术或关系意义上的关键.通过声明非密钥成为密钥,您只会混淆自己,并且只有当用户抱怨表中的重复时才会发现存在严重错误.
字段PRIMARY KEY上的A ID不提供行唯一性.因此,它不是包含行的Relational表,如果不是,则它是包含记录的文件.它没有任何完整性或功能(在此阶段,您将只知道连接功率)或速度,即Relational数据库中的表具有.
执行此代码(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
Run Code Online (Sandbox Code Playgroud)
请注意,您有重复的行.关系表需要具有唯一的行.进一步证明您没有关系表或任何一个关系表.
请注意,在你的报告中,唯一独一无二的是ID字段,没有用户关心,没有用户看到,因为它不是数据,这是一些额外的废话,一些非常愚蠢的"老师"告诉你放入每个文件.您具有记录唯一性,但不具有行唯一性.
就数据而言(实际数据减去无关的附加物),数据name_last并且name_first可以在没有该ID字段的情况下存在.一个人的名字和姓氏没有在他们的额头上盖上身份证.
您正在使用的第二件事就是AUTOINCREMENT. 如果您正在实现一个没有关系功能的记录文件系统,当然,这很有用,您不必在插入记录时对增量进行编码.但是,如果您正在实现一个关系数据库,它根本没有用处,因为您永远不会使用它.SQL中有许多功能,大多数人从不使用.
那么如何将充满重复行的dumb_file升级,提升到Relational表,以获得Relational表的一些特性和优点?这有三个步骤.
你需要了解Keys
EF Cood博士在他的RM中宣称:
密钥由数据组成
和
表中的行必须是唯一的
您的"密钥"不是由数据组成的.这是一些额外的非数据寄生虫,由您感染"老师"的疾病引起.认识到这一点,让自己拥有上帝给你的全部心智能力(注意我不要求你以孤立或零碎或抽象的方式思考,数据库中的所有元素必须相互整合).从数据中组成一个真正的密钥,并且只从数据中组成.在这种情况下,只有一个可能的密钥:(name_last, name_first).
试试这段代码,声明对数据的唯一约束:
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
Run Code Online (Sandbox Code Playgroud)
现在我们有行唯一性.这是大多数人发生的序列:他们创建一个允许欺骗的文件; 他们不知道为什么欺骗会出现在下拉中; 用户尖叫; 他们调整文件并添加索引以防止欺骗; 他们进入下一个bug修复.(他们可能正确或不正确,这是一个不同的故事.)
第二级.思考那些超越修复的人 - 它.既然我们现在有行唯一性,天堂的名字就是这个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
Run Code Online (Sandbox Code Playgroud)
工作正常,按预期工作,没有无关的字段和索引.
请记住这一点,并且每次都做得对.
在这些结束时间,按照建议,我们将拥有其中许多.请注意,ID根据本文中的详细证据,传播列的"教师" 根本不理解关系模型或关系数据库.特别是那些写书的人.
如证据所示,他们陷入了1970年以前的ISAM技术.这就是他们所理解的一切,而这就是他们所能教导的一切.它们使用SQL数据库容器,以便于访问,恢复,备份等,但内容是纯记录文件系统,没有关系完整性,功能或速度.AFAIC,这是一个严重的欺诈行为.
ID当然,除了字段之外,还有几个关键的关系或非关键概念,它们合在一起,使我形成如此严肃的结论.其他项目超出了本文的范围.
一对特殊的白痴目前正在对First Normal Form进行攻击.他们属于庇护所.
现在问你的其余部分.
有没有办法可以创建关系表而不会丢失自动增量功能?
这是一个自相矛盾的句子.我相信你会从我的解释明白,关系表也没有必要对AUTOINCREMENT"特色"; 如果文件有AUTOINCREMENT,则它不是Relational表.
AUTOINCREMENT仅适用于一件事:当且仅当您想要在SQL数据库容器中创建Excel电子表格时,请填充名称A, B,和C,顶部的字段,并在左侧记录数字.在数据库术语,即结果是SELECT,数据的平面视图,即不将源数据的,这是组织的(归一化).
另一种可能的(但不是优选的)解决方案可能是第一个表中有另一个主键,当然是用户的用户名,而不是自动增量语句.这是不可避免的吗?
在技术工作中,我们不关心偏好,因为这是主观的,并且它一直在变化.我们关心技术的正确性,因为这是客观的,并且不会改变.
是的,这是不可避免的.因为这只是时间问题; 错误数量; 数量"不能dos"; 用户尖叫的数量,直到你面对事实,克服你的虚假声明,并意识到:
确保用户行唯一的唯一方法是user_names是唯一的,就是声明UNIQUE对它的约束
并摆脱user_id或id在用户文件中
促进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
Run Code Online (Sandbox Code Playgroud)
代替:
SELECT ...
FROM child_table
WHERE gender_id = 6 -- meaningless to the maintainer
Run Code Online (Sandbox Code Playgroud)
或者更糟:
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
Run Code Online (Sandbox Code Playgroud)
请注意,这是一件谁都无法回避:你需要查找代码的唯一性和独特性的描述.这是防止两列中每一列重复的唯一方法:
CREATE TABLE gender (
gender_code CHAR(2) NOT NULL,
name CHAR(30) NOT NULL
CONSTRAINT PK
PRIMARY KEY ( gender_code )
CONSTRAINT AK
UNIQUE ( name )
)
Run Code Online (Sandbox Code Playgroud)
根据您问题中的详细信息,我怀疑您有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 )
)
Run Code Online (Sandbox Code Playgroud)
在那里,PRIMARY KEY声明是诚实的,它是一个主键; 没有ID;没有AUTOINCREMENT;没有多余的指标; 没有重复的行 ; 没有错误的期望; 没有相应的问题.
以下是与定义一起使用的数据模型.
如果您不习惯乐谱,请注意每个小刻度,刻痕和标记,实线与虚线,方形与圆角,意味着非常具体的东西.请参阅IDEF1X表示法.
一张图片胜过千言万语; 在这种情况下,标准投诉图片的价值不止于此; 一个坏的不值得它所用的论文.
请仔细检查动词短语,它们包含一组谓词.其余的Predicates可以直接从模型中确定.如果不清楚,请询问.
| 归档时间: |
|
| 查看次数: |
2765 次 |
| 最近记录: |