【问题标题】:Syntax error at or near "(" while calling function调用函数时“(”或附近的语法错误
【发布时间】:2019-08-05 04:55:05
【问题描述】:

运行此代码时,我收到以下错误:

错误:“(”处或附近的语法错误;
执行查询时出错(7)

代码:

CREATE OR REPLACE FUNCTION obs_updated_date() RETURNS INTEGER AS $$
DECLARE
  i RECORD;
BEGIN
  FOR i IN
    (SELECT r FROM pg_class
      WHERE r LIKE 'abc%1')
  LOOP
    EXECUTE 'update' || i || 'SET observation_time = xyz + INTERVAL"18 hour"';
  END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;

SELECT obs_updated_date();
DROP FUNCTION obs_updated_date();

【问题讨论】:

  • 更新子句中缺少空格,请使用:EXECUTE 'update ' || i || ' SET ...
  • 我做到了。但它仍然显示相同的错误。
  • 是同样的错误:错误:“(”或附近的语法错误;执行查询时出错(7)
  • 对此感到抱歉。错误消息是编辑一。确认错误是 ERROR: syntax error at or near "("; error while execution the query(7)
  • 为什么选择 Postgres 9.1 9.5?

标签: sql postgresql postgresql-9.1 postgresql-9.5


【解决方案1】:

主要错误是双引号,您需要单引号作为文字值:

<strike>INTERVAL "18 hour"</strike>
INTERVAL '18 hour'

但由于它嵌套在带引号的字符串中,我建议使用外部美元引号:

 EXECUTE 'update' || i || $u$SET observation_time = date_added + INTERVAL '18 hour'$u$;

相关:

更好的是,使用 format() 正确引用表名:

 EXECUTE format ($u$UPDATE %I SET observation_time = date_added + INTERVAL '18 hour'$u$, i);

而且您不能像以前那样使用record 变量。还有一些改进,结果是:

CREATE OR REPLACE FUNCTION obs_updated_date()
  RETURNS int AS
$func$
DECLARE
   _tbl regclass;
   _ct  int := 0;
BEGIN
   FOR _tbl IN
      SELECT oid
      FROM   pg_class
      WHERE  relname LIKE 'traffic%1'
      AND    relkind = 'r'   -- only actual tables
      AND    relnamespace::regnamespace::text NOT LIKE 'pg_%' -- no system tables
   LOOP
      EXECUTE format ($u$UPDATE %I SET observation_time = date_added + interval '18 hour'$u$, _tbl);
      _ct := _ct + 1;
   END LOOP;
   RETURN _ct;  -- return sth useful: the number of affected tables
END
$func$  LANGUAGE plpgsql;

您不需要 record 开始。 text 会这样做。更好的是,使用regclass 类型作为表名,因为这会在需要的地方自动添加模式名称。否则,对于在多个模式中使用的表名,这可能会出现严重错误。

一次性使用(如悬空的DROP FUNCTION 所示)考虑使用DO 语句而不是函数:

DO
$do$
DECLARE
   _tbl regclass;
   _ct  int := 0;
BEGIN

   ...

   RAISE NOTICE '% tables updated.', _ct;
END
$do$;

【讨论】:

  • 您也不能像以前那样使用record 变量。
【解决方案2】:

代码中存在三个错误:

  • iRECORD,即一整行结果。将它连接到一个字符串会隐式地将( ) 放在它周围,从而产生update(trafficfoo1)SET ...。这就是导致语法错误的原因。您需要使用i.relname 或将i 声明为TEXT

  • 生成的字符串中i 周围缺少空格。

  • "18 hour" 使用了错误的引号。双引号用于标识符,而不是字符串。 '18 hour'(单引号)可以工作,但在单引号字符串的上下文中,' 需要转义为 '',得到 ''18 hour''

工作版本:

CREATE OR REPLACE FUNCTION obs_updated_date() RETURNS INTEGER AS $$
DECLARE
  i TEXT;
--  ^^^^
BEGIN
  FOR i IN
    SELECT relname FROM pg_class
      WHERE relname LIKE 'traffic%1'
  LOOP
    execute 'update ' || i || ' SET observation_time = date_added + INTERVAL''18 hour''';
--                 ^           ^                                            ^^       ^^
  END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;

【讨论】:

    猜你喜欢
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 2018-01-26
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多