如何更新主键?

时间:2016-04-23 05:25:29

标签: mysql primary-key mysql-workbench

我正在编写一个脚本,必须更新某些行而不更改另一个创建几个表的脚本的内容。另一个条件是你不能改变或放弃约束。

创建表脚本的内容:

CREATE TABLE TRUCK(
REGNUM VARCHAR(10) NOT NULL,
CAPACITY DECIMAL(7) NOT NULL,
WEIGHT  DECIMAL(5) NOT NULL,
STATUS  VARCHAR(10) NOT NULL,
CONSTRAINT TRUCK_PKEY PRIMARY KEY(REGNUM),
CONSTRAINT TRUCK_STATUS CHECK (STATUS IN ('AVAILABLE', 'MAINTAINED', 'USED'));

并且有一些行插入语句。

CREATE TABLE TRIP(
TNUM DECIMAL(10)  NOT NULL,
LNUM DECIMAL(8)   NOT NULL,
REGNUM VARCHAR(10) NOT NULL,
TRIP_DATE DATE NOT NULL,
CONSTRAINT TRIP_PKEY PRIMARY KEY(TNUM),
CONSTRAINT TRIP_FKEY1 FOREIGN KEY(LNUM) REFERENCES DRIVER(LNUM)
CONSTRAINT TRIP_FKEY2 FOREGIN KEY(REGNUM) REFERENCES TRUCK(REGNUM) );

也有一些行插入语句。

此脚本由讲师发出,没有错误。

现在,我试过了:

UPDATE TRIP
SET REGNUN = 'PKR856'
WHERE REGNUM = 'SST005';

UPDATE TRUCK
SET REGNUN = 'PKR856'
WHERE REGNUM = 'SST005';

这会给我一个错误“无法删除/更新父行.ingin key constriant。”。给定脚本中的所有行插入语句都具有完整信息,并且存在具有regnum = sst005的行。我试图先更新卡车,它也无法正常工作。请帮忙!

3 个答案:

答案 0 :(得分:1)

CONSTRAINT TRIP_FKEY1 FOREIGN KEY(LNUM) REFERENCES DRIVER(LNUM)

查看有关MySQL foreign key的手册:

  

RESTRICT:拒绝父表的删除或更新操作。指定RESTRICT(或NO ACTION)与省略ON DELETE或ON UPDATE子句相同。

您未设置ON DELETEON UPDATE选项,因此默认情况下它们为RESTRICT。并且当子表中的行存在时,您无法更新父表主键。

您可以像这样更改CREATE TABLE

CREATE TABLE TRIP(
  TNUM DECIMAL(10)  NOT NULL,
  LNUM DECIMAL(8)   NOT NULL,
  REGNUM VARCHAR(10) NOT NULL,
  TRIP_DATE DATE NOT NULL,
  CONSTRAINT TRIP_PKEY PRIMARY KEY(TNUM),
  CONSTRAINT TRIP_FKEY1 FOREIGN KEY(LNUM) REFERENCES DRIVER(LNUM) ON UPDATE CASCADE
  CONSTRAINT TRIP_FKEY2 FOREGIN KEY(REGNUM) REFERENCES TRUCK(REGNUM) ON UPDATE CASCADE);

和查询

UPDATE TRUCK SET REGNUN = 'PKR856' WHERE REGNUM = 'SST005';

将更改两个表中的键,truck中的主键和trip中的外键。

答案 1 :(得分:1)

快速解决方法是禁用会话的外键检查,然后重新启用它们。禁用外键检查后,MySQL将允许DML更改(INSERT / UPDATE / DELETE),否则将违反外键约束。

确保您所做的更改使数据库处于一致状态,其中没有违反约束的行。

SET FOREIGN_KEY_CHECKS = 0;

UPDATE TRIP
SET REGNUN = 'PKR856'
WHERE REGNUM = 'SST005';

UPDATE TRUCK
SET REGNUN = 'PKR856'
WHERE REGNUM = 'SST005';

SET FOREIGN_KEY_CHECKS = 1;

作为另一种选择,如果脚本没有为表指定ENGINE =,则可以在执行脚本创建表之前临时将会话的默认存储引擎更改为MyISAM。

SELECT @@session.default_storage_engine INTO @prev_default_storage_engine ;
SET default_storage_engine = MYIASM ;

-- execute table creation script 

SET default_storage_engine = @prev_default_storage_engine ;

("技巧"这里是MyISAM存储引擎不强制执行外键约束。)

答案 2 :(得分:0)

不是更新父表中的主键,而是添加复制除主键之外的所有数据的新行。然后,您可以更新子表中的外键,然后删除父表中的原始行。

INSERT INTO TRUCK (regnum, capacity, weight, status)
SELECT 'PKR856', capacity, weight, status
FROM TRUCK
WHERE regnum = 'SST005';

UPDATE TRIP
SET REGNUM = 'PKR856'
WHERE REGNUM = 'SST005';

DELETE FROM TRUCK WHERE regnum = 'SST005';