更新主键会导致外表

时间:2015-12-05 19:21:35

标签: mysql sql

我有以下SQL Fiddle描述的两个表格。我的应用程序需要在tblA中在两个已存在的记录之间插入新记录。例如,如果tblA有6条AID范围为0到5的记录,并且我想插入一条AID为4的新记录,我会增加元组4的AID和元组5一个然后插入新记录。因此,我使用以下预准备语句将AIDtblA的元组的列tblB的值(通过级联)递增一:

update tblA set AID = (AID + 1) where AID >= ? order by AID desc;

在我的测试安装上,上述声明效果很好。但是,在我们的生产系统中,我们在某些情况下会收到以下错误消息:

Foreign key constraint for table 'tblA', record '4' would lead to a duplicate entry in table 'tblB'

现在,我不清楚究竟是什么导致问题以及如何解决问题。

我感谢任何提示。提前谢谢!

2 个答案:

答案 0 :(得分:1)

关于tblB

这个

create table if not exists tblB(
  BID integer not null, 
  AID integer not null, 
  constraint fkB_A foreign key(AID) references tblA(AID), 
  primary key(AID, BID)
);

应该是

create table if not exists tblB(
  BID integer not null, 
  AID integer not null, 
  constraint fkB_A foreign key(AID) references tblA(AID)
    on update cascade, 
  -- ^^^^^^^^^^^^^^^^
  primary key(AID, BID)
);

数据和SQL数据库的关系模型中的代理ID号是没有意义的。除非你知道的不仅仅是你的问题,否则AID和BID毫无意义。在设计合理的数据库中,根本不需要根据其代理ID号在两行之间插入行

如果您的实际需求只是在“2015-12-01 23:07:00”和“2015-12-04 14:58:00”之间插入时间戳,则不需要ID号4要做到这一点。

-- Use single quotes around timestamps.
insert into tblA values (-42, '2015-12-03 00:00:00');
select * from tblA order by RecordDate;
AID       RecordDate
--
  0       2015-11-07 16:55:00
  1       2015-11-08 22:16:00
  2       2015-11-10 14:26:00
  3       2015-12-01 23:07:00
-42       2015-12-03 00:00:00
  5       2015-12-04 14:58:00
  6       2015-12-13 10:07:00

关于tblA

create table if not exists tblA(
  AID integer not null, 
  RecordDate varchar(25), 
  constraint pkA primary key(AID)
);

应该是

create table if not exists tblA(
  AID integer not null, 
  RecordDate varchar(25) not null, 
  --                     ^^^^^^^^
  constraint pkA primary key(AID)
);

如果没有not null,您可以插入这样的数据。

AID  RecordDate
--
17   Null
18   Null
19   Null

由于代理ID号码毫无意义,因此这些行基本上都是相同的,同样没用。

关于更新声明

update tblA 
set AID = (AID + 1) 
where AID >= 4 
order by AID desc;

标准SQL在update语句中不允许order by处于此位置。 MySQL documents this

  

如果指定了ORDER BY子句,则按顺序更新行   指定的。

关系模型和SQL是面向集合的。更新应该“一下子”发生。恕我直言,你最好学习标准SQL并使用更好地支持标准SQL的dbms。 (PostgreSQL让人想起。)但是将on update cascade添加到tblB(上面)将使你的update语句在MySQL中成功。

update tblA 
set AID = (AID + 1) 
where AID >= 4 order by AID desc;

答案 1 :(得分:0)

添加on update cascade可能会解决您的问题

create table if not exists tblB(
       BID integer not null, 
       AID integer not null, 
       constraint fkB_A foreign key(AID) 
             references tblA(AID)
             on update cascade, 
             primary key(AID, BID));