如何一次检查多个值的存在
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 中一次检查多个值是否存在的最快方法吗?
我还考虑过使用 EXISTS
和 UNION
一起查询的方案,但文档说 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 一起使用。它将在一次往返中完成所有事情。您也将能够获得结果。
我在 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 中一次检查多个值是否存在的最快方法吗?
我还考虑过使用 EXISTS
和 UNION
一起查询的方案,但文档说 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 一起使用。它将在一次往返中完成所有事情。您也将能够获得结果。