postgresql函数错误:列名不存在
Posted
技术标签:
【中文标题】postgresql函数错误:列名不存在【英文标题】:postgresql function error: column name does not exist 【发布时间】:2013-07-04 09:46:47 【问题描述】:我已经实现了一个函数来检查一个值是否出现在特定表的特定行中:
CREATE FUNCTION check_if_if_exist(id INTEGER, table_name character(50), table_column character(20) ) RETURNS BOOLEAN AS $$
DECLARE res BOOLEAN;
BEGIN
SELECT table_column INTO res
FROM table_name
WHERE table_column = id;
RETURN res;
END;
$$ LANGUAGE plpgsql
我已经创建并填写了一个简单的测试表来尝试这个功能:
CREATE TABLE tab(f INTEGER);
我像这样调用函数
SELECT check_if_exist(10, tab, f);
但是我出现了这个错误:
ERROR: column "prova" does not exist
LINE 1: SELECT check_if_exist(10, tab, f);
^
********** Error **********
ERROR: column "tab" does not exist
SQL state: 42703
Character: 27
为什么?
【问题讨论】:
如果您尝试将其作为“如果不存在则插入”或“更新,如果不存在则插入”类型的事情的一部分,请立即停止并阅读有关 PostgreSQL 上的 upsert 的信息。如果这不是你正在做的,也许编辑并解释你的真正目标是什么,因为很难想象这样的功能在没有更好的方法的情况下会有用。 【参考方案1】:除了 Elmo 响应之外,您还必须注意类型。你有:
ERROR: column "tab" does not exist
因为 SQL 解析器不知道如何处理没有引号的tab
。您的查询必须是这样的:
SELECT check_if_exist(10, 'tab', 'f');
正如 Elmo 回答你使用动态查询,所以即使你引用 tab
你会得到错误:
ERROR: relation "table_name" does not exist
所以你可以使用EXECUTE
,例如:
CREATE OR REPLACE FUNCTION check_if_exist(id INTEGER, table_name varchar, table_column varchar) RETURNS BOOLEAN AS $$
DECLARE
sql varchar;
cnt int;
BEGIN
sql := 'SELECT count(*) FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(table_column) || '=$1';
RAISE NOTICE 'sql %', sql;
EXECUTE sql USING id INTO cnt;
RETURN cnt > 0;
END;
$$ LANGUAGE plpgsql
您还可以在函数参数中使用VARCHAR
代替character(N)
,并使用CREATE OR REPLACE FUNCTION ...
代替CREATE FUNCTION ...
,这在调试时非常方便。
【讨论】:
请不要使用直接字符串连接显示EXECUTE
。它使函数成为 SQL 注入的向量。上面应该写成EXECUTE format('SELECT count(*) FROM %I WHERE %I = $1', table_name, table_column) USING id INTO cnt;
,或者,对于没有format
的旧PostgreSQL版本,应该在quote_ident
调用中包装表和列名。
+1 为答案,但@CraigRinger 对他的担忧是正确的,所以也为他+1。很高兴向 OP 展示如何进行动态查询和防止 SQL 注入,但我仍然说编写这个确切的函数是在重新发明***。
谢谢,我刚刚编辑了答案。当我们可以使用select exists (select * from my_table where my_column=my_value)
时,我认为这个功能不是很有用。【参考方案2】:
您的代码没有机会工作 - 在 PLPGSQL 中处理不同的表时,您需要使用动态查询,因此需要 EXECUTE
- http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
但首先 - 使用 PostgreSQL EXISTS
- http://www.postgresql.org/docs/current/static/functions-subquery.html#AEN15284 而不是自己发明并没有什么不好 - 解决方案的性能将比使用随附的电池差得多...
希望这会有所帮助。祝你好运。
【讨论】:
以上是关于postgresql函数错误:列名不存在的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?