2016-08-19 3 views
0

следующие работы:PL/SQL вставки с использованием нескольких выбирает и минус оператор

INSERT INTO BASE_TABLE 
(
    req, 
    desc, 
    ver 
) 
    SELECT * FROM UPDATE_TABLE 
minus 
    SELECT req, desc, ver FROM BASE_TABLE; 

Однако это приводит к ошибке (просто пытается вставить еще одно поле: «ключ»):

INSERT INTO BASE_TABLE 
(
    req, 
    desc, 
    ver, 
    key   
) 
    SELECT * FROM UPDATE_TABLE 
minus 
    SELECT req, desc, ver FROM BASE_TABLE, 
    SELECT CONCAT(req, ver) FROM UPDATE_TABLE; 

Ошибка:

PL/SQL: ORA-00903: неверное имя таблицы

Попытка вставить строки в BASE_TABLE, выбирая все из таблицы UPDATE, которая уже не находится в BASE_TABLE. Просто хотел добавить поле «ключ».

Последний SELECT кажется неуместным и вызывает эту ошибку. Является ли «SELECT ... минус SELECT ...» равным одному утверждению, поэтому необходимо выделить третий оператор SELECT? Но как?

+0

Взгляните на 'MERGE' - это, вероятно, гораздо лучше, когда вам нужно сравнить две таблицы для' INSERT '. – mathguy

+0

Несколько заметок/вопросов: во-первых, вы не сможете использовать 'DESC' и' KEY' в качестве имен столбцов (они являются недопустимыми именами объектов, поскольку они зарезервированные слова Oracle). В ваших фактических данных вы, вероятно, имеете другие имена, но для тестирования 'DESC' и' KEY' не будет работать.Затем в Oracle 'concat()' довольно ограничен (например, он принимает только два аргумента), вам лучше использовать оператор '||', который делает то же самое. Затем, какие типы данных являются вашими 'req' и' ver'? Если они не являются символьным типом данных, Oracle будет конвертировать их неявно, это то, что вы хотите? – mathguy

+1

Кроме того, вы объединяете req и ver без разделителя; это нечетный тип ключа. 'req = 1, ver = 23' будет иметь тот же ключ, что и' req = 12, ver = 3' - это то, что вам нужно? – mathguy

ответ

0

два выбор на основании Mus Shou содержит тх одинакового числа и тип столбцов

попробуйте использовать

SELECT req, desc, ver FROM UPDATE_TABLE 
minus 
SELECT req, desc, ver FROM BASE_TABLE 
2

Чтобы заставить его работать as_is, ваша последние «SELECT» фактически должно идти на внешний запрос , например, так:

INSERT INTO BASE_TABLE 
(
    req, 
    desc, 
    ver, 
    key   
) 
    SELECT req, desc, ver, CONCAT(req, ver) 
    FROM 
    (SELECT * FROM UPDATE_TABLE 
     minus 
     SELECT req, desc, ver FROM BASE_TABLE 
    ); 

ПРИМЕЧАНИЕ: Это «ленивый» решение, не должно быть никаких SELECT *, имена столбцов должны быть прописаны в полном объеме. Я просто следил за твоим руководством ... Прямо сейчас, UPDATE_TABLE должно иметь точно правильное количество столбцов с правильными именами и в правильном порядке, потому что вы сказали, что ваш первый запрос работает (он не будет работать иначе). Но если в будущем вы добавите столбец в UPDATE_TABLE, запрос с SELECT * больше не будет работать, но тот, у кого есть полные имена столбцов, не будет затронуто.

+0

получение ошибки по этому методу: PL/SQL: ORA-01789: блок запроса имеет неправильное количество столбцов результатов – user1798810

+0

Извините, это правильно - позвольте мне исправить. (По-прежнему нужен подзапрос для минуса!) – mathguy

+0

мой глаз дрогнул, когда я увидел оператора «минус». первый раз работал с pl/sql. – user1798810

0

MERGE решение: иллюстрация

Документация здесь: https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

создать две небольшие таблицы для иллюстрации. См. Мои комментарии к исходному сообщению: desc и key являются зарезервированными словами, поэтому они не могут использоваться как имена столбцов, поэтому я их соответствующим образом изменил. Я использовал оператор || для конкатенации и явных преобразований в тип символьных данных (VARCHAR2).

Создание небольших тестовых таблиц:

create table base_table (req, dscr, ver, ky) as 
     select 1, 'alpha', 235, '1235' from dual union all 
     select 2, 'beta' , 33 , '233' from dual 
; 
select * from base_table; 

     REQ DSCR   VER KY 
---------- ----- ---------- ---- 
     1 alpha  235 1235 
     2 beta   33 233 

create table update_table (req, dscr, ver) as 
    select 1, 'alpha', 235 from dual union all 
    select 5, 'rho' , 444 from dual 
; 
select * from update_table; 

     REQ DSCR   VER 
---------- ----- ---------- 
     1 alpha  235 
     5 rho   444 

MERGE решение и результат:

merge into base_table b 
    using update_table u 
    on  (b.req = u.req and b.dscr = u.dscr and b.ver = u.ver) 
    when not matched then 
    insert ( req, dscr, ver, ky        ) 
    values (u.req, u.dscr, u.ver, to_char(u.req) || to_char(u.ver)) 
; 

select * from base_table; 

     REQ DSCR   VER KY 
---------- ----- ---------- ---- 
     1 alpha  235 1235 
     2 beta   33 233 
     5 rho   444 5444 
Смежные вопросы