我有一个包含许多列的表,我想做的是复制表中的所有行,还要将其中一列更新为新值。
例如,可以说我有下表。我想将每行的副本添加到我的表中,除了不是BASIC访问,它将具有“ ADVANCED”:
之前:
NAME, GENDER, ACCESS
----------------------
STEVE, MALE, BASIC
MOLLY, FEMALE, BASIC
之后
NAME, GENDER, ACCESS
----------------------
STEVE, MALE, BASIC
MOLLY, FEMALE, BASIC
STEVE, MALE, ADVANCED
MOLLY, FEMALE, ADVANCED
有没有一种方法可以不指定所有列?表中有60列,并且结构可以更改(这意味着可以添加,删除,重命名列等)。
在Oracle SQL中是否可以自动执行此操作?
答案 0 :(得分:2)
只需使用insert . . . select
:
insert into t (name, gender, access)
select name, gender, 'ADVANCED'
from t;
您需要列出所有列。您可以通过使用查询生成列表来缩短手动过程。如果您必须执行很多操作并且始终知道自己遗漏了access
并且access
是最后一列,则可以使用以下视图:
create view v_t as
select . . . -- all but access
from t;
insert into t ( . . . )
select v.*, 'ADVANCED'
from v_t;
或者您可以使用动态SQL生成语句。
但是,我不推荐其中任何一个。取而代之的是,我会担心要在其中定期添加和修改表中的列的数据模型。听起来很危险。
答案 1 :(得分:1)
是否不指定所有列?在“临时”表的帮助下,方法如下:
您当前的表格:
SQL> create table test
2 (name varchar2(10),
3 gender varchar2(20),
4 caccess varchar2(20));
Table created.
SQL> insert into test
2 select 'steve', 'male', 'basic' from dual union all
3 select 'molly', 'female', 'basic' from dual;
2 rows created.
SQL> create table test_temp as select * From test;
Table created.
SQL> update test_temp set caccess = 'advanced';
2 rows updated.
SQL> insert into test select * From test_temp;
2 rows created.
SQL> drop table test_Temp;
Table dropped.
SQL> select * From test;
NAME GENDER CACCESS
---------- -------------------- --------------------
steve male basic
molly female basic
steve male advanced
molly female advanced
SQL>
显然可以,但是-如果原始表很大怎么办?它占用大量空间,其副本占用的空间大约是原来的两倍。你为什么要这么做?
答案 2 :(得分:0)
尝试以下使用匿名块的方法来避免在插入语句中列出列
CREATE TABLE ACCESS_CHN
(NAAME VARCHAR2(100),
GENDER VARCHAR2(20),
ACCCESS VARCHAR2(30))
INSERT into ACCESS_CHN values('STEVE','MALE','BASIC');
INSERT into ACCESS_CHN values('MOLLY','FEMALE','BASIC');
COMMIT;
DECLARE
column_list varchar2(2000):=NULL;
plsql_block VARCHAR2(1000);
BEGIN
select LISTAGG(column_name,',') within group (order by column_id)
into column_list
from user_tab_columns
where table_name='ACCESS_CHN';
plsql_block := 'CREATE TABLE ACCESS_CHN_BKP as select '|| column_list || ' from ACCESS_CHN';
EXECUTE IMMEDIATE plsql_block;
plsql_block := 'UPDATE ACCESS_CHN_BKP set ACCCESS=''ADVANCED'' ';
EXECUTE IMMEDIATE plsql_block;
COMMIT;
plsql_block := 'CREATE TABLE ACCESS_CHN_FINAL as select * from ACCESS_CHN
union all
select * from ACCESS_CHN_BKP';
EXECUTE IMMEDIATE plsql_block;
END;
--To rerun drop tables ACCESS_CHN_BKP and ACCESS_CHN_FINAL