【问题标题】:SQL Bulk Delete Queries on composite key with fixed length query具有固定长度查询的复合键上的 SQL 批量删除查询
【发布时间】:2026-01-04 16:15:02
【问题描述】:

在 Postgresql 中,我有一个具有复合主键的表。 PRIMARY KEY(id_fnd_users, id_app_apps,id_app_categories)

我正在尝试创建一个查询以进行批量删除,并且我希望此查询的大小固定(用于统计分析目的)。

这是我想出的:

 DELETE FROM app_users_apps_categories
 WHERE
   ("id_fnd_users", "id_app_apps","id_app_categories") 
   in (
          SELECT id_fnd_users, id_app_apps, id_app_categories
          FROM unnest($1::"uuid"[], $2::"uuid"[], $3::"uuid"[]) AS foo(id_fnd_users, id_app_apps,id_app_categories)
        )

以下是我为此查询设置的参数示例:

$1 = '{61615807-c654-4844-910c-1609dcf3ff4c,61615807-c654-4844-910c-1609dcf3ff4c}',
$2 = '{25fda4e9-ca83-41fb-98ad-77230a74bbbc,34c0cd50-905e-4ea6-9ccf-baeaa591e98a}', 
$3 = '{NULL,NULL}'

基本上我会得到这样的查询:

DELETE FROM app_users_apps_categories
        where ("id_fnd_users", "id_app_apps","id_app_categories") in (
          SELECT id_fnd_users, id_app_apps, id_app_categories
          FROM 
            unnest(
                '{61615807-c654-4844-910c-1609dcf3ff4c,61615807-c654-4844-910c-1609dcf3ff4c}'::"uuid"[], 
                '{25fda4e9-ca83-41fb-98ad-77230a74bbbc,34c0cd50-905e-4ea6-9ccf-baeaa591e98a}'::"uuid"[], 
                '{NULL,NULL}'::"uuid"[]
             ) AS foo(id_fnd_users, id_app_apps,id_app_categories)
      )

查询执行正确,但我的记录没有被删除。 我检查了 ID 和它们的顺序,它们没问题。 所以我想这不是正确的做法,但我想不出另一个。

提前致谢。

【问题讨论】:

    标签: sql postgresql performance


    【解决方案1】:

    你是如何传递参数 $1,$2,$3 的。但我想这并不重要。您的问题似乎与 NULL 值有关。无论您如何进行 null 到 null 的比较,总是会产生 null 并且没有相等的(或这里的 IN)将永远匹配。与任何其他数据类型一样,您可以将 coalesce 与 UUID 一起使用。所以

    delete 
      from app_users_apps_categories
     where (id_fnd_users
           ,id_app_apps
           ,coalesce(id_app_categories,'00000000-0000-0000-0000-000000000000'::uuid)
           )                             
       in (
            select id_fnd_users
                 , id_app_apps
                 , coalesce(id_app_categories,'00000000-0000-0000-0000-000000000000'::uuid) 
              from 
                   unnest(
                           '{61615807-c654-4844-910c-1609dcf3ff4c,61615807-c654-4844-910c-1609dcf3ff4c}'::uuid[], 
                           '{25fda4e9-ca83-41fb-98ad-77230a74bbbc,34c0cd50-905e-4ea6-9ccf-baeaa591e98a}'::uuid[], 
                           '{null,null}'::uuid[]
                         ) as foo(id_fnd_users, id_app_apps,id_app_categories)  
           ) ;
    

    您也可以将其包装在返回 void 的 SQL 函数中:

    create or replace function remove_app_users_apps_categories(
                               fnd_users_in uuid[]
                             , app_apps_in  uuid[]
                             , app_cats_in  uuid[]
                             )
      returns void
      language sql 
    as $$
    delete 
      from app_users_apps_categories
     where (id_fnd_users
           ,id_app_apps
           ,coalesce(id_app_categories,'00000000-0000-0000-0000-000000000000'::uuid)
           )                             
       in (
            select id_fnd_users
                 , id_app_apps
                 , coalesce(id_app_categories,'00000000-0000-0000-0000-000000000000'::uuid) 
              from 
                   unnest( fnd_users_in
                         , app_apps_in 
                         , app_cats_in 
                         ) as foo(id_fnd_users, id_app_apps,id_app_categories)  
           ) ; 
    $$; 
    

    我猜只是我的怪癖,但我从不使用 $n 表示法。不记得n是什么意思。

    【讨论】: