引用自身的外键列的效果(或目的)是什么?

时间:2012-10-18 21:44:41

标签: sql sql-server-2008-r2 sybase

在数据库迁移期间,我遇到了以下形式的数据库表约束:

ALTER TABLE [dbo].[myTable]
ADD CONSTRAINT [someName] FOREIGN KEY ([id]) REFERENCES [dbo].[myTable] ([id])
ON DELETE NO ACTION
ON UPDATE NO ACTION

为什么会这样做?这最初是在Sybase数据库上完成的,我们正在转换为SQL Server 2008 R2。

UPDATE :是的,外键约束是引用同一个表和相同字段的字段。

我在源Sybase数据库上运行了这个查询,发现定义了42个疯狂的键,所以它看起来不像是错字。

SELECT sr.constrid as [Constraint ID],
       so.name as [Table],
       sc.name as [Column]
  FROM sysreferences sr
       INNER JOIN sysobjects so ON (so.id = sr.tableid)
       INNER JOIN syscolumns sc ON (sc.id = sr.tableid AND sc.colid = sr.fokey1)
 WHERE sr.tableid = sr.reftabid
   AND sr.fokey1 = sr.refkey1
   AND sr.fokey2 = 0
   AND sr.refkey2 = 0

4 个答案:

答案 0 :(得分:2)

我相信,只要您对同一个表使用外键,层次结构就是您在书中找到的标准示例,例如:

create table Employees (
 EmployeeID int identity primary key,
 EmployeeName varchar(50),
 ManagerID int
 Foreign key (managerID) references Employees(EmployeeID)
)

您发布的内容在同一个表中看起来像是这种层次结构关系的错误应用。我不完全确定你为什么要这样做。

希望这有帮助=)

答案 1 :(得分:1)

惊喜!这完全有效:

create table crazy (
    ID int primary key references crazy (ID) -- This runs
);
insert into crazy select 1;  -- So does this
select * from crazy; -- Returns 1
truncate table crazy; -- Works just fine

我只能认为这是一个错误(错字?在图表中将列拖到自身上?)或用于欺骗另一个系统(ORM?)成某种特定行为。我将非常好奇,看看是否有人提出合法的理由。

更新:正如@ 8kb巧妙建议的那样,这可能是一种阻止截断的尝试,但我们可以从我的例子中看到即使截断也能正常工作。

答案 2 :(得分:0)

我猜这是数据库模型中的一个错误。

真的很奇怪。我无法想象这个结构的用途是什么。

如何插入数据的唯一方法是不检查参考完整性。它意味着具有明确禁用的引用或某种批量插入等。

答案 3 :(得分:0)

引用自身的外键列的效果似乎无效。关于为什么数据库引擎会让你做这样无用的事情,这仍然是一个很突出的问题。

但是,我认为有人会像这样构建一个外键的原因是懒惰/粗心。我发现在SQL Server Management Studio中,如果使用GUI构建外键(而不是在T-SQL中编写),SSMS的初始行为就是创建外键,就像在这个问题中一样:

  1. 在“对象资源管理器”窗格中展开数据库的任何表。我们将此表称为TableA。
  2. 单击TableA节点下的Keys并选择New Foreign Key ...这将打开Modify table窗格和Foreign Key Relationships对话框。
  3. 不做任何改动,只需单击“外键关系”对话框上的“关闭”按钮。 “糟糕,我并不是故意尝试添加外键。”
  4. 关闭对话框仍然会生成名为FK_TableA_TableA的外键,并选择主键列作为基本列和参考列。
  5. 如果“修改”表格窗格仍处于打开状态(关闭“外键关系”对话框后仍然如此),请将其关闭。它有变化(你刚刚制作的新外键)。保存这些更改。
  6. 现在,TableA的数据库中存在一个新的外键,主键列引用自身。