You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redshift存储过程中如何处理Cedilla分隔符的COPY/UNLOAD命令

Redshift存储过程中使用八进制转义分隔符\307的问题

问题背景

直接执行的UNLOAD语句能正常工作,指定的分隔符是Ç字符(用八进制转义\307表示):

unload('select * from table') to 's3://path'
credentials '*******'
header
parallel off
delimiter as '\307'

但把这段逻辑写成Redshift存储过程后,执行时抛出错误:BAD UTF8 hex sequence: C7 27 (error 4)。存储过程代码如下:

create or replace procedure unload_table(in path varchar)
as 
$$
begin
execute
'unload(''select * from table'') to ''||path||''
    credentials '*******'
    header
    parallel off
    delimiter as ''\307'';';
end;
$$ language plpgsql;

调用命令:

call unload_table('s3://path')

换成竖线|做分隔符时存储过程能正常跑,但业务必须用\307;直接写Ç字符会报错COPY delimiter must be a single one-byte character,之前用COPY命令时也碰到过同样问题,没法事后替换分隔符解决。

解决办法

问题核心是PL/pgSQL动态SQL的转义规则和直接执行SQL不同,这里提供两种可行方案:

方案1:双重转义八进制字符

在动态SQL字符串里,把\307改成\\307,同时修正原代码里路径拼接的引号错误(原写法会把||path||当成字符串的一部分,而不是变量拼接):

create or replace procedure unload_table(in path varchar)
as 
$$
begin
execute
'unload(''select * from table'') to ''' || path || '''
    credentials ''*******''
    header
    parallel off
    delimiter as ''\\307'';';
end;
$$ language plpgsql;

原理:PL/pgSQL解析动态字符串时,会先把\\转成单个\,最终生成的执行语句里分隔符部分就是'\307',和直接执行的语句完全一致。

方案2:用CHR()函数构造分隔符

利用Redshift内置的CHR()函数,通过ASCII码(Ç的ASCII码是199,对应八进制307)直接生成目标字符,搭配format()函数自动处理字符串转义和引号,彻底避开转义问题:

create or replace procedure unload_table(in path varchar)
as 
$$
begin
execute format(
'unload(''select * from table'') to %L
    credentials %L
    header
    parallel off
    delimiter as %L;',
path, '*******', CHR(199)
);
end;
$$ language plpgsql;

原理:%L是format()函数的占位符,会自动为字符串添加单引号并处理内部转义;CHR(199)生成的是单字节的Ç字符,符合Redshift对分隔符的要求。

注意事项

  • 确认执行存储过程的会话字符集支持单字节ASCII,避免UTF-8环境下的字符解析异常
  • 可以先执行SELECT CHR(199);验证生成的字符是否正确

内容的提问来源于stack exchange,提问作者Rikky Bhai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 14:18:26