使用pg_background调用含raise notice函数时WIN1252编码报错求助
问题:pg_background扩展在Windows/PostgreSQL 15下的字符编码异常(与RAISE NOTICE相关)
环境与编码设置
当前客户端与服务器编码:
select current_setting('client_encoding'), current_setting('server_encoding');
输出:
current_setting | current_setting -----------------+----------------- WIN1252 | UTF8 (1 row)
测试函数定义
创建两个测试函数,区别仅在于是否包含RAISE NOTICE语句:
create or replace function test_encoding_1() returns text language plpgsql as $$ begin raise notice 'Noël'; return 'Noël'; end $$; create or replace function test_encoding_2() returns text language plpgsql as $$ begin return 'Noël'; end $$;
直接调用结果
直接调用两个函数均正常显示字符:
select test_encoding_1();
输出:
NOTICE: Noël test_encoding_1 ----------------- Noël (1 row)
pg_background调用的异常表现
通过pg_background调用时,含RAISE NOTICE的函数报错,无该语句的函数正常:
select r from pg_background_result(pg_background_launch('select test_encoding_1()')) as t(r text);
报错:
ERROR: invalid byte sequence for encoding "UTF8": 0xeb 0x6c
调用无RAISE NOTICE的函数正常:
select r from pg_background_result(pg_background_launch('select test_encoding_2()')) as t(r text);
输出:
r ------ Noël (1 row)
修改客户端编码为SQL_ASCII后的表现
设置客户端编码为SQL_ASCII后不再报错,但字符显示乱码:
set client_encoding to 'SQL_ASCII'; select r from pg_background_result(pg_background_launch('select test_encoding_1()')) as t(r text);
输出:
NOTICE: Noël r ------- Noël (1 row)
select r from pg_background_result(pg_background_launch('select test_encoding_2()')) as t(r text);
输出:
r ------- Noël (1 row)
需求
是否可通过配置服务器、修改函数代码或其他方式,获取正确WIN1252字符集的结果?
解决方案
方法1:后台会话显式设置客户端编码
pg_background启动的后台会话默认继承服务器编码(UTF8),与当前客户端的WIN1252编码不一致,导致RAISE NOTICE的输出转码失败。在后台执行的SQL开头显式设置client_encoding为WIN1252即可:
select r from pg_background_result(pg_background_launch('SET client_encoding = ''WIN1252''; select test_encoding_1()')) as t(r text);
此方法让后台会话的编码与当前客户端对齐,RAISE NOTICE的输出会按WIN1252编码传递,可正常显示无报错。
方法2:修改函数,显式控制字符串编码
在函数中对RAISE NOTICE的字符串进行编码转换,确保后台会话输出的字节符合当前客户端编码要求:
create or replace function test_encoding_1() returns text language plpgsql as $$ begin -- 将字符串转换为WIN1252编码的字节串后输出 raise notice '%', convert_to('Noël', 'WIN1252'); return 'Noël'; end $$;
修改后通过pg_background调用时,RAISE NOTICE输出的是WIN1252编码的字节,当前客户端可直接正确解析。
方法3:全局配置后台会话编码(可选)
若需所有pg_background会话默认使用WIN1252编码,可修改PostgreSQL的postgresql.conf,添加或调整:
client_encoding = 'WIN1252'
修改后需重启PostgreSQL服务。此方法会影响所有会话的默认编码,需根据实际场景评估是否适用。
内容的提问来源于stack exchange,提问作者Joël Hecht
相关产品推荐
相关产品推荐

