【问题标题】:How to insert value into foreign key in SQL server? (Avoid the duplicate key.)如何在 SQL Server 的外键中插入值? (避免重复键。)
【发布时间】:2017-07-04 10:58:00
【问题描述】:

我创建了两个表。它们通过主键和外键连接。当我插入新值时,它说不能在对象中插入重复的键。这是我的桌子

create table person (
sinNum int primary key not null,
gender varchar(6) not null check (gender in ('male','female')) default 'female',
age int not null check (age>=18 and age<=100),
emailAddr varchar (50) not null,
phoneNum int not null,  
)


create table employee (
empId int identity (1,1) unique,
lastName varchar (30) not null,
firstName varchar (30) not null,
sinNum int unique foreign key references person (sinNum),
departmentId int foreign key references department (departmentId), 
position varchar (20) not null check (position in ('clerk','assistant','supervisor','manager','director','president')) default'clerk',
baseSalary float not null
)

这是我的插入语句

insert into person (sinNum,gender,age,emailAddr, phoneNum) values (333, 
'female', 24, 'dds', 2121)

insert into employee(lastName,firstName, sinNum, departmentId, 
position,baseSalary) values ('Snow','John',333,20,'clerk',4000)

这里是错误信息

违反主键约束“PK__person__228E26BE3A9512B2”。 无法在对象“dbo.person”中插入重复键。重复键 值为 (333)。

谁能给我指路?非常感谢

【问题讨论】:

  • 您是否要再次向dbo.person 插入“333”?你不能这样做,因为它是主键破坏。具有主键的字段不能有冗余数据。
  • 我想怎么办?因为我需要员工和人只能通过 sinNum 匹配。
  • @Jeffery 如果 person.sisNum 需要唯一,您可以考虑使用 MERGE 来更新记录,而不是尝试插入重复记录。
  • 已经有一个sinNum 333的人,尝试查询SELECT * FROM person WHERE sinNum = 333。如果它返回一条记录,那么您就知道这是问题所在。

标签: sql sql-server


【解决方案1】:

您尚未将 sinNum 设置为身份。使其自动递增,然后如下更改您的插入查询。

insert into person (sinNum,gender,age,emailAddr, phoneNum) values ((SELECT ISNULL(MAX(sinNum)+1,0) FROM person WITH(SERIALIZABLE, UPDLOCK)), 
'female', 24, 'dds', 2121)

你也可以使用更简单的版本,但不保证并发:

insert into person (sinNum,gender,age,emailAddr, phoneNum) values (NULL, 
'female', 24, 'dds', 2121) 

【讨论】:

  • sinNum 是随机给出的。不能自动分配。
  • @Jeffery 然后将其指定为PrimaryKey 是没有意义的。删除 PrimaryKey。
【解决方案2】:

由于 sinNum 是您的主键,如果您尝试 INSERT 包含相同值的新行,它将拒绝您。

只需使用以下查询删除行,然后再次添加即可。

DELETE FROM person WHERE sinNum = 333;

您也可以更新/合并该行,或者干脆不添加它,因为您已经完成了。

【讨论】:

    【解决方案3】:

    因为 'sinum' 列是主键,所以不能明确定义。

    所以请在下面尝试一下。

    Insert into person (gender,age,emailAddr, phoneNum) values ( 'female', 24, 'dds', 2121)
    
    Declare @sinnum=IDENT_CURRENT('Person')
    
    If @@error=0
    
    Insert into employee(lastName,firstName, sinnum, departmentId, position,baseSalary) values ('Snow','John',@sinnum,20,'clerk',4000)
    

    Ident_current 将在提到的表中保存最后插入的主键值。将该值保存在临时变量中,以便在员工表中使用与 FK 相同的值。

    这里使用@@error 来确保仅在person 表中成功插入时才在employee 表中插入。

    【讨论】:

      【解决方案4】:

      这里发生的情况是您在 Person 表上的插入违反了主键约束。所以我们可以用这个异常作为解药。

      您可以使用 Try-Catch 语句,并可以在 catch 块中实现您的进一步逻辑。

      /* You an use @output parameter too */
      Declare @output bit=1
      
      BEGIN TRY
          insert into person (sinNum,gender,age,emailAddr, phoneNum) values (333, 
          'female', 24, 'dds', 2121)
      
          insert into employee(lastName,firstName, sinNum, departmentId, 
          position,baseSalary) values ('Snow','John',333,20,'clerk',4000)
      
          print 'Record inserted in both table'
      
      set @output=1
      END TRY
      
      BEGIN CATCH
       if error_message() like 'Violation of PRIMARY KEY constraint%'
          Begin
      
          /* Do whatever you like to do here */
          /* You can delete the existing record if you want */
      
           print 'Record already exists is Person table' --just the intimation
           set @output=0
      
          End
      
       else
          print 'other exception'       --just the intimation
      
      END CATCH
      

      您可以删除 catch 块中的现有记录,也可以使用@output 变量进行新事务。。希望它对你有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        • 1970-01-01
        • 2017-03-03
        • 2022-08-15
        • 2021-04-05
        相关资源
        最近更新 更多