我在PostgreSQL中有一个表,在bytea
列上有一个唯一索引。
目前,我正在运行此查询以确定表中该列是否已存在值。
-- mycolumn definition: mycolumn bytea unique not null
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn;
当我将结果发送到DataReader
时,我只是检查它是否有行,如果是,则返回true。
但是,我需要批量检查数百个值,由于往返开销,每个值的运行速度有点慢。
我考虑过发送多个语句:
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn1;
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn2;
SELECT 1 FROM mytable WHERE mycolumn = @mycolumn3;
-- etc
在这里,我会看到读者是否有像以前一样的行,然后调用NextResult()
转到下一个查询结果。当然,我必须生成此查询并添加参数。这是在pgsql中一次检查多个值是否存在的最快方法?
我还考虑了一起使用EXISTS
和UNION
查询的方案,但文档说UNION不保留排序。那么我还必须在查询中提供一个订单号作为另一个参数,这样我就可以在服务器上重新排序结果。这似乎比上面更浪费......如果有效。
我刚刚根据文档发现了PG中的returning multiple result sets is not supported。所以上面是行不通的。那么最好的方法是什么?
<击>
命令字符串可以包含多个SQL命令(以分号分隔)。 [...] 请注意,返回的PGresult结构仅描述从字符串执行的最后一个命令的结果。
显然以上只涉及功能。
答案 0 :(得分:2)
如果你需要的只是bytea
值而不是id
左右,那么你可以用一组值来解决它,并在处理时保留 normalality (大概和未经测试,我自己不是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
加入unnested数组值并检查哪些值确实具有相应的值。您将获得等于数组长度的行数,每行包含标量值boolean
类型。 normalality 的排序可确保按照数组中值的顺序返回行。
如果您希望获得一个boolean
数组,那么您应该将查询包装在外部查询中array_agg(present)
coalesce(mt.present, false) AS present
子句(因此请使用子语句中的别名)查询)。
答案 1 :(得分:1)
您可以使用Npgsql的原始想法。它将在一次往返中完成所有工作。您也可以获得结果。
答案 2 :(得分:-1)
如何构建这样的动态查询:
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 )
这只需要向服务器进行一次往返。
您可以在一个查询中打包几十个号码并立即检查所有号码。
在应用程序端,只需直接从结果集中读取缺失的数字。
原则上,也应该可以创建一个只有一个数组类型参数的预备语句,并将一个值数组绑定到这个参数而不是构建一个动态查询,但我从来没有这样做过,并且#&# 39;不知道怎么做。您可以对此主题进行进一步研究。