Java调用PostgreSQL函数时,如何用参数匹配所有ctv.value值?
问题描述
我编写了如下Java方法用于调用PostgreSQL函数:
public void cleanupCustomFields(String keyField, String keyFieldValue, String[] fieldsToCleanup) throws ServiceWareException { Connection conn = null; CallableStatement cleanupFields = null; try { conn = getConnection(); cleanupFields = conn.prepareCall("{call cleanup_custom_tags(?, ?, ?)}"); cleanupFields.setString(1, keyField); cleanupFields.setString(2, keyFieldValue); cleanupFields.setArray(3, conn.createArrayOf("varchar", fieldsToCleanup)); cleanupFields.execute(); } catch (SQLException ex) { throw new ServiceWareException(Messages.DATABASE_GENERAL_FAILURE, ex); } finally { closeConnection(conn, null, cleanupFields); } }
对应的PostgreSQL函数代码如下:
CREATE OR REPLACE FUNCTION public.cleanup_custom_tags( _tag_name character varying, _tag_value character varying, _tags_list character varying[]) RETURNS void LANGUAGE 'plpgsql' COST 100 VOLATILE SECURITY DEFINER PARALLEL UNSAFE AS $BODY$ DECLARE tag_id_list int[]; BEGIN SELECT ARRAY_AGG(id) INTO tag_id_list FROM tbl_custom_tags WHERE tag_name = ANY(_tags_list); DELETE FROM tbl_custom_tag_values WHERE tag_id = ANY(tag_id_list) AND entity_id IN (SELECT s.id FROM tbl_servers s INNER JOIN tbl_custom_tag_values ctv ON s.id = ctv.entity_id INNER JOIN tbl_custom_tags ct ON ct.id = ctv.tag_id WHERE ct.tag_name = _tag_name AND ctv.value = _tag_value); END; $BODY$;
我希望给变量keyFieldValue(对应PG函数中的_tag_value)设置一个值,使其能匹配ctv.value中的所有内容(类似正则表达式.*的效果),但查阅文档后未能成功实现,请问需要使用什么语法?
解决方案
当前PostgreSQL函数中用ctv.value = _tag_value做精确匹配,要实现匹配所有内容的效果,推荐以下两种方式:
方式1:通过特殊标记触发全匹配逻辑
指定一个特殊值(比如'*'),当传入的_tag_value等于该值时,跳过ctv.value的匹配条件,直接匹配所有内容:
CREATE OR REPLACE FUNCTION public.cleanup_custom_tags( _tag_name character varying, _tag_value character varying, _tags_list character varying[]) RETURNS void LANGUAGE 'plpgsql' COST 100 VOLATILE SECURITY DEFINER PARALLEL UNSAFE AS $BODY$ DECLARE tag_id_list int[]; BEGIN SELECT ARRAY_AGG(id) INTO tag_id_list FROM tbl_custom_tags WHERE tag_name = ANY(_tags_list); DELETE FROM tbl_custom_tag_values WHERE tag_id = ANY(tag_id_list) AND entity_id IN (SELECT s.id FROM tbl_servers s INNER JOIN tbl_custom_tag_values ctv ON s.id = ctv.entity_id INNER JOIN tbl_custom_tags ct ON ct.id = ctv.tag_id WHERE ct.tag_name = _tag_name -- 新增逻辑:如果_tag_value为'*'则匹配所有,否则精确匹配 AND (_tag_value = '*' OR ctv.value = _tag_value)); END; $BODY$;
使用时,在Java代码中给keyFieldValue赋值为"*"即可实现全匹配。这种方式性能最优,还能保留ctv.value字段的索引利用率。
方式2:使用正则匹配(全量场景不推荐)
PostgreSQL支持用~操作符做正则匹配,当传入的_tag_value为'.*'时,就能匹配所有ctv.value内容:
-- 修改子查询中的条件部分 WHERE ct.tag_name = _tag_name AND ctv.value ~ _tag_value
但这种方式会增加计算开销,且无法利用ctv.value上的索引(如果存在),仅适合需要灵活正则规则的场景,全量匹配不建议使用。
内容的提问来源于stack exchange,提问作者Liran_T
相关产品推荐
相关产品推荐

