Как объединить две таблицы без именования всех столбцов? - PullRequest
7 голосов
/ 20 января 2012

Скажем, у меня есть эти две таблицы с одинаковыми столбцами. Используйте свое воображение, чтобы сделать их больше:

USER_COUNTERPARTY:
ID  |Name                        |Credit Rating    |Sovereign Risk    |Invoicing Type
----+----------------------------+-----------------+------------------+---------------
1   |Nat Bank of Transnistria    |7                |93                |Automatic
2   |Acme Ltd.                   |25               |12                |Automatic
3   |CowBInd LLP.                |49               |12                |Manual

TEMP:
ID  |Name                        |Credit Rating    |Sovereign Risk    |Invoicing Type
----+----------------------------+-----------------+------------------+---------------
2   |Acacacme Ltd.               |31               |12                |Manual
4   |Disenthralled Nimrod Corp.  |31               |52                |Automatic

и я хочу объединить их в одно, заменив вторым то, что имеет тот же идентификатор в первом, и вставив то, чего там нет. Я могу использовать это утверждение:

MERGE INTO USER_COUNTERPARTY C
USING TEMP T
ON (C.COUNTER_ID = T.COUNTER_ID)
WHEN MATCHED THEN UPDATE SET
    C.COUNTER_NAME = T.COUNTER_NAME,
    C.COUNTER_CREDIT = T.COUNTER_CREDIT,
    C.COUNTER_SVRN_RISK = T.COUNTER_SVRN_RISK,
    C.COUNTER_INVOICE_TYPE = T.COUNTER_INVOICE_TYPE
WHEN NOT MATCHED THEN INSERT VALUES (
    T.COUNTER_ID,
    T.COUNTER_NAME,
    T.COUNTER_CREDIT,
    T.COUNTER_SVRN_RISK,
    T.COUNTER_INVOICE_TYPE);

Что достаточно мило, но обратите внимание, что я должен назвать каждый из столбцов. Есть ли способ объединить эти таблицы, не называя все столбцы? Документация Oracle настаивает на том, чтобы я использовал имена столбцов после 'вставки' ​​и 'установки' в слиянии, поэтому может потребоваться другое утверждение. Результат должен быть таким:

ID  |Name                        |Credit Rating    |Sovereign Risk    |Invoicing Type
----+----------------------------+-----------------+------------------+---------------
1   |Nat Bank of Transnistria    |7                |93                |Automatic
2   |Acacacme Ltd.               |31               |12                |Manual
3   |CowBInd LLP.                |49               |12                |Manual
4   |Disenthralled Nimrod Corp.  |31               |52                |Automatic

Если это поможет, я вставлю это сюда:

CREATE TABLE USER_COUNTERPARTY
( COUNTER_ID             INTEGER       NOT NULL PRIMARY KEY,
  COUNTER_NAME           VARCHAR(38),
  COUNTER_CREDIT         INTEGER,
  COUNTER_SVRN_RISK      INTEGER,
  COUNTER_INVOICE_TYPE   VARCHAR(10) );

INSERT ALL
INTO USER_COUNTERPARTY VALUES (1, ‘Nat Bank of Transnistria’, 7, 93, ‘Automatic’)
INTO USER_COUNTERPARTY VALUES (2, ‘Acme Ltd.’, 25, 12, ‘Manual’)
INTO USER_COUNTERPARTY VALUES (3, ‘CowBInd LLP.’, 49, 12, ‘Manual’)
SELECT * FROM DUAL;

CREATE TABLE TEMP AS SELECT * FROM USER_COUNTERPARTY;
DELETE FROM TEMP;

INSERT ALL
INTO TEMP VALUES (2, ‘Conoco Ltd.’, 25, 12, ‘Automatic’)
INTO TEMP VALUES (4, ‘Disenthralled Nimrod Corp.’, 63, 12, ‘Manual’)
SELECT * FROM DUAL;

Ответы [ 5 ]

4 голосов
/ 21 января 2012

Я полагаю, что единственная возможность, которую вы должны избегать, использовать имена столбцов - это два отдельных утверждения:

delete from USER_COUNTERPARTY UC
      where exists
              (select null
                 from TEMP T
                where T.COUNTER_ID = UC.COUNTER_ID);

insert into USER_COUNTERPARTY UC
  select *
    from TEMP T
   where not exists
           (select null
              from USER_COUNTERPARTY UC
             where T.COUNTER_ID = UC.COUNTER_ID);
1 голос
/ 20 января 2012

Вы можете попробовать использовать завернутый оператор объединения, например так:

SELECT (*) FROM
(SELECT * FROM Table1 WHERE ID NOT IN (SELECT ID FROM Table2)
 UNION ALL
 SELECT * FROM Table2)
ORDER BY 1
0 голосов
/ 18 декабря 2017

Я столкнулся с той же проблемой и написал процедуру, которая получает список всех столбцов таблицы и создает динамический SQL-запрос для обновления без именования всех столбцов.

PROCEDURE update_from_table(
  p_source VARCHAR2,  -- Table to copy all columns from
  p_target VARCHAR2,  -- Table to copy into 
  p_id_name VARCHAR2 -- Primary key name
)
  AS
v_sql VARCHAR2(4096) := 'UPDATE ' || p_target || ' t1 SET (';
v_sql_src VARCHAR2(4096) := ') = (SELECT ';
v_sql_end VARCHAR2(4096) := ' FROM '|| p_source ||' t2 WHERE t1.'||p_id_name||' = t2.'||p_id_name||') 
WHERE EXISTS (
SELECT 1
  FROM '|| p_source ||' t2
 WHERE t1.'||p_id_name||' = t2.'||p_id_name||' )';
v_first BOOLEAN := TRUE;  
BEGIN
FOR col IN
(select column_name from user_tab_columns
  where table_name = p_source
)
LOOP
  IF NOT v_first THEN
    v_sql:= v_sql || ', '; -- adding comma before every arg except first
    v_sql_src := v_sql_src || ', ';
  ELSE
    v_first := FALSE;
  END IF;
  v_sql:= v_sql || col.column_name ;
  v_sql_src:= v_sql_src || col.column_name ;
END LOOP;

v_sql := v_sql || v_sql_src || v_sql_end;
EXECUTE IMMEDIATE v_sql;
END update_from_table;

И затем я объединяюсь в 2 шага:

-- Insert not matching records
INSERT INTO USER_COUNTERPARTY
            SELECT *
            FROM TEMP WHERE COUNTER_ID NOT IN (
        SELECT USER_COUNTERPARTY.COUNTER_ID 
        FROM USER_COUNTERPARTY 
        JOIN TEMP ON TEMP.COUNTER_ID = USER_COUNTERPARTY.COUNTER_ID);
-- Update matching records
update_from_table('TEMP', 'USER_COUNTERPARTY', 'COUNTER_ID');
0 голосов
/ 31 июля 2014

Я столкнулся с описанной проблемой, и то, как я ее решил, - это очень низкотехнологичная технология, но я подумал, что поделюсь, если она вызовет другие идеи для людей.

Я взял имена столбцов (я извлекаю их из таблицы DDL в SQL-разработчике, но также использую метод в таблице tab_columns) и вставил их в электронную таблицу Excel. Затем я удалил операторы Varchar и т. Д. (Используя функцию Excel для преобразования текста в столбцы, а затем просто удалил столбец (столбцы), в которых оказались операторы varchar, number и т. Д.), Поэтому он просто оставил имена полей. Затем я вставил формулу в следующий столбец Excel = "dest." & A2 & "= src." & A2 & "," и заполнил ее для всех 110 полей, а затем в новом столбце Excel, используется = A2 & "," и в новый столбец = "src." & A2 & ",", снова заполняющий все поля. Затем в листе SQL я ввожу:

merge into <schema>.<destination_table> dest
  using <schema>.<source_table> src
on (dest.<link> = src.<link>)
when matched then update set
(<copy all of the first column, 
  not including the linking fields and removing the comma at the end>)
when not matched then insert 
(<copy and paste the second column from Excel, and remove the final comma>)
values
(<copy and paste the third column from Excel and remove the final comma>)

У меня также есть версия для объединения таблиц с разными именами столбцов, но для этого требуется дополнительный шаг сопоставления полей в листе Excel.

Я считаю, что мне нужно использовать операторы слияния для того, что я делаю, - я считаю, что слияние позволяет сэкономить время по сравнению с обновлением там, где он есть.

0 голосов
/ 21 января 2012

Если у вас есть значения по умолчанию для столбцов (и вы хотите использовать эти значения по умолчанию), вы можете опустить их в операторе вставки, но в противном случае вам нужно указать каждый столбец, для которого вы хотите вставить или обновить значения.

Сокращений нет, например * для SELECT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...