ORACLE新增主键问题【CREATE PRIMARY KEY AFTER CREATED A TABLE】

本文讨论了在已有表上增加主键时应注意的问题,包括主键名称的定义、存储位置的选择等,并探讨了允许为空的字段上创建索引的可能性及创建主键后的字段属性变化。
    我们都遇到过需要在已建立的表上新增主键的问题(设计发生变化时), 在建立主键时我们有些问题需要注意。
    1.最好指定主键名称和其他存储的属性
    
SQL> alter table larry_test add primary key (terminal_id);

Table altered.
   
    这样的SQL语句没有问题,但是将会有两个问题比较“讨厌”:
    主键名称不知,由系统生成。在DBA[USER]_INDEXES中INDEX_NAME显示的'SYS'开头的基本上就是由系统自动产生的。
    另外一点,我认为更重要一些。即建立的主键存储的表空间和原始表的相同。不利于平衡I/O(当然从某些存储的观点来看,值得商榷。),最起码还是应该将数据和索引分布在不同的表空间上会好些。
    建议使用:
   
  SQL> ALTER TABLE larry_test ADD CONSTRAINT pk_larry_test PRIMARY KEY (terminal_id)USING INDEX  TABLESPACE indx;

Table altered.
   
    当然如果再灵活些,还可以指定索引的存储参数等等。
    同时还有两个小问题:
    首先我们都知道所谓主键就是,该字段或多个字段上为唯一(unique)索引且字段不为空
    那么问题1:在允许为空的字段上是否可以创建索引?
    答案是:可以也不可以。
     可以的情况是该字段虽允许为空,但所有被存储的数据中,该字段没有为空的!字段可以创建索引。反之,不可以。
    2.这个问题很有意思,在允许为空的字段上创建了主键,如果主键被删除,该字段又是怎样的属性呢?
    答案是:我们通过实验发现,一旦主键被建立,该字段属性变为非空(NOT NULL),当主键被删除后,该字段属性恢复建立主键建立前属性,即允许为空。
    
    -:)

DROP TABLE IF EXISTS sequence; CREATE TABLE sequence ( name varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, current_value bigint NULL DEFAULT NULL, crement bigint NULL DEFAULT NULL ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic; ALTER TABLE sequence ADD CONSTRAINT pk_name PRIMARY KEY(name); INSERT INTO sequence(name,current_value,crement) select 'pims_seq' as name, concat(cvalue,'2023000000000') as current_value, '1' as crement from t_bims_system_config where ccode='StationNo'; SET FOREIGN_KEY_CHECKS = 1; -- DROP FUNCTION IF EXISTS currval ; CREATE FUNCTION currval(seq_name VARCHAR(30)) RETURNS bigint LANGUAGE SQL DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT '' BEGIN DECLARE VALUE bigint; SET VALUE =0; SELECT current_value INTO VALUE FROM sequence WHERE NAME=seq_name; RETURN VALUE; END ; CREATE FUNCTION nextval (seq_name VARCHAR(30)) RETURNS bigint LANGUAGE SQL DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT '' BEGIN UPDATE sequence SET current_value = current_value + crement WHERE NAME = seq_name; RETURN currval(seq_name); END; CREATE PROCEDURE db_add_etlId () BEGIN DECLARE s_tablename VARCHAR ( 100 ); DECLARE cur_table_structure CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema =(SELECT DATABASE ()) and substr(table_name,1,6) ='t_bims' and table_type='BASE TABLE' AND table_name NOT IN ( SELECT t.table_name FROM ( SELECT table_name, column_name FROM information_schema.COLUMNS where table_schema =(SELECT DATABASE ()) and table_name IN ( SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema =(SELECT DATABASE ()) and substr(table_name,1,6) ='t_bims' and table_type='BASE TABLE') ) t WHERE t.column_name = 'etlId' ); DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s_tablename = NULL; OPEN cur_table_structure; FETCH cur_table_structure INTO s_tablename; WHILE ( s_tablename IS NOT NULL ) DO SET @MyQuery = CONCAT( "alter table `", s_tablename, "` add COLUMN `etlId` bigint;" ); PREPARE MSQL FROM @MyQuery; EXECUTE MSQL; FETCH cur_table_structure INTO s_tablename; END WHILE; CLOSE cur_table_structure; END; CREATE PROCEDURE db_add_etlId_seq () BEGIN DECLARE s_tablename VARCHAR ( 100 ); DECLARE cur_table_structure CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema =(SELECT DATABASE ()) and substr(table_name,1,6) ='t_bims' and table_type='BASE TABLE' AND table_name IN ( SELECT t.table_name FROM ( SELECT table_name, column_name FROM information_schema.COLUMNS WHERE table_name IN ( SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema =(SELECT DATABASE ()) and substr(table_name,1,6) ='t_bims' and table_type='BASE TABLE' and table_name<>'t_bims_item_value') ) t WHERE t.column_name = 'etlId' ) order by table_rows desc; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s_tablename = NULL; OPEN cur_table_structure; FETCH cur_table_structure INTO s_tablename; WHILE ( s_tablename IS NOT NULL ) DO SET @MyQuery = CONCAT( "update `", s_tablename, "` set etlId=nextval('pims_seq') where etlId is null;" ); PREPARE MSQL FROM @MyQuery; EXECUTE MSQL; FETCH cur_table_structure INTO s_tablename; END WHILE; CLOSE cur_table_structure; END; 通过这种方式生成了bigint的主键,有没有更方便的方式生成bigint主键,能够数据重新还原后还是得到一样的bigint类型主键。最重要的是保持唯一性。
最新发布
08-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值