我的问题是,例如,当我创建一个表时:table1以下几列:
table1
customerId
CustomerName
Address
State
哪里customerId是PRIMARY KEY用AUTO_INCREMENT。
PRIMARY KEY
AUTO_INCREMENT
然后table2以列为例:
table2
purchaseId
product
cost
凡PRIMARY KEY是purchaseId与外键是customerId从table1。
应该是说我已经建立的关系table1和table2使用customerId。
这两个表最初都是空的,因此我编写了以下SQL命令:
INSERT INTO table1 (CustomerName,Address,State) VALUES('value1','value2','value3')
这很好用,但是当我尝试插入子表(table2)时,它告诉我:
错误外键约束
所以基本上我想要做的是插入到父表,然后到子表,以便customerId显示出来的table2(子表)的外键,相当于用customerId在table1(父表)。
我必须先创建两个表,而无需使用外键,然后再尝试建立关系。一直在说,只要关系存在就存在约束。
table2外键约束意味着任何table2客户ID值都必须在表1中显示为客户ID。之所以出现错误,是因为您正在将未在table1中出现的customerID插入到table2中。
由于DBMS通过自动递增生成table1客户ID,所以如果您插入一行,则必须获取该值,以便使用该customerID将一行插入table2。
我猜您说“我已经在table1和table2之间建立了关系”的意思是“我声明了外键约束”。我猜您认为这意味着“插入表1后,DBMS将在插入表2时将自动生成的键值用作外键值”。但这并不意味着那样。你必须自己做。外键约束仅意味着DBMS检查每个table2 customerId值是否都显示为table1 customerId值。
当您插入具有外键的表时,您可以并且必须使用任何先前插入的键值作为相应值。
要获取由DBMS生成的自动递增的键值,请使用LAST_INSERT_ID():
INSERT INTO table1 (CustomerName,Address,State) VALUES('value1','value2','value3'); INSERT INTO table2 (customerId,product,cost) VALUES(LAST_INSERT_ID(),'valueA','valueB');
这就是它的目的。但是,如果不使用它,就会出现问题。
首先,如果您不在序列化事务中,则必须使用LAST_INSERT_ID()。因为在table1插入之后但在table2插入之前,其他人可能已经添加了行和/或删除了行(包括新行)和/或更改了行(包括新行)。因此,在table1插入后获得您知道已添加的某些customerId值之后,就不能依赖于查询table1。
其次,假设您正在进行序列化事务,并且不使用LAST_INSERT_ID()。
如果(CustomerName,Address,State) 也是 table1 的超键 ,即它的值是唯一的,即在其所有或某些列上声明了SQL UNIQUE / KEY / PK,那么您可以使用它来查询关联的新customerId :
set @customerId = ( SELECT customerId FROM table1 WHERE CustomerName = 'value1' AND Address = 'value2' AND State = 'value3'); INSERT INTO table2 (customerId,product,cost) VALUES(@customerId,'valueA','valueB');
但是,如果(CustomerName,Address,State) 不是 table1 的超键 ,那么您将无法执行此操作。因为该子行的其他重复行可能在table1中。这样您可以返回多行。因此,您将不知道哪个是最新的。取而代之的是,您必须在插入之前查询table1,然后插入,然后找到新旧客户ID集之间的区别:
CREATE TEMPORARY TABLE table1old ( customerId (int) PRIMARY KEY ); INSERT INTO table1old SELECT customerId FROM table1; INSERT INTO table1 (CustomerName,Address,State) VALUES('value1','value2','value3'); set @customerId = ( SELECT customerId FROM table1 WHERE CustomerName NOT IN table1old); INSERT INTO table2 (customerId,product,cost) VALUES(@customerId,'valueA','valueB');
只需使用LAST_INSERT_ID()。
PS:有趣的是,给定表定义,理想情况下可以这样写:
INSERT INTO ( SELECT CustomerName,Address,State,A,B FROM table1 JOIN table2 USING (CustomerId)) VALUES('value1','value2','value3','valueA','valueB')
因为只会产生一对新的table1和table2值。通过SQL中的视图有一些合法的更新,尽管目前没有涉及MySQL中的多个表的更新