我需要使用函数UNACCENT
来删除WHERE CLAUSE
中的变音符号,但仅在安装了此扩展名的情况下才使用普通字符串比较。
考虑表A和B,它可以有数十万行(历史)。然后我从A加到B并在B中寻找一个特定的字符串,但是不想要检查变音符号,并且显然必须快速几乎与正常比较相同(在更多字段中搜索的速度必须相同)
CREATE EXTENSION unaccent;
--DROP EXTENSION unaccent;
DROP TABLE IF EXISTS A;
DROP TABLE IF EXISTS B;
CREATE TEMPORARY TABLE A (id serial, cost numeric, b_id int);
CREATE TEMPORARY TABLE B (id serial, name varchar, surname varchar);
INSERT INTO B(id, name, surname) SELECT gen.id AS id, 'Some test name' || gen.id as name, 'Some test surname' || gen.id as surname FROM (SELECT generate_series(1,10000) as id) gen;
INSERT INTO A(id, cost, b_id) SELECT gen.id AS id, random() * 1000 as cost, (gen.id -1 ) / 10 + 1 FROM (SELECT generate_series(1,100000) as id) gen;
-- this cost 115 ms
SELECT * FROM A
LEFT OUTER JOIN B ON B.id = A.b_id
WHERE
B.name ILIKE '%e%' AND
B.surname ILIKE '%e%'
-- this cost 412 ms OR crash where not instaled extension
SELECT * FROM A
LEFT OUTER JOIN B ON B.id = A.b_id
WHERE
CASE WHEN (SELECT EXISTS ( SELECT 1 FROM pg_extension WHERE extname = 'unaccent' AND extversion IS NOT NULL) LIMIT 1) THEN unaccent(B.name) ILIKE '%e%' ELSE B.name ILIKE '%e%' END AND
CASE WHEN (SELECT EXISTS ( SELECT 1 FROM pg_extension WHERE extname = 'unaccent' AND extversion IS NOT NULL) LIMIT 1) THEN unaccent(B.surname) ILIKE '%e%' ELSE B.surname ILIKE '%e%' END
我需要第二个选择与第一个选择相同的速度,并且在未扩展时不会崩溃。
感谢您的帮助。帕维尔
答案 0 :(得分:0)
您不能在单个SQL语句中执行此操作,因为查询在执行之前会被解析,如果unaccent
不存在,则会出现解析错误。
有两种可能性:
运行两个查询:第一个查询是否存在扩展名,并根据第一个查询的结果构建第二个查询。
您设置了SAVEPOINT
,然后尝试unaccent
查询,如果失败,则ROLLBACK TO SAVEPOINT
并尝试其他查询。
在PL / pgSQL中,您可以使用BEGIN ... EXCEPTION ... END
块对其进行编码。