通过Dblink向远程数据库插入数据时INTERVAL语法报错问题
错误原因
- 语法顺序错误:PostgreSQL中时间间隔常量的标准写法为
INTERVAL '时间值',原语句将时间值字符串放在INTERVAL关键字前,不符合语法规则。 - 单引号未转义:传给dblink的远程SQL本身是外层SQL的字符串参数,字符串内部的单引号需要用两个连续单引号
''转义,否则外层解析器会误判字符串结束位置,把后续内容识别为外层SQL的语法片段触发报错。这也是加了时间条件后才报错、无筛选条件时语句正常运行的核心原因。
修正后完整SQL(普通单引号写法)
INSERT INTO tc_new_events SELECT * FROM dblink ( 'dev_connec', 'SELECT id,type,eventtime,deviceid,positionid,geofenceid,attributes,maintenanceid FROM tc_events WHERE eventTime < NOW() - INTERVAL ''30 days''' ) AS DATA ( id int, type varchar, eventtime timestamp without time zone, deviceid integer, positionid integer, geofenceid integer, attributes varchar, maintenanceid integer );
可选优化写法(美元引用,无需转义单引号)
如果觉得单引号转义容易出错,可以用PostgreSQL支持的美元引用语法包裹远程查询字符串,内部的单引号不需要额外转义,可读性更高:
INSERT INTO tc_new_events SELECT * FROM dblink ( 'dev_connec', $remote$ SELECT id,type,eventtime,deviceid,positionid,geofenceid,attributes,maintenanceid FROM tc_events WHERE eventTime < NOW() - INTERVAL '30 days' $remote$ ) AS DATA ( id int, type varchar, eventtime timestamp without time zone, deviceid integer, positionid integer, geofenceid integer, attributes varchar, maintenanceid integer );
注意事项
- 上述写法筛选的是
eventTime早于「当前时间往前推30天」的历史数据,如果你的需求是筛选最近30天内的数据,需要将<改为>=。 - 所有写在dblink参数内的远程SQL,只要包含字符串值,用普通单引号包裹时都需要做双写转义,否则会触发同类语法错误。
内容的提问来源于stack exchange,提问作者Aakansha
相关产品推荐
相关产品推荐

