如何设置表之间的关系在phpMyAdmin中

时间:2014-06-26 01:21:03

标签: mysql sql database-design phpmyadmin

我的问题是,当我创建一个表格时,table1包含以下列:

  • customerId
  • CustomerName
  • Address
  • State

其中customerIdPRIMARY KEY AUTO_INCREMENT

然后table2例如列:

  • purchaseId
  • customerId
  • product
  • cost

PRIMARY KEY purchaseId customerId,外键table1来自table1

这应该意味着我已经使用table2customerIdINSERT INTO table1 (CustomerName,Address,State) VALUES('value1','value2','value3') 之间建立了关系。

这两个表最初都是空的,所以我编写了这个SQL命令:

table2

这很好用,但当我尝试插入子表(customerId)时,它告诉我:

  

错误外键约束

所以基本上我想要做的是插入父表然后插入子表,以便table2作为外键出现在customerId(子表)中,并与{{ 1}}在table1(父表)。

在没有外键的情况下,我是否必须首先创建两个表格,然后尝试建立关系。只要关系存在,它就会说存在约束。

1 个答案:

答案 0 :(得分:1)

table2外键约束意味着任何table2 customerId值必须在table1中显示为customerId。您收到错误是因为您将customerID插入到table2中并且不会出现在table1中。

由于DBMS通过自动增量生成table1 customerID,如果您插入一行,则必须获取该值才能使用该customerID将行插入到table2中。

我想你说"我已经建立了table1和table2&#34之间的关系;意思是"我宣布了一个外键约束"。我想你认为这意味着"在我插入table1之后,当我插入table2"时,DBMS将使用自动生成的键值作为外键值。但这并不意味着。你必须自己做。外键约束仅表示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值。

其次,假设您处于序列化交易中,并且您不使用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,然后插入,然后找出旧的和新的customerIds集之间的区别:

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中的多个表