运行此代码时,出现以下错误:
错误:“(”;或附近的语法错误 执行查询时出错(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();
答案 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;
开始时不需要record
。 text
可以做到。更好的方法是,对表名使用类型regclass
,因为这样会在需要时自动添加架构名称。否则,在多个模式中使用的表名可能会出现严重错误。
要1次使用(如悬挂的DROP FUNCTION
所示),请考虑使用DO
语句而不是函数:
DO
$do$
DECLARE
_tbl regclass;
_ct int := 0;
BEGIN
...
RAISE NOTICE '% tables updated.', _ct;
END
$do$;
答案 1 :(得分:1)
代码中存在三个错误:
i
是RECORD
,即整行结果。将其连接为字符串会隐式将(
)
放在字符串周围,从而产生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;