【问题标题】:"missing FROM-clause entry" in PLPGSQL function to update a tablePLPGSQL 函数中的“缺少 FROM 子句条目”以更新表
【发布时间】:2021-06-21 04:16:57
【问题描述】:

我正在尝试更新 Postgres 中的表,但出现以下错误。
Userid 是主键。

CREATE OR REPLACE FUNCTION public.update_user(username character varying, 
                                                userid character varying, 
                                                roleid integer,
                                                deptid integer, 
                                                status integer)
RETURNS integer AS 
$$
BEGIN

UPDATE public."M_User" SET public."M_User".user_name = public.update_user.username, 
    public."M_User".user_role_id = public.update_user.roleid, 
    public."M_User".dept_id = public.update_user.deptid, 
    public."M_User".status = public.update_user.status 
    WHERE public."M_User".user_id = userid;
    
RETURN 0;
END
$$
LANGUAGE 'plpgsql';

呼叫:

SELECT * FROM public.update_user ('ji','gis', 123, 24, 1);

错误:

ERROR:  missing FROM-clause entry for table "update_user"
LINE 1: ...E public."M_User" SET public."M_User".user_name = public.upd...
                                                             ^
QUERY:  UPDATE public."M_User" SET public."M_User".user_name = public.update_user.username, 
  public."M_User".user_role_id = public.update_user.roleid, 
  public."M_User".dept_id = public.update_user.deptid, 
  public."M_User".status = public.update_user.status 
  WHERE public."M_User".user_id = userid
CONTEXT:  PL/pgSQL function update_user(character varying,character varying,integer,integer,integer) line 4 at SQL

声明 SQL 状态:42P01

如何解决问题?

【问题讨论】:

    标签: postgresql sql-update plpgsql


    【解决方案1】:
    CREATE OR REPLACE FUNCTION public.update_user(_username varchar, 
                                                    _userid varchar, 
                                                    _roleid integer,
                                                    _deptid integer, 
                                                    _status integer)
      RETURNS integer
      LANGUAGE sql AS 
    $func$
    UPDATE public."M_User" u
    SET    user_name    = _username
         , user_role_id = _roleid
         , dept_id      = _deptid
         , status       = _status 
    WHERE  u.user_id = _userid
    AND   (u.user_name, u.user_role_id, u.dept_id, u.status) IS DISTINCT FROM
          ( _username ,       _roleid ,  _deptid ,  _status)  -- optional addition
    RETURNING u.user_id;
    $func$
    

    可以用函数名称限定函数参数以消除歧义,但这通常是一个尴尬的解决方案。重命名函数时中断。还有其他方法。见:

    我喜欢在参数和变量前加上下划线,从不为列名做同样的事情。不是标准的,而是普遍的惯例。养成对所有列名进行表限定的习惯,这样您就安全了。表别名有助于降低噪音。 the manual on UPDATE 中的基础知识。

    但是UPDATE 语句中的目标列不能被限定。 (它们从不模棱两可。)

    我添加了一个可选谓词来跳过 UPDATE 如果它不会改变任何东西。见:

    您不需要为此使用 PL/pgSQL。 (当然,尽管您可以。)一个更简单的 SQL 函数可以完成这项工作。见:

    RETURN 0 没有任何用处。我将其更改为返回更新行的有效user_id。 (通常与输入 _userid 相同,但它可能与触发器不同。)重要的区别:只有当行实际更新时才会获得返回值,这使得它很有用。否则,您不妨将函数声明为RETURNS void。与无条件的RETURN 0; 一样有用,但更便宜。

    【讨论】:

      【解决方案2】:

      doc 表示可以将输入引用为 function_name.parameter_name,因此请尝试删除对 schema_name 的引用

      UPDATE public."M_User" 
      SET user_name = update_user.username, 
          user_role_id = update_user.roleid, 
          dept_id = update_user.deptid, 
          status = update_user.status 
      WHERE user_id = update_user.userid;
      

      【讨论】:

      • 此外,SET column_name = column_val 必须只是列名,而不是每个UPDATE 的 table_name.column_name '...不要在目标列的规范中包含表的名称...'。所以,user_name = update_user.username.
      • @AdrianKlaver 是的,当然,感谢您的观看!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-06
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多