Oracle 通过多个 DBLinks 进行 charset 转换合并
Oracle merge with charset conversion through multiple DBLinks
Objective:
我想从位于 DBLINK1
的 TABLE_X
加载数据到位于 DBLINK2
的 TABLE_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
列中的值未转换或翻译
当我使用如下所示的稍微不同的方法时,CONVERT
和 TRANSLATE
操作成功完成。
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;
第二种方法的问题在于,与合并命令相比,它的执行时间更长。
问题: 是否有关于为什么 CONVERT
和 TRANSLATE
函数在与 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 将在 DBLINK1
或 DBLINK2
上进行翻译,您可以尝试通过 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 进行合并。
Objective:
我想从位于 DBLINK1
的 TABLE_X
加载数据到位于 DBLINK2
的 TABLE_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
列中的值未转换或翻译
当我使用如下所示的稍微不同的方法时,CONVERT
和 TRANSLATE
操作成功完成。
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;
第二种方法的问题在于,与合并命令相比,它的执行时间更长。
问题: 是否有关于为什么 CONVERT
和 TRANSLATE
函数在与 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
.
ID > 0
) 后,它才完全起作用
据我所知,方法 2 的区别在于您将数据从 DBLINK1
提取到本地数据库,在本地数据库上进行转换,然后将转换后的数据插入到 DBLINK2
。方法 1 将在 DBLINK1
或 DBLINK2
上进行翻译,您可以尝试通过 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 进行合并。