PostgreSQL如何单条SQL删除匹配UUID数组值对的表行
问题说明
需要单条SQL删除test_info表中匹配多组id_name、id_surname值对的行,初始尝试的SQL无法执行,涉及表结构如下:
create table test_info ( id_name uuid not null, id_surname uuid not null );
初始错误写法:
DELETE FROM test_info WHERE id_name = ($1::uuid[]) AND id_surname = ($2::uuid[])
错误原因
=是单值等值判断符,无法直接将uuid类型的字段和uuid数组类型的参数做匹配- 就算改用
ANY匹配数组,两个独立数组的判断逻辑会生成笛卡尔积——比如传入$1为[a,b]、$2为[c,d],会错误匹配(a,d)、(b,c)这类非目标值对,不符合成对匹配的需求。
正确实现方案
方案1:传两个同顺序对应数组(兼容原有传参习惯)
使用unnest函数将两个等长数组按下标成对展开为值对集合,通过IN做匹配,是最贴合原有传参逻辑的写法:
DELETE FROM test_info WHERE (id_name, id_surname) IN ( SELECT * FROM unnest($1::uuid[], $2::uuid[]) );
参数要求:$1为所有待匹配id_name组成的uuid数组,$2为同顺序一一对应的id_surname组成的uuid数组,两个数组长度必须完全一致。
方案2:直接在SQL中枚举值对
如果不需要动态传参,值对固定,可以直接在行构造器中枚举所有待删除的值对:
DELETE FROM test_info WHERE (id_name, id_surname) IN ( ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid, 'b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid), ('c0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid, 'd0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid) );
避坑提醒
绝对不要使用如下写法,该写法会交叉匹配两个数组的所有组合,造成误删非目标数据:
-- 错误写法,会产生笛卡尔积错配 DELETE FROM test_info WHERE id_name = ANY($1::uuid[]) AND id_surname = ANY($2::uuid[])
如果test_info表存在(id_name, id_surname)联合索引或联合主键,上述正确写法可以正常命中索引,删除效率较高。
内容的提问来源于stack exchange,提问作者Nakem1
相关产品推荐
相关产品推荐

