“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 命令。仅限 INSERTUPDATEDELETESELECT。 (嗯,技术上也是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' 处或附近的语法错误”

在“PARALLEL”处或附近创建 postgis 扩展语法错误

Postgresql:“-”处或附近的语法错误

错误:“用户”处或附近的语法错误

postgresql 错误:“返回”处或附近的语法错误

错误:“修改”处或附近的语法错误 - 在 postgres