"возможно ли в Oracle написать этот запрос без перечисления всех столбцов (будь то в SELECT или в части INSERT)"
Нет.Единственный способ избежать ввода явной проекции - это использовать все столбцы таблицы.Вы этого не делаете, потому что хотите использовать литерал вместо столбца X
.Это означает, что вам нужно перечислить все остальные столбцы в проекции SELECT.
Конечно, вам не нужно указывать столбцы в предложении INSERT.
В течение многих лет разработчики время от времени желали использовать синтаксис «исключая», что-то вроде:
select * except X from t
, но он никогда не включался в стандарт ANSI.На самом деле, я сомневаюсь, что это вообще обсуждалось.
«Ответы PLSQL приветствуются!»
Хорошо, вот подтверждение концепции, которая используетсловарь данных для создания динамического оператора вставки.
Он принимает следующие допущения:
- Вы хотите подставить значение только одного столбца.
- Столбец, который вы хотите заменить, является типом данных строки.
- Вы хотите клонировать все записи в исходной таблице.
Вам потребуется изменить код, если какое-либо из этих предположений неверно.
Процедуразацикливает таблицу USER_TAB_COLUMNS, сортируя столбцы в соответствии с прогнозируемым порядком таблицы.Он объединяет имена столбцов в предложение SELECT оператора INSERT, за исключением случаев, когда имя совпадает с именем замещенного столбца, когда вместо этого он объединяет предоставленный литерал.Наконец, он использует собственный динамический SQL для запуска собранного оператора INSERT.
create or replace procedure clone_minus_one
( p_sub_col in user_tab_columns.column_name%type
, p_sub_val in varchar2 )
is
stmt varchar2(32767) := 'insert into source_table select ';
begin
for lrec in ( select column_name
, column_position
from user_tab_columns.
where table_name = 'SOURCE_TABLE'
order by column_position )
loop
if lrec.column_position != 1
then
stmt := stmt ||',';
end if;
if lrec.column_name != p_sub_col
then
stmt := stmt ||lrec.column_name;
else
stmt := stmt ||''''||p_sub_val||'''';
end if;
end loop;
stmt := stmt || ' from source_table';
execute immediate stmt;
end;
/