给定一个表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
有老值的所有行都是相同的,只是现在x
有新值。
给定一个表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
有老值的所有行都是相同的,只是现在x
有新值。
“是否有可能在甲骨文写这个查询没有列出所有 列(不管是在SELECT还是在INSERT部分)“
否。避免输入显式投影的唯一方法是使用所有表格的列。你不这样做,因为你想使用文字而不是列X
。这意味着您必须在SELECT投影中列出所有其他列。
当然,您不必在INSERT子句中指定列。
在开发人员偶尔希望对年“除了”语法,是这样的:
select * except X from t
,但它从未进入ANSI标准。事实上,我怀疑它是否被讨论过。
“PLSQL答案,欢迎呢!”
好的,这里是使用数据字典生成动态插入语句的概念证明。
它作以下假设:
如果这些假设中的任何一个错误,您将需要调整代码。
该过程围绕USER_TAB_COLUMNS表循环,将列排序为表的投影顺序。它将列名连接到INSERT语句的SELECT子句中,除非名称是连接所提供的文字时替换列的名称。最后它使用本地动态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;
/
您可以按照您的描述完成,只要您选择的列正确排列。
以下是有效的
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;
您必须在选择中列出所需的所有列,但只要它们按正确的顺序映射到列,则查询将起作用。 –
@Hugh Jones:好的,重新提出的问题:我想避免列出INSERT部分中的所有列,并在SELECT部分列出除x以外的所有列。这不够清楚吗? – Benoit
我迂腐了吗?抱歉。 –
以下是走得太远,以免一些打字海事组织,但我喜欢挑战,所以这里去...
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排序)并复制/粘贴到我的脚本/过程中。但可能是一些其他的原因,以避免这一点,不知道。
你试过了吗? –
@Hugh Jones:当然,INSERTING没有列出列将插入默认值。我想复制现有的行。 – Benoit
您在上面显示的查询将具有您正在寻找的效果。 –