具有动态表名的过程中“20231002”处或附近的语法错误

Syntax error at or near ""20231002"" in procedure with dynamic table name

提问人:ogkush 提问时间:10/31/2023 最后编辑:Erwin Brandstetterogkush 更新时间:10/31/2023 访问量:40

问:

我想创建可以创建具有动态表名称的表的过程。它采用日期、格式并将其附加到表名中。

我做了什么:

CREATE OR REPLACE PROCEDURE l2.accounts_balances_load(var_balancedate date)
 LANGUAGE plpgsql
AS $procedure$
declare var_balancedate_ int = to_char(var_balancedate, 'YYYYMMDD') ;  
begin

raise notice 'SQL:: %', var_balancedate_;

execute format ('create table if not exists l2.accounts_balances_%I partition of l2.accounts_balances', var_balancedate_);

end;
$procedure$
;   

我打电话说:

call l2.accounts_balances_load('2023-10-02');

但是我收到错误:

SQL Error [42601]: ERROR: syntax error at or near ""20231002""
Где: PL/pgSQL function l2.accounts_balances_load(date) line 9 at EXECUTE

我做错了什么?

PostgreSQL PLPGSQL 过程 动态 SQL 标识符

评论

0赞 Erwin Brandstetter 11/1/2023
那么你有答案吗?

答:

1赞 Erwin Brandstetter 10/31/2023 #1

在这种情况下,format() 需要格式说明符 %s 而不是 %I。喜欢:

CREATE OR REPLACE PROCEDURE l2.accounts_balances_load(var_balancedate date)
  LANGUAGE plpgsql AS
$proc$
DECLARE
   var_balancedate_ text := to_char(var_balancedate, 'YYYYMMDD');
BEGIN
   RAISE NOTICE 'SQL:: %', var_balancedate_;

   EXECUTE format(
      'CREATE TABLE IF NOT EXISTS l2.accounts_balances_%s
       PARTITION OF l2.accounts_balances', var_balancedate_);
END
$proc$;

此外,强制格式化的日期来回也没有意义。我做到了.var_balancedate_inttext

说明符将输入视为标识符,如果字符串无效,则用双引号括起来。一串数字用双引号引起来。随后的串联使名称成为非法名称。%I

现在,您的表名是一个标识符,但您只是附加了数字。您必须用双引号括住整个名称。由于被赋值了 的结果,我们知道字符串是安全的,所以不可能注入 SQL,也没问题。
否则,您将连接整个表名,并将其与要引用的说明符一起传递。
var_balancedate_to_char()%s%I

相关: