插入不匹配的元组

plicqrtu  于 2021-08-13  发布在  Java
关注(0)|答案(1)|浏览(401)

我有一个包含以下列的表: id , store , category_id 以及 option_id . 此表的内容通过web钩子从其他服务器上的原始表更新。一旦收到的内容,我将需要检查,看看哪些行需要删除,哪些需要插入。
为了简单起见,让我们假设我从web钩子收到的category和option id元组是(1,1)和(1,2),并且数据库已经包含(1,1)和(1,3)。所以(1,3)需要删除,(1,2)需要插入。
我可以这样做:

DELETE FROM store_category_options 
 WHERE store=1 AND (category_id, option_id) NOT IN ((1,1), (1,2));

但是,插入需要两个查询,一个用于检索数据库中已有的值

SELECT category_id, option_id FROM store_category_options WHERE store=1

在mysql之外计算出差值后,再插入一个:

INSERT INTO store_category_option (category_id, option_id) VALUES (1,2)

我想知道是否有办法用一个查询而不是两个查询来进行插入。

s3fp2yjn

s3fp2yjn1#

最后我自己想出来了。我们可以从将webhook数据转换成一个派生表开始 WHERE NOT IN ```
SELECT 1 as store_category_id, 1 as store_option_id UNION SELECT 1, 2;

在mysql cli中,这将生成输出:

+-------------------+-----------------+
| store_category_id | store_option_id |
+-------------------+-----------------+
| 1 | 1 |
| 1 | 2 |
+-------------------+-----------------+
2 rows in set (0.00 sec)

要使用where子句查询此表,必须将其包含在另一个select的子查询中,并为该表提供别名:

SELECT store_category_id, store_option_id FROM (
SELECT 1 as store_category_id, 1 as store_option_id
UNION SELECT 1, 2
) AS vt WHERE store_option_id = 1;

这将产生输出:

+-------------------+-----------------+
| store_category_id | store_option_id |
+-------------------+-----------------+
| 1 | 1 |
+-------------------+-----------------+
1 row in set (0.00 sec)

现在我们可以使用where子句和另一个子查询来选择要插入的行:

SELECT store_category_id, store_option_id FROM (
SELECT 1 as store_category_id, 1 as store_option_id
UNION SELECT 1, 2
) AS vt WHERE (category_id, option_id) NOT IN (
SELECT store_category_id, store_option_id
FROM store_category_options
);

结果是:

+-------------------+-----------------+
| store_category_id | store_option_id |
+-------------------+-----------------+
| 1 | 2 |
+-------------------+-----------------+
1 row in set (0.00 sec)

最后,为了插入我们计算的行,我们将前面的select语句包含在insert into select语句中

INSERT INTO store_category_options
(store_category_id, store_option_id)
SELECT store_category_id, store_option_id FROM (
SELECT 1 as store_category_id, 1 as store_option_id
UNION SELECT 1, 2
) AS vt WHERE (store_category_id, store_option_id) NOT IN (
SELECT store_category_id, store_option_id
FROM store_category_options
);

相关问题