调用函数时在“(”或附近的语法错误

时间:2019-08-05 04:55:05

标签: sql postgresql postgresql-9.1 postgresql-9.5

运行此代码时,出现以下错误:

  

错误:“(”;或附近的语法错误   执行查询时出错(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();

2 个答案:

答案 0 :(得分:2)

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

INTERVAL "18 hour"
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;

开始时不需要recordtext可以做到。更好的方法是,对表名使用类型regclass,因为这样会在需要时自动添加架构名称。否则,在多个模式中使用的表名可能会出现严重错误。

要1次使用(如悬挂的DROP FUNCTION所示),请考虑使用DO语句而不是函数:

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

   ...

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

答案 1 :(得分:1)

代码中存在三个错误:

  • 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;