【问题标题】:How can I increase and synchronize primary keys of two tables at the same time with triggers?如何使用触发器同时增加和同步两个表的主键?
【发布时间】:2021-04-03 18:39:42
【问题描述】:

我有两个独立的数据库表来存储公司员工的个人和地址信息,如下所示:

CREATE TABLE [dbo].[Person]
(
    [BusinessEntityID] [int] IDENTITY(1,1) NOT NULL,
    [NationalIDNumber] [int] NULL,
    [FirstName] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,

    CONSTRAINT [PK_Student] 
         PRIMARY KEY CLUSTERED ([BusinessEntityID] ASC)
                     WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                           IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                           ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Address]
(
    [AddressID] [int] NOT NULL,
    [AddressLine1] [varchar](150) NULL,
    [AddressLine2] [varchar](150) NULL,

    CONSTRAINT [PK_StudentAddress] 
        PRIMARY KEY CLUSTERED ([AddressID] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

当我在[dbo].[Person] 中插入一个新行(如[FirstName])时,它会自动创建一个[BusinessEntityID] 并一次递增一个。我想使用[BusinessEntityID] 值并将其插入[AddressID] 并为该员工的地址信息创建空间以便稍后输入。

可以使用触发器吗?我添加了这个触发器,但没有任何反应:

ALTER TRIGGER /*OR CREATE*/ [dbo].[auto_inc] 
ON [dbo].[Person]
AFTER INSERT
AS
BEGIN
    INSERT INTO Address(AddressID) SELECT p.BusinessEntityID FROM [Person] p
    UPDATE [Address]  SET AddressID = p.BusinessEntityID FROM [Person] p
END

【问题讨论】:

  • 首先,它必须是AFTER INSERT 触发器,并且必须在dbo.Person 表上.....其次:您没有引用@ 987654330@ 伪表,其中包含已插入的行 - 那么您希望如何获得新插入的 BusinessEntityId 值?第三:dbo.Address 上的AddressId alsoIDENTITY 列,因此您不应该只将自己的值插入其中 - 让 SQL Server 处理......
  • @marc_s 对不起,我是这些东西的新手。有一部分我不完全理解。我已经编辑了命令,将触发器移动到 Person 表,从 Address 中删除了 IDENTITY,但没有任何改变......我只是想移动相关行的 id.. 一定不难。

标签: sql sql-server database tsql triggers


【解决方案1】:

如果您想捕获插入到Person 表中的标识值 - 您需要有一个AFTER INSERT 触发器,并且您需要查看触发器内的Inserted 伪表,以找出哪些行具有被插入。这些可以是多行 - 因此您需要相应地处理。

但是您真的想通过BusinessEntityId 向新创建的Person 添加一个“空”地址吗?这会产生大量空地址 - 有什么好处?另外:按照您现在的设置方式,一个人只能拥有一个地址——这也可能不是一个好主意。

所以如果你真的想要这样做 - 你需要一个类似这样的触发器:

CREATE OR ALTER TRIGGER [dbo].[auto_inc] 
ON [dbo].[Person]
AFTER INSERT
AS
BEGIN
    INSERT INTO dbo.Address (AddressID) 
        SELECT p.BusinessEntityID 
        FROM Inserted;
END

但是,从逻辑的角度来看,我认为这都是错误的。我会像这样设置Address 表:

CREATE TABLE dbo.Address
(
    -- use an IDENTITY for the unique ID for each address
    AddressID INT IDENTITY(1,1) NOT NULL,

    -- link the address to a person - this way, one person can have *multiple* addresses
    BusinessEntityID INT NOT NULL,
    AddressLine1 VARCHAR(150) NULL,
    AddressLine2 VARCHAR(150) NULL,
    -- more colums, like "AddressType" or something....

    CONSTRAINT PK_Address
        PRIMARY KEY CLUSTERED (AddressID ASC),
    -- establish foreign key constraint to Person
    CONSTRAINT FK_Address_Person
        FOREIGN KEY (BusinessEntityId) REFERENCES dbo.Person (BusinessEntityId)
)

我会自动为您创建的每个人插入一个空地址 - 有什么用??

【讨论】:

  • 问题是,我们正在为学期项目设计一个网站,我们从数据库中获取数据并对其应用 crud 操作。 (创建、更新、删除)。我们为网站上的 Person 表输入值。但是,我们不能向地址表添加任何值,因为相同的 id 不会同步到地址部分。所以我们认为保持businessid和addresid相等同步可以解决问题。
  • @KeremYavuz 在这一点上,不可能对您对原始帖子所做的所有编辑进行有意义的讨论。但是,当您选择使用标识列作为主键时,您将放弃该值分配中的任何角色。但这与您尝试“对齐”它们相矛盾。在相关表之间“对齐” PK 值很少是一个好主意 - 这样做需要依赖表不使用标识。你有一个设计缺陷,你不能(大部分)编码。
猜你喜欢
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
  • 2013-11-25
  • 2023-01-24
  • 2021-09-23
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
相关资源
最近更新 更多