Pet*_*uza 49 sql database foreign-keys
当你研究关系理论时,外键当然是强制性的.但实际上,在我工作的每个地方,表产品和连接总是通过在查询中明确指定键来完成,而不是依赖于DBMS中的外键.
这样,您当然可以按字段连接两个表,这些字段不是外键,具有意外结果.
你为什么这么认为?DBMS是否应该强制只使用外键来创建联接和产品?
编辑:谢谢你的所有答案.现在我很清楚,FK的主要原因是参考完整性.但是如果你设计一个DB,模型中的所有关系(ERD中的IE箭头)都会成为外键,至少在理论上,无论你是否在DBMS中定义它们,它们都是语义上的FK.我无法想象需要通过不是FK的字段来连接表.有人能给出一个有意义的例子吗?
PS:我知道N:M关系变成了单独的表而不是外键,为简单起见省略了它.
Dan*_*llo 39
存在外键约束的原因是为了保证引用的行存在.
"外键标识一个表中的一列或一组列,这些列引用另一个表中的一列或一组列.引用列的一行中的值必须出现在引用表的一行中.
因此,引用表中的行不能包含引用表中不存在的值(可能为NULL除外).通过这种方式可以将信息链接在一起,这是数据库规范化的重要组成部分."(维基百科)
RE:您的问题:"我无法想象需要按非FK字段连接表格":
定义外键约束时,引用表中的列必须是引用表的主键,或者至少是候选键.
进行连接时,无需加入主键或候选键.
以下是一个可能有意义的示例:
CREATE TABLE clients (
client_id uniqueidentifier NOT NULL,
client_name nvarchar(250) NOT NULL,
client_country char(2) NOT NULL
);
CREATE TABLE suppliers (
supplier_id uniqueidentifier NOT NULL,
supplier_name nvarchar(250) NOT NULL,
supplier_country char(2) NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
然后查询如下:
SELECT
client_name, supplier_name, client_country
FROM
clients
INNER JOIN
suppliers ON (clients.client_country = suppliers.supplier_country)
ORDER BY
client_country;
Run Code Online (Sandbox Code Playgroud)
这些连接有意义的另一种情况是提供地理空间功能的数据库,如SQL Server 2008或Postgres with PostGIS.您将能够执行以下查询:
SELECT
state, electorate
FROM
electorates
INNER JOIN
postcodes on (postcodes.Location.STIntersects(electorates.Location) = 1);
Run Code Online (Sandbox Code Playgroud)
来源:ConceptDev - SQL Server 2008地理:STIntersects,STArea
您可以在" Sql 2008查询问题 - 在地理多边形中存在哪个LatLong? " 的帖子的接受答案中看到另一个类似的地理空间示例:
SELECT
G.Name, COUNT(CL.Id)
FROM
GeoShapes G
INNER JOIN
CrimeLocations CL ON G.ShapeFile.STIntersects(CL.LatLong) = 1
GROUP BY
G.Name;
Run Code Online (Sandbox Code Playgroud)
这些都是与外键和候选键无关的有效SQL连接,在实践中仍然有用.
Otá*_*cio 34
与保持数据库完整性相比,外键与连接的关系较少.证明这一点就是你可以以任何你想要的方式连接表格,即使是以一些不一定有意义的方式.
Qua*_*noi 10
我无法想象需要通过不是FK的字段来连接表.有人能给出一个有意义的例子吗?
FOREIGN KEY如果ER模型实体之间的关系反映在关系模型中两个关系之间的等值连接,则s只能用于强制引用完整性.
这并非总是如此.
这是我前一段时间写的博客文章中的一个例子:
此模型描述了商品和价格范围:

这是模型的关系实现:
CREATE TABLE Goods (ID, Name, Price)
CREATE TABLE PriceRange (Price, Bonus)
Run Code Online (Sandbox Code Playgroud)
如您所见,该PriceRange表只有一个与价格相关的属性Price,但该模型有两个属性:StartPrice和EndPrice.
这是因为关系模型允许变换集合,并且PriceRange可以使用SQL操作容易地重建实体.
Goods
ID Name Price
1 Wormy apple 0.09
2 Bangkok durian 9.99
3 Densuke watermelon 999.99
4 White truffle 99999.99
PriceRange
Price Bonus
0.01 1%
1.00 3%
100.00 10%
10000.00 30%
Run Code Online (Sandbox Code Playgroud)
我们只存储每个范围的下限.可以很容易地推断出上限.
以下是查找每种商品奖金的查询:
SELECT *
FROM Goods
JOIN PriceRange
ON PriceRange.Price =
(
SELECT MAX(Price)
FROM PriceRange
WHERE PriceRange.Price <= Goods.Price
)
Run Code Online (Sandbox Code Playgroud)
我们看到这些关系模型很好地实现了ER模型,但是在这些关系之间不能声明外键,因为用于绑定它们的操作不是等值连接.
不,执法是不必要的; 它会禁止一些有用的功能,例如可能的列重载.虽然这种用途并不理想,但它在某些现实世界中很有用.
对外键约束的适当使用就是这样; 对添加到给定列的值的约束,以确保其引用的行存在.
应该注意的是,对给定模式的显着缺乏外键约束是一种不好的"气味",并且可能表明一些严重的设计问题.
你可以加入任何表达.是否在数据库中定义外键是无关紧要的.外键约束INSERT/UPDATE/DELETE,而不是SELECT.
那么为什么很多项目都会跳过定义外键呢?有几个原因:
数据模型的设计很差,需要破坏引用(例如:多态关联,EAV).
编码员可能听说"外键很慢",所以他们放弃了.实际上,当您不能依赖外键时,为确保数据一致性而必须做的额外工作会使您的应用程序效率降低.在没有实际测量效益的情况下过早优化是一个常见问题.
约束妨碍了一些数据清理任务.有时您需要在重构数据时暂时中断引用.许多RDBMS允许禁用约束,但有时程序员决定让它们更容易被禁用.如果经常需要禁用约束,这可能表明数据库设计严重受损.
因为在实践中,光有理论是不够的。
理论不够灵活,无法考虑现实世界中必须处理的所有可能性。只有当您必须存储在数据库中的一种极其奇怪的情况(或更常见的情况,例如重载列)时,您才必须取出 FK 并在数据访问层 (DAL) 中实现它。
也许您可以开发一些可以以完全标准化的方式存档的解决方案,但在许多情况下,所需的工作和/或最终结果是不值得的。
| 归档时间: |
|
| 查看次数: |
18835 次 |
| 最近记录: |