【问题标题】:Error "relation does not exist" in PostgreSQL function()PostgreSQL 函数()中的错误“关系不存在”
【发布时间】:2019-06-26 10:40:49
【问题描述】:

函数定义:

CREATE OR REPLACE FUNCTION len_chars(t_name VARCHAR, f_name VARCHAR) RETURNS BIGINT AS $$ 
BEGIN 
  SELECT sum(char_length(f_name)) FROM t_name; 
END; 
$$ LANGUAGE plpgsql;

从 psql 调用它

SELECT len_chars('public.tag', 'name');

对于表“标签”和列“名称”返回错误:

psql: ERROR:  relation "t_name" does not exist
LINE 1: SELECT sum(char_length(f_name)) FROM t_name
                                             ^
QUERY:  SELECT sum(char_length(f_name)) FROM t_name
CONTEXT:  PL/pgSQL function len_chars(character varying,character varying) line 1 at SQL statement

是否可以在 postgresql 函数中选择表名?

【问题讨论】:

标签: sql postgresql function plpgsql dynamic-sql


【解决方案1】:

为此,您需要动态 SQL。并且要安全地构造动态 SQL 字符串,最好的方法是使用 format() 函数和 %I 占位符,以便在需要时正确处理引用标识符。

CREATE OR REPLACE FUNCTION len_chars(t_name VARCHAR, f_name VARCHAR) 
  RETURNS BIGINT AS $$ 
declare
  l_result bigint;  
BEGIN 
  execute format('SELECT sum(char_length(%I)) FROM %I', f_name, t_name)
    into l_result;
  return l_result; 
END; 
$$ LANGUAGE plpgsql;

【讨论】:

  • 我建议使用 %S 而不是 %I。 在我的例子中,%I 将参数值用双引号括起来。即SELECT sum(char_length("name")) FROM "public.tag" 并且对于t_name 仍然出现相同的错误。而%S 将参数值格式化为字符串。即SELECT sum(char_length(name)) FROM public.tag.
  • @srp:好吧,您不应该将架构和表名作为单个参数传递。最好将它们作为两个参数传递,然后使用from %I.%I 确保正确引用两个名称
  • 你说得对,最好分开传。但我想知道%I 在您的情况下如何为t_name 传递public.tag 值,因为它在我的情况下会出错。
  • 它假定public.tag 是一个包含.单个(表)名称,并且因为. 在标识符中是非法的(它只允许作为分隔符),则需要引用整个表达式:"public.tag" - 但显然您没有具有该名称的表。如果你通过public tagpublic&tag 也是一样的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 2014-12-25
  • 1970-01-01
  • 2021-09-21
相关资源
最近更新 更多