Sql 在更新一个或多个列时,是否可以复制表中的所有值

Sql 在更新一个或多个列时,是否可以复制表中的所有值,sql,oracle,Sql,Oracle,我有一个包含许多列的表,我想做的是复制表中的所有行,同时将其中一列更新为新值 例如,假设我有下表。我想向我的表中添加每一行的副本,除了基本访问之外,它将具有“高级”: 之前: NAME, GENDER, ACCESS ---------------------- STEVE, MALE, BASIC MOLLY, FEMALE, BASIC 之后 NAME, GENDER, ACCESS ---------------------- STEVE, MALE, BASIC MOLLY, FEMA

我有一个包含许多列的表,我想做的是复制表中的所有行,同时将其中一列更新为新值

例如,假设我有下表。我想向我的表中添加每一行的副本,除了基本访问之外,它将具有“高级”:

之前:

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中是否可以自动执行此操作?

只需使用
插入。选择

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生成语句


但是,我不推荐任何一种。相反,我关心的是一个数据模型,您可以在其中定期添加和修改表中的列。听起来很危险。

只要使用
插入。选择

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生成语句


但是,我不推荐任何一种。相反,我关心的是一个数据模型,您可以在其中定期添加和修改表中的列。听起来很危险。

不指定所有列?在“临时”表格的帮助下,以下是如何:

您当前的表格:

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
  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.
  • 创建一个“临时”表作为“原始”表的副本
  • 更新要修改的列
  • 将整个“临时”表复制到“原始”表
  • 删除“临时”表


显然,这是可行的,但是——如果原来的桌子很大呢?它占用了大量的空间,而且它的副本占用了大约两倍的空间。无论如何,为什么要这样做?

尝试下面的匿名块方法,以避免在insert语句中列出列

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

请使用匿名块尝试下面的方法,以避免在insert语句中列出列

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

不要混淆Oracle SQL和PL/SQL;PL/SQL完全是另一回事,与您的问题无关。我会在这方面编辑你的帖子。好吧,假设你今天做“这个”。(“这意味着在更改访问权限时复制现有行。)明天,您将向表中添加1000行。如果您无意识地再次应用该过程,那么您将得到重复的旧行,其中
ACCESS='ADVANCED'
。这就是你想要的吗?您确定您考虑过多次这样做的未来副作用吗?不要将Oracle SQL与PL/SQL混淆;PL/SQL完全是另一回事,与您的问题无关。我会在这方面编辑你的帖子。好吧,假设你今天做“这个”。(“这意味着在更改访问权限时复制现有行。)明天,您将向表中添加1000行。如果您无意识地再次应用该过程,那么您将得到重复的旧行,其中
ACCESS='ADVANCED'
。这就是你想要的吗?你确定你考虑过多次这样做的未来副作用吗?如前所述,我想在不指定所有列的情况下执行此操作,因为该表有近60列。如前所述,我想在不指定所有列的情况下执行此操作,因为该表有近60列。是,我曾想过这样做,但正如你所说,似乎有很多额外的数据写入到数据库中。我真的希望Oracle有类似于google SQL支持的SELECT*REPLACE的东西。听起来好像不是。我查看了你发布的链接;是的,看起来是个不错的选择。不过,据我所知,Oracle没有。是的,我曾考虑过这样做,但正如你所说,似乎有很多额外的数据写入到数据库中。我真的希望Oracle有类似于google SQL支持的SELECT*REPLACE的东西。听起来好像不是。我查看了你发布的链接;是的,看起来是个不错的选择。不过,据我所知,甲骨文没有。