我刚开始学习SQL(使用SQLite),我正在试图找出应该使用外键的时间。它向我解释的方式是,任何时候重复数据出现都应该使用外键,只需保存ID以节省空间。我正在制作的数据库中有几千条记录,列出了类别和县(每列可能有几十个独特的记录)。因此,我可以为具有县名和主键ID的县创建一个单独的表,并对类别执行相同的操作。我毫不怀疑它会使数据库缩小约5%。但这是唯一的好处吗?似乎它正在使其他一切变得更加复杂。添加不需要的县和类别的ID。在phpLiteAdmin中查看表时,它只显示一个数字而不是类别/县名,这使得可视化变得更加困难。在这种情况下使用外键和制作单独的表有什么好处?或者我应该不这样做并坚持在一个表中的所有数据(重复和所有)?此外,将县/类别表只有一列没有数字主键是否有意义,因为它们都是独一无二的?这至少会在phpLiteAdmin中显示全名。提前谢谢!
答案 0 :(得分:3)
如果您使用外键。它也被称为参照完整性。
假设您有两个表,第一个表是account_user,第二个是account_user_detail。
所以account_user表将具有account_id的account_number的主键。和account_user_detail表将具有帐户持有人地址详细信息。
因此,如果您同时关联两个表,则account_number或account_id将相同。
所以在第二个表中使用主键的值我们定义外键。
外键标识第二表中account_number的值是第一个表中具有相同帐号的Xyz先生的引用。
因此,外键用于连接两个表,这两个表与两个表共用,并共享相同的唯一值。
答案 1 :(得分:0)
您可以查看this:
SQL外键约束用于强制执行“存在”关系 表之间。
修改: - 强>
存在外键约束是为了保证引用的行存在。
wiki也说: -
数据库设计的一个重要部分是确保这一点 现实世界实体之间的关系反映在 数据库通过引用,使用外键从一个表引用到 另一个。[9]数据库设计的另一个重要部分是数据库 规范化,其中表被拆分并且外键生成 它们有可能被重建。
同时检查此线程。
答案 2 :(得分:0)
如果您的国家/地区名称是“美国”,则为24字节。如果使用foriegn密钥,则只需2-4个字节。这是一个巨大的差异。
当您搜索国家/地区名称时,它将非常快,因为您只需匹配一个数字而不是整个字符串。
此外,如果您在country_id字段上使用索引,则会更小。
我能理解你指出增加的复杂性。在你的情况下,你可以逃避不使用外键,但你不应该。你最终会需要它们,以便更好地准备和体验这个主题。
答案 3 :(得分:0)
但这是唯一的好处吗?
没有
外键在逻辑上类似于大多数编程语言中的指针或引用。想象一下,尝试通过复制数据来制作一些数据结构,而不能引用任何东西。没有外键的数据库同样存在问题。
如果没有参考内容的能力,您必须确保所有副本都保持最新状态。如果有一个错误导致一个副本被更新而另一个副本没有被更新,这将有效地损坏数据 - 您将不再知道哪个副本是正确的。
避免冗余主要不是空间,而是数据完整性。数据库规范化的整个目的(没有外键就无法完成)是避免冗余,从而保护数据的完整性。
在您的特定情况下......
如果任一答案为“是”,则应将类别放入单独的查找表中。此查找表是否应使用自然(名称)或代理(ID)密钥是一个不同的问题。列出了一些优点和缺点here。
答案 4 :(得分:0)
外键约束用于限制列或列集中允许存在的值。例如,结婚:
CREATE TABLE person
(person_id INTEGER NOT NULL PRIMARY KEY
, name varchar NOT NULL
);
CREATE TABLE marriage
( person1 INTEGER NOT NULL PRIMARY KEY
, person2 INTEGER NOT NULL UNIQUE
, comment varchar
, CONSTRAINT marriage_1 FOREIGN KEY (person1) REFERENCES person(person_id)
, CONSTRAINT marriage_2 FOREIGN KEY (person2) REFERENCES person(person_id)
, CONSTRAINT order_in_court CHECK (person1 < person2)
);
-- add some data ...
INSERT INTO person(person_id,name) values (1,'Bob'),(2,'Alice'),(3,'Charles');
INSERT INTO marriage(person1,person2, comment) VALUES(1,2, 'Crypto marriage!') ; -- Ok
INSERT INTO marriage(person1,person2, comment) VALUES(2,1, 'Not twice!' ) ; -- Should fail
INSERT INTO marriage(person1,person2, comment) VALUES(3,3, 'No you dont...' ) ; -- Should fail
INSERT INTO marriage(person1,person2, comment) VALUES(2,3, 'OMG she did it again.' ) ; -- Should fail (does not)
INSERT INTO marriage(person1,person2, comment) VALUES(3,4, 'Non existant persons are not allowed to marry !' ) ; -- Should fail
SELECT p1.name, p2.name, m.comment
FROM marriage m
JOIN person p1 ON m.person1 = p1.person_id
JOIN person p2 ON m.person2 = p2.person_id
;
以上DDL试图模拟婚姻(并且部分失败)要建模的约束是:
输出:
INSERT 0 3
INSERT 0 1
ERROR: new row for relation "marriage" violates check constraint "order_in_court"
ERROR: new row for relation "marriage" violates check constraint "order_in_court"
INSERT 0 1
ERROR: insert or update on table "marriage" violates foreign key constraint "marriage_2"
DETAIL: Key (person2)=(4) is not present in table "person".
name | name | comment
-------+---------+-----------------------
Bob | Alice | Crypto marriage!
Alice | Charles | OMG she did it again.
(2 rows)