给定一个表T(x, y, z, t, u, v, ...)
是否可以在Oracle中编写此查询而不列出所有列(在SELECT或INSERT部分中)?
INSERT INTO T (x, y, z, t, u, v, ...)
SELECT 'new', y, z, t, u, v, ...
FROM T
WHERE x = 'old'
效果是x
具有 old 值的所有行都是重复的,但现在x
的值为 new
答案 0 :(得分:2)
“在Oracle中可以编写此查询而不列出所有内容 列(在SELECT或INSERT部分中)“
没有。避免键入显式投影的唯一方法是使用所有表的列。您没有这样做,因为您想使用文字而不是列X
。这意味着您必须列出SELECT投影中的所有其他列。
当然,您不必在INSERT子句中指定列。
多年来,开发人员偶尔希望使用“except”语法,例如:
select * except X from t
但它从未进入ANSI标准。事实上,我怀疑它是否被讨论过。
“欢迎PLSQL回答!”
好的,这是一个概念证明,它使用数据字典生成动态插入语句。
它做出以下假设:
如果任何这些假设错误,您将需要调整代码。
该过程遍历USER_TAB_COLUMNS表,将列排序为表的预计顺序。它将列名连接到INSERT语句的SELECT子句中,除非在连接提供的文字时,名称是替换列的名称。最后,它使用Native Dynamic 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;
/
答案 1 :(得分:1)
如果所选列正确排序,您可以完全按照您的描述进行操作。
以下是有效
INSERT INTO T
SELECT 'new', y, z, t, u, v, ...
FROM T
WHERE x = 'old'
或者你可以尝试这个(粗略的脚本未经测试)
CREATE TABLE TEMPTABLE AS SELECT * FROM T WHERE X = 'Old';
UPDATE TEMPTABLE SET X='New';
INSERT INTO T (SELECT * FROM TEMPTABLE);
DROP TABLE TEMPTABLE;
答案 2 :(得分:0)
以下是太过分了,以避免一些打字imo,但我喜欢挑战,所以在这里... ...
insert into T
select * from T
where x='old';
commit;
-- update every other row to 'new'
update T
set x='new'
where rowid in
(
select rowid from
(select rownum rnum, rowid row_id
from T
where x='old'
)
where mod(rnum,2)=0
);
commit;
分2步,但我个人只是查询表的all_tab_columns(按column_id排序)并复制/粘贴到我的脚本/过程中。但可能是其他一些避免这种情况的原因,不确定。