我在这里、谷歌或文档中找不到答案……
我需要对数组类型进行不区分大小写的选择。
因此,如果:
value = {"Foo","bar","bAz"}
我需要
SELECT value FROM table WHERE 'foo' = ANY(value)
匹配。
我尝试了很多 lower() 组合但没有成功。
ILIKE
而不是=
似乎工作,但我一直很紧张LIKE
- 这是最好的方法吗?
我在这里、谷歌或文档中找不到答案……
我需要对数组类型进行不区分大小写的选择。
因此,如果:
value = {"Foo","bar","bAz"}
我需要
SELECT value FROM table WHERE 'foo' = ANY(value)
匹配。
我尝试了很多 lower() 组合但没有成功。
ILIKE
而不是=
似乎工作,但我一直很紧张LIKE
- 这是最好的方法吗?
这对我来说似乎很骇人听闻,但我认为它应该有效
SELECT value FROM table WHERE 'foo' = ANY(lower(value::text)::text[])
ilike
如果您的阵列可以有_
或%
请注意,您正在做的是将文本数组转换为单个文本字符串,将其转换为小写,然后再转换回数组。这应该是安全的。如果这还不够,您可以使用 string_to_array 和 array_to_string 的各种组合,但我认为标准的文本表示应该更安全。
在下面的子查询解决方案上更新构建,一个选项是一个简单的函数:
CREATE OR REPLACE FUNCTION lower(text[]) RETURNS text[] LANGUAGE SQL IMMUTABLE AS
$$
SELECT array_agg(lower(value)) FROM unnest($1) value;
$$;
然后你可以这样做:
SELECT value FROM table WHERE 'foo' = ANY(lower(value));
这实际上可能是最好的方法。如果需要,您还可以在函数的输出上创建 GIN 索引。
未提及的一种替代方法是安装PostgreSQL 8.4+ 附带的citext
扩展并使用以下数组citext
:
regress=# CREATE EXTENSION citext;
regress=# SELECT 'foo' = ANY( '{"Foo","bar","bAz"}'::citext[] );
?column?
----------
t
(1 row)
如果您想对此严格正确并避免扩展,则必须执行一些非常丑陋的子查询,因为 Pg 没有很多丰富的数组操作,尤其是没有功能映射操作。就像是:
SELECT array_agg(lower(($1)[n])) FROM generate_subscripts($1,1) n;
...其中 $1 是数组参数。在您的情况下,我认为您可以作弊,因为您不关心保留数组的顺序,因此您可以执行以下操作:
SELECT 'foo' IN (SELECT lower(x) FROM unnest('{"Foo","bar","bAz"}'::text[]) x);
另一种选择是unnest()
WITH tbl AS (SELECT 1 AS id, '{"Foo","bar","bAz"}'::text[] AS value)
SELECT value
FROM (SELECT id, value, unnest(value) AS val FROM tbl) x
WHERE lower(val) = 'foo'
GROUP BY id, value;
我添加了一id
列以获得完全相同的结果 - 即value
如果基表中有重复项,则重复。根据您的具体情况,您可能可以id
从查询中省略 以折叠结果中的重复项,或者如果开始没有重复项。还演示了一种替代语法:
SELECT value
FROM (SELECT value, lower(unnest(value)) AS val FROM tbl) x
WHERE val = 'foo'
GROUP BY value;
If array elements are unique within arrays in lower case, you don't even need the GROUP BY
, since every value
can only match once.
SELECT value
FROM (SELECT value, lower(unnest(value)) AS val FROM tbl) x
WHERE val = 'foo';
'foo'
must be lower case, obviously.
Should be fast.
If you want that fast wit a big table, I would create a functional GIN index, though.
my solution to exclude values using a sub select...
and groupname not ilike all (
select unnest(array[exceptionname||'%'])
from public.group_exceptions
where ...
and ...
)
Regular expression may do the job for most cases
SELECT array_to_string('{"a","b","c"}'::text[],'|') ~* ANY('{"A","B","C"}');
I find creating a custom PostgreSQL function works best for me
CREATE OR REPLACE FUNCTION lower(text_array text[]) RETURNS text[] AS
$BODY$
SELECT (lower(text_array::text))::text[]
$BODY$
LANGUAGE SQL IMMUTABLE;