Oracle 通过多个 DBLinks 进行 charset 转换合并

Oracle merge with charset conversion through multiple DBLinks

Objective: 我想从位于 DBLINK1TABLE_X 加载数据到位于 DBLINK2TABLE_Y

我还需要处理不同的字符集,所以我使用oracle CONVERT函数和TRANSLATE函数来替换重音字符。

简化的 MERGE 命令如下所示:

MERGE INTO TABLE_Y@DBLINK2 TABLE_ACTUAL
USING(SELECT ID,
             TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME
        FROM TABLE_X@DBLINK1) TABLE_NEW
   ON (TABLE_ACTUAL.ID = TABLE_NEW.ID)
WHEN MATCHED THEN
  UPDATE SET NAME = TABLE_NEW.NAME
WHEN NOT MATCHED THEN
  INSERT (ID, NAME) VALUES(TABLE_NEW.ID, TABLE_NEW.NAME);

此命令运行没有问题,但是当我查看 TABLE_Y@DBLINK2.

时,NAME 列中的值未转换或翻译

当我使用如下所示的稍微不同的方法时,CONVERTTRANSLATE 操作成功完成。

DECLARE
  CURSOR CUR_TABLE IS
    SELECT ID,
           TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME
      FROM TABLE_X@DBLINK1;

BEGIN
  FOR REG_TABLE IN CUR_TABLE LOOP  
    BEGIN
      INSERT INTO TABLE_Y@DBLINK2(ID, NAME)
      VALUES(REG_TABLE.ID, REG_TABLE.NAME);

      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          UPDATE TABLE_Y@DBLINK2
            SET NAME = REG_TABLE.NAME
          WHERE ID = REG_TABLE.ID;
     END;
   END LOOP;
END;

第二种方法的问题在于,与合并命令相比,它的执行时间更长。

问题: 是否有关于为什么 CONVERTTRANSLATE 函数在与 MERGE 一起使用时不起作用的原因?命令?

附加信息:

CURRENT DB: Oracle 10
DBLINK2 (destination): Oracle 12
DBLINK1 (origin): Unknown version

更新: 正如@Kacper 建议的那样,我尝试使用 DRIVING_SITE 提示强制 oracle 计算本地数据库上的表达式。

最终的工作解决方案:

MERGE INTO TABLE_Y@DBLINK2 TABLE_ACTUAL
USING(SELECT /*+DRIVING_SITE(DUAL)*/ 
             ID,
             TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME
        FROM TABLE_X@DBLINK1, 
             DUAL
        WHERE ID > 0) TABLE_NEW
   ON (TABLE_ACTUAL.ID = TABLE_NEW.ID)
WHEN MATCHED THEN
  UPDATE SET NAME = TABLE_NEW.NAME
WHEN NOT MATCHED THEN
  INSERT (ID, NAME) VALUES(TABLE_NEW.ID, TABLE_NEW.NAME);

奇怪的是,只有在我在源 SELECT.

上放置一个虚拟 where 子句 (ID > 0) 后,它才完全起作用

据我所知,方法 2 的区别在于您将数据从 DBLINK1 提取到本地数据库,在本地数据库上进行转换,然后将转换后的数据插入到 DBLINK2。方法 1 将在 DBLINK1DBLINK2 上进行翻译,您可以尝试通过 DRIVING_SITE 提示来控制它。

我不确定它是否有帮助,但我会尝试 create view db1_v as SELECT ID, TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME FROM TABLE_X@DBLINK1 然后使用视图合并。

在最坏的情况下,如果这没有帮助 create table t1 as SELECT ID, TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME FROM TABLE_X@DBLINK1 并使用新的 table 进行合并。