如何一次检查多个值的存在

How to check existence of multiple values at once

我在 PostgreSQL 中有一个 table,在 bytea 列上有一个唯一索引。

目前,我正在 运行 执行此查询以确定 table.

中的该列是否已存在值
-- mycolumn definition: mycolumn bytea unique not null
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn;

当我得到 DataReader 的结果时,我只是检查它是否有行,如果有,return 为真。

但是,我可能需要批量检查数百个值,由于往返开销,每个值 运行 感觉有点慢。

我考虑过只发送多个语句:

SELECT 1 FROM mytable WHERE mycolumn = @mycolumn1;
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn2;
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn3;
-- etc

这里我会看看reader有没有跟之前一样的行,然后调用NextResult()去下一个查询结果。当然,我必须生成此查询并添加参数。这是在 pgsql 中一次检查多个值是否存在的最快方法吗?

我还考虑过使用 EXISTSUNION 一起查询的方案,但文档说 UNION 不保留顺序。因此,我还必须提供一个订单号作为查询中的另一个参数,这样我才能对服务器上的结果重新排序。这似乎比上面更浪费......如果有效的话。

更新

我刚刚根据文档发现,returning multiple result sets is not supported 在 PG 中。所以上面是行不通的。那么最好的方法是什么?

The command string can include multiple SQL commands (separated by semicolons). [...] Note however that the returned PGresult structure describes only the result of the last command executed from the string.

显然以上仅指功能。

如何构建这样的动态查询:

SELECT x FROM (
    select unnest( 
        ARRAY[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
              21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,30]
    ) as x
) x
WHERE x NOT IN ( SELECT my_column FROM my_table )

这只需要到服务器一次往返。
您可以在一个查询中打包几十个号码并一次检查所有号码。
在应用程序端直接从结果集中读取缺失的数字。


假设,也应该可以创建一个只有一个数组类型参数的准备语句,并将一组值绑定到这个参数,而不是构建一个动态查询,但我从来没有这样做过,也不会不知道该怎么做。您可以对此主题做进一步的研究。

如果您只需要 bytea 个值而没有 id 左右,那么您可以使用一个值数组并保留 序数 处理时(大概是未经测试,我自己不是 npgsql 用户):

SELECT coalesce(mt.present, false) 
FROM unnest(@values) WITH ORDINALITY x (v, ord)
LEFT JOIN LATERAL (SELECT true AS present FROM mytable WHERE mycolumn = x.v) mt ON true
ORDER BY x.ord;

您传入一个数组 @values,其中包含要测试的 bytea 个值。取消嵌套数组时,您可以使用 WITH ORDINALITY 子句,这样您就可以保留顺序。然后将 mytable 连接到未嵌套的数组值并检查哪些确实具有对应的值。您将返回等于数组长度的行数,每行包含一个 boolean 类型的标量值。按 ordinality 排序确保行按数组中值的顺序返回。

如果你更喜欢返回一个 boolean 的数组,那么你应该将查询包装在一个外部查询中,其中你 array_agg(present) coalesce(mt.present, false) AS present 子句(所以在子查询)。

您可以将您的原始想法与 Npgsql 一起使用。它将在一次往返中完成所有事情。您也将能够获得结果。