ora_rowscn 在 USING 子句中时的 Oracle 合并语句行为

Posted

技术标签:

【中文标题】ora_rowscn 在 USING 子句中时的 Oracle 合并语句行为【英文标题】:Oracle Merge Statement Behavior when ora_rowscn is in USING clause 【发布时间】:2012-02-17 16:39:02 【问题描述】:

我有一个 MERGE 语句,它给了我可怕的 ORA-00904: invalid identifier 错误消息。请注意,此处不存在“无效标识符”错误的典型问题 - 我没有尝试更新连接的列,也没有拼错列名。我试图在USING 子句的SELECT 语句中使用oracle 伪列ORA_ROWSCN

使用这些示例表,我尝试运行

MERGE INTO MY_MERGE_TABLE D
  USING
 (SELECT PRIMARY_KEY, 
         COALESCE (UPDATE_DT, CREATED_DT) update_dt,
         ORA_ROWSCN AS rowscn 
    FROM MY_SOURCE_TABLE) S
   ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
     UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt),
                D.rowscn = GREATEST(D.rowscn, S.rowscn)
WHEN NOT MATCHED THEN
     INSERT (D.PRIMARY_KEY, D.UPDATE_DT, D.ROWSCN)
     VALUES (S.PRIMARY_KEY, S.UPDATE_DT, S.ROWSCN);

如果我从 USING 子句中删除伪列 ora_rowscn,我将不再收到错误消息,并且合并成功完成。

MERGE INTO MY_MERGE_TABLE D
  USING
 (SELECT PRIMARY_KEY, 
         COALESCE (UPDATE_DT, CREATED_DT) update_dt
    FROM MY_SOURCE_TABLE) S
   ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
     UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt)
WHEN NOT MATCHED THEN
     INSERT (D.PRIMARY_KEY, D.UPDATE_DT)
     VALUES (S.PRIMARY_KEY, S.UPDATE_DT);

如果我改为将查询放入 VIEW 中,则可以成功使用 ora_rowscn:

CREATE VIEW MY_VIEW AS 
    SELECT PRIMARY_KEY, 
         COALESCE (UPDATE_DT, CREATED_DT) update_dt,
         ORA_ROWSCN AS rowscn 
    FROM MY_SOURCE_TABLE;

MERGE INTO MY_MERGE_TABLE D
  USING (SELECT PRIMARY_KEY, UPDATE_DT, ROWSCN FROM MY_VIEW) S
   ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
     UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt),
                D.rowscn = GREATEST(D.rowscn, S.rowscn)
WHEN NOT MATCHED THEN
     INSERT (D.PRIMARY_KEY, D.UPDATE_DT, D.ROWSCN)
     VALUES (S.PRIMARY_KEY, S.UPDATE_DT, S.ROWSCN);

有没有办法在不为查询创建视图的情况下做到这一点?作为 ETL 过程的一部分,我必须在许多表上执行此操作,并且不希望构建多个视图。

编辑: 根据格伦在 cmets 中的建议,我尝试将查询放入子查询中:

MERGE INTO MY_MERGE_TABLE D
  USING
 (WITH QRY AS 
  (SELECT PRIMARY_KEY, 
         COALESCE (UPDATE_DT, CREATED_DT) update_dt,
         ORA_ROWSCN AS rowscn 
    FROM MY_SOURCE_TABLE)
  SELECT ORDER_ID, UPDATE_DT, ROWSCN FROM QRY)
 ON (D.PRIMARY_KEY = S.PRIMARY_KEY)
WHEN MATCHED THEN
     UPDATE SET D.update_dt = GREATEST(D.update_dt, S.update_dt),
                D.rowscn = GREATEST(D.rowscn, S.rowscn)
WHEN NOT MATCHED THEN
     INSERT (D.PRIMARY_KEY, D.UPDATE_DT, D.ROWSCN)
     VALUES (S.PRIMARY_KEY, S.UPDATE_DT, S.ROWSCN);

此查询仍然给我ORA-00904: invalid identifier 错误消息。

这里是重新创建问题的 DDL。

CREATE TABLE MY_SOURCE_TABLE (
  PRIMARY_KEY NUMBER,
  CREATED_DT TIMESTAMP(6),
  UPDATED_DT TIMESTAMP(6)
);

CREATE TABLE MY_MERGE_TABLE (
  PRIMARY_KEY NUMBER,
  UPDATED_DT TIMESTAMP(6),
  ROWSCN NUMBER
);

INSERT INTO MY_SOURCE_TABLE (PRIMARY_KEY, CREATED_DT, UPDATED_DT)
VALUES (1, SYSDATE-2, SYSDATE);

INSERT INTO MY_SOURCE_TABLE (PRIMARY_KEY, CREATED_DT, UPDATED_DT)
VALUES (2, SYSDATE-1, NULL);

INSERT INTO MY_SOURCE_TABLE (PRIMARY_KEY, CREATED_DT, UPDATED_DT)
VALUES (3, SYSDATE-1, SYSDATE+1);

INSERT INTO MY_MERGE_TABLE (PRIMARY_KEY, UPDATED_DT, ROWSCN)
VALUES (1, SYSDATE-2, 0);

INSERT INTO MY_MERGE_TABLE (PRIMARY_KEY, UPDATED_DT, ROWSCN)
VALUES (2, SYSDATE-1, 0);

【问题讨论】:

合并语句在 11.2.0.1 上对我来说很好用。您可能需要发布 DDL 和一些示例数据。 您能否在“使用”选择子句中使用子查询分解,如该问题的已接受答案:***.com/questions/6673806/… @jonearles - 当您在 SELECT 语句中使用伪列 ORA_ROWSCN 作为 USING 子句的一部分时,合并语句是否适合您?没有它,我一直使用合并,这很好。这是我遇到问题的具体案例。 @Glenn - 我尝试将语句包装在 WITH 子句中,也只是一个子查询,它仍然给出 Invalid Identifier 错误消息。我将更新问题以反映我尝试过。 我创建了具有相同名称和列的表并运行完全相同的 SQL 语句而没有错误。 【参考方案1】:

我运行了你的 SQL 并得到了同样的错误(在 11.2.0.1 上)。然后我尝试运行选择

SELECT PRIMARY_KEY, 
         COALESCE (UPDATE_DT, CREATED_DT) update_dt,
         ORA_ROWSCN AS rowscn 
    FROM MY_SOURCE_TABLE;

仍然出现ORA-00904: "UPDATE_DT": invalid identifier 错误。然后我注意到在您的 DDL 中,MY_SOURCE_TABLE 上的列称为UPDATED_DT(即带有一个额外的D 字符)。在您的 MERGE 声明中更改对它的引用使其对我有用,希望对您有所帮助。

【讨论】:

以上是关于ora_rowscn 在 USING 子句中时的 Oracle 合并语句行为的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 N 查询的“USING”子句的雄辩连接

在 Oracle Merge 语句的 Using 子句中指定参数

SQL 异常在嵌套查询中使用“USING”子句?

using 子句会关闭此流吗?

Oracle ora_rowscn 何时换行

选择描述字段而不将其包含在 GROUP BY 子句中时 GROUP BY id 的最佳方法