2016-10-27 6 views
1

Цель: Я хочу, чтобы загрузить данные из TABLE_X, расположенных в DBLINK1 в TABLE_Y находится в DBLINK2.Oracle слияния с преобразованием кодировки через несколько DBLinks

Мне также нужно обрабатывать разные кодировки, поэтому я использую функцию oracle CONVERT и функцию TRANSLATE для замены акцентированных символов.

Упрощенная MERGE команда будет выглядеть следующим образом:

MERGE INTO [email protected] TABLE_ACTUAL 
USING(SELECT ID, 
      TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME 
     FROM [email protected]) 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); 

Эта команда работает без вопроса, но значения в столбце NAME не конвертируются и не переводятся, когда я смотрю в [email protected].

Когда я использую несколько иной подход, как показано ниже, операции CONVERT и TRANSLATE выполнены успешно.

DECLARE 
    CURSOR CUR_TABLE IS 
    SELECT ID, 
      TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME 
     FROM [email protected]; 

BEGIN 
    FOR REG_TABLE IN CUR_TABLE LOOP 
    BEGIN 
     INSERT INTO [email protected](ID, NAME) 
     VALUES(REG_TABLE.ID, REG_TABLE.NAME); 

     EXCEPTION 
     WHEN DUP_VAL_ON_INDEX THEN 
      UPDATE [email protected] 
      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 

Update: Как предложил @Kacper, я попытался с помощью DRIVING_SITE намек, чтобы заставить оракул оценить выражения в локальной базе данных.

Окончательный рабочий раствор:

MERGE INTO [email protected] TABLE_ACTUAL 
USING(SELECT /*+DRIVING_SITE(DUAL)*/ 
      ID, 
      TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME 
     FROM [email protected], 
      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); 

достаточно Жутко, он только полностью работал после того, как я поставил манекен, где положение (ID > 0) на источник SELECT.

ответ

1

Что я понимаю, разница в подходе 2 вы извлекаете данные из DBLINK1 в локальную базу данных, выполняете преобразование в локальной базе данных, а затем вставляете преобразованные данные в DBLINK2. Подход 1 будет делать переводчик на DBLINK1 или DBLINK2, вы можете попытаться его контролировать DRIVING_SITE намек.

Я не уверен, если он поможет, но я бы попробовал create view db1_v as SELECT ID, TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME FROM [email protected], а затем объединил с использованием вида.

В худшем случае, если это не помогает create table t1 as SELECT ID, TRANSLATE(CONVERT(NAME, 'WE8PC850', 'WE8ISO8859P1'), 'Ã', 'A') NAME FROM [email protected] и используйте новую таблицу для слияния.

+0

Подсказка DRIVING_SITE была ключом. Я обновил вопрос с окончательным решением. Благодарю. –