我在谷歌或文档中找到答案时遇到了问题...... 我需要针对数组类型进行不区分大小写的选择。
所以如果:
value = {"Foo","bar","bAz"}
我需要
SELECT value FROM table WHERE 'foo' = ANY(value)
匹配。
我尝试了很多lower()的组合而没有成功。
ILIKE
代替=
似乎有效,但我一直对LIKE
感到紧张 - 这是最好的方法吗?
答案 0 :(得分:17)
未提及的一个替代方法是安装PostgreSQL 8.4+附带的the citext
extension并使用citext
数组:
regress=# CREATE EXTENSION citext;
regress=# SELECT 'foo' = ANY( '{"Foo","bar","bAz"}'::citext[] );
?column?
----------
t
(1 row)
如果你想严格正确并避免扩展,你必须做一些pretty ugly subqueries,因为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);
答案 1 :(得分:16)
这对我来说似乎很苛刻,但我认为它应该有用
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索引。
答案 2 :(得分:4)
另一种选择是使用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;
如果数组元素在小写的数组中是唯一的,那么您甚至不需要GROUP BY
,因为每个value
只能匹配一次。
SELECT value
FROM (SELECT value, lower(unnest(value)) AS val FROM tbl) x
WHERE val = 'foo';
显然, 'foo'
必须是小写的
应快。
如果你希望 fast 有一个大表,我会创建一个功能GIN索引。
答案 3 :(得分:0)
我的解决方案是使用子选择...
排除值and groupname not ilike all (
select unnest(array[exceptionname||'%'])
from public.group_exceptions
where ...
and ...
)
答案 4 :(得分:0)
在大多数情况下,正则表达式可以胜任
SELECT array_to_string('{“ a”,“ b”,“ c”}':: text [],'|')〜* ANY('{“ A”,“ B”,“ C”}' );
答案 5 :(得分:0)
我发现创建自定义PostgreSQL函数最适合我
CREATE OR REPLACE FUNCTION lower(text_array text[]) RETURNS text[] AS
$BODY$
SELECT (lower(text_array::text))::text[]
$BODY$
LANGUAGE SQL IMMUTABLE;