分享
 
 
 

实例讲解如何更改字段至兼容的不同类型

王朝other·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

在实际的工作和学习中,我们可能由于疏忽将一个字段定义为varchar2类型,后来插入里面的数据又都是数字,在此之后,你会突然发现这个字段确实应该为number类型,而此时如果我们想在不影响用户使用的前提下,或者说尽量小的影响用户,保证数据不丢失的情况下,来更改这个数据类型,这个时候如果我们用普通的alter table modify命令,就可能要遇到错误了。示例如下:

22:25:31 SQL> select * from t;

A

----------

10

22:25:32 SQL> desc t

名称 是否为空? 类型

-------------------- --------- --------------------

A VARCHAR2(10)

22:25:34 SQL> alter table t modify(a number);

alter table t modify(a number)

*

第 1 行出现错误:

ORA-01439: 要更改数据类型, 则要修改的列必须为空

其实,类似的现象确实很多,如本来应该为date类型,结果被定义成varchar2类型等等,主要就是那些兼容的数据类型之间的转换定义。当然,为什么一开始会犯这样的错误,那可能原因就有多方面了,如一开始需求就不对等等。

下面,以上面那个例子为基础,介绍两种处理这种问题的方法。

第一种方法,通过增加列来完成

22:25:44 SQL> alter table t add (b number);

表已更改。

22:34:16 SQL> update t set b = to_number(a)

已更新 1 行。

22:34:39 SQL> update t set a = null;

已更新 1 行。

22:34:50 SQL> commit;

提交完成。

22:34:52 SQL> select * from t;

A B

---------- ----------

10

22:34:55 SQL> alter table t modify a number

表已更改。

22:35:21 SQL> update t set a=b;

已更新 1 行。

已用时间: 00: 00: 00.01

22:35:33 SQL> commit;

提交完成。

22:35:52 SQL> alter table t drop column b;

表已更改。

在这种方法中最后也可以先drop column a,然后rename column b to a,达到的效果是一样的。

第二种方法:通过新建表,在新表上更改字段,最后rename新表来完成

22:41:44 SQL> create table t1 as select * from t where 1=2;

表已创建。

22:42:14 SQL> alter table t1 modify (a number);

表已更改。

22:42:24 SQL> insert into t1 select * from t;

已创建 1 行。

22:42:37 SQL> commit;

提交完成。

22:42:40 SQL> drop table t;

表已删除。

22:42:46 SQL> rename t1 to t;

表已重命名。

22:43:00 SQL> desc t;

名称 是否为空? 类型

-------------- --------- -------------

A NUMBER

我就知道这两种常见的方法,不知道还有没有什么其他的好方法。如果有,请分享。建议使用第一种。

约束和索引都被摧残了,可以做个实验证明一下。

先建立测试表并插入数据

15:28:45 SQL> create table t (a varchar2(10) not null);

表已创建。

已用时间: 00: 00: 00.03

15:28:47 SQL> insert into t values ('10');

已创建 1 行。

已用时间: 00: 00: 00.00

15:28:55 SQL> commit;

提交完成。

已用时间: 00: 00: 00.00

然后增加一个列,并且把数据复制过去

15:29:08 SQL> alter table t add (b number);

表已更改。

已用时间: 00: 00: 00.01

15:29:31 SQL> update t set b=to_number(a);

已更新 1 行。

已用时间: 00: 00: 00.01

15:29:42 SQL> commit;

提交完成。

已用时间: 00: 00: 00.00

15:29:45 SQL> alter table t modify b not null;

表已更改。

已用时间: 00: 00: 00.10

在原来的列上建立索引和约束

15:29:59 SQL> create index ind_t_a on t(a);

索引已创建。

已用时间: 00: 00: 00.15

15:31:01 SQL> alter table t add constraint uk_t_a unique(a);

表已更改。

已用时间: 00: 00: 00.03

斗转星移:

15:31:20 SQL> alter table t drop column a;

表已更改。

已用时间: 00: 00: 01.20

15:32:06 SQL> alter table t rename column b to a;

表已更改。

已用时间: 00: 00: 00.03

查看索引是否还在?可以看到索引已经被损坏了:

15:33:17 SQL> select index_name,status from user_indexes where table_name='T';

未选定行

已用时间: 00: 00: 00.12

15:34:20 SQL> select index_name,status from user_indexes order by 1;

INDEX_NAME STATUS

------------------------------ --------

PK_DEPT VALID

PK_EMP VALID

已用时间: 00: 00: 00.35

然后查看约束是否还在?可以看到它也被摧残了

15:38:07 SQL> select constraint_name,constraint_type,invalid,table_name from user_constraints where table_name='T';

CONSTRAINT_NAME CONSTRAINT_TYPE INVALID TABLE_NAME

------------------------------ -------------------- ------- -----------

SYS_C005423 C T

已用时间: 00: 00: 00.03

15:38:24 SQL> select constraint_name,constraint_type,invalid,table_name from user_constraints;

CONSTRAINT_NAME CONSTRAINT_TYPE INVALID TABLE_NAME

------------------------------ -------------------- ------- ------------

BIN$lNdA2W97SK69TBAu945o7w==$0 C BIN$W9ZnSgtTS9+Fs/438TqKuA==$0

BIN$6JXde6KdTsum1GYM3py1eg==$0 C BIN$W9ZnSgtTS9+Fs/438TqKuA==$0

SYS_C005423 C T

FK_DEPTNO R EMP

PK_DEPT P DEPT

PK_EMP P EMP

已选择6行。

已用时间: 00: 00: 00.23

验证后,唯一约束已经不起作用了

15:38:31 SQL> select * from t;

A

----------

10

已用时间: 00: 00: 00.03

15:39:26 SQL> desc t;

名称 是否为空? 类型

--------------- --------- ---------------------------

A NOT NULL NUMBER

15:39:29 SQL> insert into t values(10);

已创建 1 行。

已用时间: 00: 00: 00.01

15:39:38 SQL> commit;

提交完成。

已用时间: 00: 00: 00.00

15:39:44 SQL> select * from t;

A

----------

10

10

可能大家会问,为什么还有一个C约束呢?上面的查询显示它是not null约束:

15:51:06 SQL> select table_name,constraint_name,column_name from user_cons_columns where table_name='T';

TABLE_NAME CONSTRAINT_NAME COLUMN_NAME

------------------------------ ------------------------------ -----------------

T SYS_C005423 A

16:09:29 SQL> select search_condition from user_constraints where table_name='T';

SEARCH_CONDITION

--------------------------------------------------------------------------------

"A" IS NOT NULL

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有