目标:我想将数据从位于DBLINK1
的TABLE_X
加载到位于DBLINK2
的TABLE_Y
中。
我还需要处理不同的字符集,所以我使用oracleCONVERT
函数和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;
第二种方法的问题是,与merge命令相比,它的执行时间要长得多。
问题:对于CONVERT
和TRANSLATE
函数与MERGE
命令一起使用时无法工作的原因,是否有任何合理的解释?
其他信息:
CURRENT DB: Oracle 10
DBLINK2 (destination): Oracle 12
DBLINK1 (origin): Unknown version
更新:正如@Kapper建议的那样,我尝试使用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
没有帮助,则使用新表进行合并。