6

我正在寻找将数据插入多个 MySQL 表的最佳实践方法,其中某些列是外键依赖项。这是一个例子:

Table: contacts
--------------------------------------------------------------------
|  contact_id  |  first_name  | last_name  |  prof_id  |  zip_code  |
--------------------------------------------------------------------

'contacts' 表有 PRIMARY KEY (contact_id) 这只是 auto_increments,和 FOREIGN KEY (prof_id) REFERENCES 'profession' 表, FOREIGN KEY (zip_code) REFERENCES 'zip_code' 表。这些表看起来像这样:

Table: profession
----------------------------
|  prof_id  |  profession  |
----------------------------

其中 'prof_id' 是一个 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,并且

Table: zip_code
--------------------------------
|  zip_code  | city  |  state  |
--------------------------------

其中 'zip_code' 是一个 INT(5) NOT NULL PRIMARY KEY。

我有一个想要为其添加记录的新人,比如说:

first_name = 'John', last_name = 'Doe', profession = 'Network Administrator', city = 'Sometown', state = 'NY', zip_code = 12345

这就是我想要做的:我想获取这些信息并将其插入到适当的表和列中。为了防止列中的重复值(例如职业),我首先要确保没有“网络管理员”的条目,如果有我只想获取它的键值,如果不插入它然后获取它的键值。zip_code、city、state 也是如此 - 如果存在,只需使用该 zip_code 密钥,否则插入新数据并获取关联的密钥。然后,最后,我想使用提供的信息将新联系人输入到“联系人”表中,包括与其他表中的职业和位置相关的适当键值。

我的问题是,最好的推荐方法是什么?我知道我可以坐在这里写一个语句来检查给定的职业是否存在,如果不存在则输入它,然后获取密钥。对 zip_code 执行相同的操作。然后最后将所有这些插入到联系人中,但是我知道必须有更好的方法在更少(可能是一个)语句中完成此操作,特别是考虑到如果数据库在中间脱机一会儿可能会导致问题所有这一切。有没有办法使用 JOIN 和这个 INSERT 来让所有东西都级联到正确的位置?我是否应该使用 TRANSACTION 系列语句来处理这个问题?

我正处于 SQL 的学习阶段,但我觉得到目前为止我使用的书籍和资源已经开始使用嵌套查询和 JOINS,前提是我们已经填充了所有这些数据表。我什至愿意接受关于我应该在谷歌上搜索什么以更好地学习这一点的建议,或者任何可以帮助填补这一空白的资源。理想情况下,我希望看到一些功能正常的 SQL 代码来执行此操作。如有必要,假设 PHP 作为与数据库交互的语言,但命令行 sql 是我的目标。提前谢谢,希望我把一切都说清楚了。

4

1 回答 1

4

简而言之,您想使用事务 (有关此的更多文档),以便您的插入是atomic。这是保证插入所有(或不插入)数据的唯一方法。否则,您可能会遇到您描述的数据库在某些插入后变得不可用而其他无法完成的情况。事务告诉数据库您正在做的事情是全有或全无,因此如果出现问题,它应该回滚。

当您使用合成主键时,PHP 和其他语言提供了获取最后插入的 id 的机制。如果你想完全在 MySQL 中完成,你可以使用LAST_INSERT_ID()函数。你最终会得到这样的代码:

START TRANSACTION;
INSERT INTO foo (auto,text)
    VALUES(NULL,'text');         # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
    VALUES(LAST_INSERT_ID(),'text');  # use ID in second table
COMMIT;
于 2013-08-05T23:01:39.443 回答