考虑以下表格:
产品
+----+------+-------------+
| id | name | category_id |
+----+------+-------------+
| 1 | foo | 1 |
+----+------+-------------+
类别
+----+------+
| id | name |
+----+------+
| 1 | food |
+----+------+
现在假设我有人发布了一个新产品:
{
"name": "bar",
"category": "drink"
}
在这种情况下,我们需要自动创建新类别:
INSERT IGNORE INTO categories (name) VALUES ('drink')
然后我们最终可以插入实际的产品行:
INSERT INTO products (name, category_id) VALUES ('bar', SELECT id FROM categories WHERE name = 'drink')
然而,虽然这有效,但它需要一个事务设置是安全的,因为这似乎不是一个超级复杂的查询,我想知道是否可以将两个查询合并在一起(例如,将类别查询插入到产品插入的选择子查询中?
答案 0 :(得分:2)
我会反对INSERT IGNORE
,原因是@Bill Karwin so eloquently explains。此外,正如INSERT ... ON DUPLICATE KEY UPDATE
Syntax所述:
如果表包含
AUTO_INCREMENT
列并且INSERT ... ON DUPLICATE KEY UPDATE
插入或更新行,则LAST_INSERT_ID()
函数将返回AUTO_INCREMENT
值。例外:对于更新,LAST_INSERT_ID()
在MySQL 5.1.12之前没有意义。但是,您可以使用LAST_INSERT_ID(expr)
解决此问题。假设id
是AUTO_INCREMENT
列。要使LAST_INSERT_ID()
对更新有意义,请按如下方式插入行:INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
然后可以获得How to Get the Unique ID for the Last Inserted Row下记录的id
(无论是预先存在的还是新插入的):
如果将记录插入包含
AUTO_INCREMENT
列的表中,则可以通过调用mysql_insert_id()
函数获取存储在该列中的值。[ deletia ]当生成新的
AUTO_INCREMENT
值时,您还可以通过执行带有mysql_query()
的SELECT LAST_INSERT_ID()
语句并从语句返回的结果集中检索值来获取它。 / p>
因此,例如,人们可以这样做:
INSERT INTO categories (name) VALUES ('drink')
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
INSERT INTO products (name, category_id) VALUES ('bar', LAST_INSERT_ID());
当然,如果您需要原子性,这些语句仍然需要在事务中执行。
答案 1 :(得分:-1)
不,那是不可能的。但是,您可以执行的操作是在产品表上创建BEFORE INSERT
触发器,并在触发器内部检查(如果类别已存在)。如果它不存在,你可以在那里创建它。
触发器将在与INSERT
- 语句相同的事务中自动执行,因此不需要额外的事务处理。
我看到的唯一问题是,当您忘记触发器时,您可能会开始想知道为什么每个新产品都会自动显示类别(类似于我)。
<强>更新强>
中查看简单触发器的示例您可以使用BEFORE INSERT
在NEW.column_name
触发器中访问要插入的新值,这样就可以NEW.category