为什么外键在理论上比在实践中更多?

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连接,在实践中仍然有用.

  • @Petruza:即使`client_country`是外键(到countries表),它肯定不是`supplier_country`的外键. (5认同)

Otá*_*cio 34

与保持数据库完整性相比,外键与连接的关系较少.证明这一点就是你可以以任何你想要的方式连接表格,即使是以一些不一定有意义的方式.

  • 你是说我不应该试着`选择*来自书内的人加入书.ISBN = person.Phone`? (6认同)
  • @Petruza,外键不应该是良好编码实践的替代品(例如代码审查),DBMS软件不应该限制SQL语言的表达能力......否则我们最终会达到SQL Server的地步有可怕的回形针:"看起来你正在写一个查询......"! (4认同)
  • 如果这就是你所需要的,那么一定要做到.如果您的业务需求决定,您甚至可以在book.ISBN和person.Phone之间建立FK. (2认同)
  • `select*from book as b inner join disc as d on b.num_sold = d.num_sold` - join*sans*foreign keys. (2认同)

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,但该模型有两个属性:StartPriceEndPrice.

这是因为关系模型允许变换集合,并且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模型,但是在这些关系之间不能声明外键,因为用于绑定它们的操作不是等值连接.


Pau*_*ier 8

不,执法是不必要的; 它会禁止一些有用的功能,例如可能的列重载.虽然这种用途并不理想,但它在某些现实世界中很有用.

对外键约束的适当使用就是这样; 对添加到给定列的值的约束,以确保其引用的行存在.

应该注意的是,对给定模式的显着缺乏外键约束是一种不好的"气味",并且可能表明一些严重的设计问题.


Bil*_*win 6

你可以加入任何表达.是否在数据库中定义外键是无关紧要的.外键约束INSERT/UPDATE/DELETE,而不是SELECT.

那么为什么很多项目都会跳过定义外键呢?有几个原因:

  • 数据模型的设计很差,需要破坏引用(例如:多态关联,EAV).

  • 编码员可能听说"外键很慢",所以他们放弃了.实际上,当您不能依赖外键时,为确保数据一致性而必须做的额外工作会使您的应用程序效率降低.在没有实际测量效益的情况下过早优化是一个常见问题.

  • 约束妨碍了一些数据清理任务.有时您需要在重构数据时暂时中断引用.许多RDBMS允许禁用约束,但有时程序员决定它们更容易被禁用.如果经常需要禁用约束,这可能表明数据库设计严重受损.


j.a*_*van 5

因为在实践中,光有理论是不够的。

理论不够灵活,无法考虑现实世界中必须处理的所有可能性。只有当您必须存储在数据库中的一种极其奇怪的情况(或更常见的情况,例如重载列)时,您才必须取出 FK 并在数据访问层 (DAL) 中实现它。

也许您可以开发一些可以以完全标准化的方式存档的解决方案,但在许多情况下,所需的工作和/或最终结果是不值得的。