使用“继承”在数据库表中插入记录

时间:2011-07-15 22:54:11

标签: sql-server database-design

我有一个表,其主键也是另一个表的主键的外键(即在数据库中模拟的“继承”)。

/****** Object:  Table [dbo].[BaseClass]    Script Date: 07/15/2011 18:17:27 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[BaseClass](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Title] [nvarchar](50) NOT NULL,
    [Description] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_BaseClass] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

USE [TestConcepts]
GO

/****** Object:  Table [dbo].[DerivedTable]    Script Date: 07/15/2011 18:17:49 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[DerivedTable](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [SpecialProperty] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_DerivedTable] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[DerivedTable]  WITH CHECK ADD  CONSTRAINT [FK_DerivedTable_BaseClass] FOREIGN KEY([ID])
REFERENCES [dbo].[BaseClass] ([ID])
GO

ALTER TABLE [dbo].[DerivedTable] CHECK CONSTRAINT [FK_DerivedTable_BaseClass]
GO

在这种情况下插入记录的正确方法是什么?显然插入不会返回插入行的PK(加上子表的PK也是标识符)。

3 个答案:

答案 0 :(得分:4)

以下是此模式的 few examples

子类型表应具有自动递增ID,ID与超类型表中的ID匹配。

基本技术(使用您的示例)看起来像

DECLARE @MY_ID integer;
INSERT INTO BaseTable(Title, Description)
    VALUES ('title_here', 'blah, blah');
SELECT @MY_ID = SCOPE_IDENTITY();

INSERT INTO DerivedTable(ID, SpecialProperty)
    VALUES (@MY_ID, newid()); -- the SpecialProperty is uniqueidentifier

一种方法是创建一个视图,一个用于每个子类型表,或者只有一个用于所有子类型表。然后在视图上创建INSTEAD OF INSERT TRIGGER并使用触发器内的技术。

您也可以找到 this technique 来捕获多个有用的插入ID。

答案 1 :(得分:0)

  1. 没有人称之为“继承”。那不是它的本质。这是一种关系,即RDBMS中的R.

  2. INSERT do 告诉您刚刚插入的行的PK。在SQL Server上查看@@ SCOPE_IDENTITY。

答案 2 :(得分:0)

DERIVEDCLASS表可能具有自动递增(标识)PK但如果是这样,则必须有另一列作为外键引用返回BASETABLE:

          BASETABLE
          id int pk autoincrement
          baseattribute1
          baseattribute2
          etc etc


           DERIVEDTABLE
           id  int pk autoincrement
           **baseid**  foreign key references BASETABLE(id)
           extendedattribute1
           extendedattribute2

这将允许每个基本实体的多个派生。如果需要,可以在DERIVEDTABLE.baseid上放置一个唯一索引或将baseid设为PK,这样可以防止这种情况发生。

以下将实例化基类的成员及其派生实例和/或扩展属性(如果有的话)将取决于baseid在DerivedTable中是否具有唯一约束;如果后者可能是与BaseTable一对一关系的PK,而不是多对一]:

          select * from BASETABLE
          LEFT JOIN DERIVEDTABLE
          on BASETABLE.id = DERIVEDTABLE.baseid

未扩展的基类实例在extendedattribute列中将为NULL。

要仅查找已扩展的实体,请使用内部联接:

         select * from DERIVEDTABLE
         inner join BASETABLE
         on DERIVEDTABLE.baseid = BASETABLE.id