“TRUNCATE”处或附近的语法错误 - Aurora Postgres 10.12
Posted
技术标签:
【中文标题】“TRUNCATE”处或附近的语法错误 - Aurora Postgres 10.12【英文标题】:Syntax error at or near "TRUNCATE" - Aurora Postgres 10.12 【发布时间】:2021-05-20 23:24:04 【问题描述】:我正在尝试重构查询并删除一组窗口函数,以按原样捕获所有记录。当我去粘贴查询以替换我的函数时,pgAdmin 在“截断”语句附近指示语法错误。我只是无法弄清楚它是什么,并且可能是一些非常明显的东西,但我会欣赏另一(或许多)眼睛。
我在 Postgres 10.12 上。
这是我要插入的代码(最后包含了“之前”代码。任何建议将不胜感激。尝试了括号、逗号和分号闭包的所有类型和组合,并在斗智斗勇……
我正在尝试插入的代码
预期结果:从暂存中取出行并插入到目标中。完成后截断暂存
WITH ins_agent AS (
INSERT INTO agents (
currentagentsnapshot,
previousagentsnapshot,
agentarn,
eventid,
eventtimestamp,
eventtype,
instancearn)
SELECT
agent_stg.currentagentsnapshot::jsonb AS currentagentsnapshot,
agent_stg.previousagentsnapshot::jsonb AS previousagentsnapshot,
agent_stg.agentarn::text AS agentarn,
agent_stg.eventid::text AS eventid,
agent_stg.eventtimestamp::timestamptz AS eventtimestamp,
agent_stg.eventtype::text AS eventtype,
agent_stg.instancearn::text AS instancearn
FROM agents_staging AS agent_stg
WHERE agent_stg.agentarn IS NOT NULL)
TRUNCATE agents_staging;
我正在尝试更改的代码
预期结果:选择不同的代理并捕获他们最近的快照。将 agent_id 插入另一个表。考虑 upserts。
更改原因:除了需要对数百万条记录进行查询之外,它几乎没有任何价值,因为它会丢弃所有代理快照,因为它们是不同的,除了它们的最新快照。不是我们想要的。
WITH ins_agent AS (INSERT INTO agents (currentagentsnapshot,
previousagentsnapshot,
agentarn,
eventid,
eventtimestamp,
eventtype,
instancearn)
SELECT DISTINCT LAST_VALUE(currentagentsnapshot::jsonb)
OVER (PARTITION BY agentarn ORDER BY lat.eventtimestamp DESC ) AS previousagentsnapshot,
LAST_VALUE(previousagentsnapshot::jsonb)
OVER (PARTITION BY agentarn ORDER BY lat.eventtimestamp DESC ) AS previousagentsnapshot,
agentarn,
LAST_VALUE(eventid)
OVER (PARTITION BY agentarn ORDER BY lat.eventtimestamp DESC) AS eventid,
LAST_VALUE(lat.eventtimestamp)
OVER (PARTITION BY agentarn ORDER BY lat.eventtimestamp DESC) AS eventtimestamp,
LAST_VALUE(eventtype)
OVER (PARTITION BY agentarn ORDER BY lat.eventtimestamp DESC) AS eventtype,
LAST_VALUE(instancearn)
OVER (PARTITION BY agentarn ORDER BY lat.eventtimestamp DESC) AS instancearn
FROM agents_staging AS agent
CROSS JOIN LATERAL (SELECT agent.eventtimestamp::timestamp AS eventtimestamp) AS lat
WHERE NOT (
agent.agentarn IS NULL
OR agent.currentagentsnapshot IS NULL
OR agent.currentagentsnapshot = '')
ON CONFLICT (agentarn)
DO NOTHING
RETURNING agentarn, agent_id)
UPDATE contact_trace_records
SET agent_id=ins_agent.agent_id
FROM ins_agent
WHERE contact_trace_records.agent_id IS NULL
AND ins_agent.agentarn = contact_trace_records.agent ->> 'ARN';
TRUNCATE agents_staging;
【问题讨论】:
不确定 Aurora 语法是否与普通 PostgreSql 不同,但它是否像在WHERE agent_stg.agentarn IS NOT NULL)
之后在 TRUNCATE
之前使用括号而不是分号一样简单?
@mdisibio - 这是令人沮丧的事情。所以括号是用来关闭行首的 with 子句的。然后我在结尾加上一个分号。这引发了一个错误。试图在“where”之后用分号截断并引发错误。甚至试图不关闭“with”,但这也会引发错误。呃……
【参考方案1】:
语法错误是 CTE 不能附加到 TRUNCATE
命令。仅限 INSERT
、UPDATE
、DELETE
或 SELECT
。 (嗯,技术上也是TABLE
,但这只是SELECT * FROM
的简短语法。)
删除WITH
子句,并运行两个单独的命令。
INSERT INTO agents (
currentagentsnapshot,
previousagentsnapshot,
agentarn,
eventid,
eventtimestamp,
eventtype,
instancearn)
SELECT
agent_stg.currentagentsnapshot::jsonb AS currentagentsnapshot,
agent_stg.previousagentsnapshot::jsonb AS previousagentsnapshot,
agent_stg.agentarn::text AS agentarn,
agent_stg.eventid::text AS eventid,
agent_stg.eventtimestamp::timestamptz AS eventtimestamp,
agent_stg.eventtype::text AS eventtype,
agent_stg.instancearn::text AS instancearn
FROM agents_staging AS agent_stg
WHERE agent_stg.agentarn IS NOT NULL;
TRUNCATE agents_staging;
如果您需要防御竞争条件,请将整个操作包装在一个事务中,并首先对表进行写锁定:
BEGIN;
LOCK TABLE agents_staging;
INSERT ...;
TRUNCATE agents_staging;
COMMIT;
除此之外:外部SELECT
中的表别名在INSERT
命令中什么都不做。这些充其量只是文档。但是由于所有列都已经有了最终的名称,所以这实际上只是噪音。
如果源列具有兼容的数据类型(隐式或赋值转换为目标类型,而不是显式转换),您可能也不需要表限定或显式转换。看起来两个表都具有相同的数据类型?然后您可以在很大程度上简化为:
INSERT INTO agents
(currentagentsnapshot, previousagentsnapshot, agentarn, eventid, eventtimestamp, eventtype, instancearn)
SELECT currentagentsnapshot, previousagentsnapshot, agentarn, eventid, eventtimestamp, eventtype, instancearn
FROM agents_staging
WHERE agentarn IS NOT NULL;
【讨论】:
感谢您的修复和建议。注意到别名。本能,我猜,但很高兴知道它不是必需的。显式转换是因为临时表将其作为文本获取,因为 Glue 无法通过 jdbc 传输 jsonb。 不确定您指的是关于竞争条件的内容,但不想将其包装为单独的事务,因为在提交之前还有 3 个其他表属于同一函数。代理阶段和其他阶段是异步加载的,因此该函数作为日志表上触发器的一部分,当数据到达任一阶段表时将被写入。再次,非常感谢 @sandeepmohan:竞争条件示例:并发事务将任何行更改为agents_staging
之后您的INSERT
开始。然后TRUNCATE
首先被阻塞,直到该事务完成,然后更改丢失。但是表名agents_staging
表示没有其他人写入该表...以上是关于“TRUNCATE”处或附近的语法错误 - Aurora Postgres 10.12的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL 中的“'order' 处或附近的语法错误”