oracle对没有主键表的新增主键修改表数据操作(没有主键字段,则新增一个主键字段,然后赋值,然后再添加主键)

本文介绍如何通过添加主键、创建序列、更新主键值、设置主键约束等步骤优化Oracle数据库中的表结构,并提供删除重复记录及修改字段为非空的具体SQL语句。
--新增主键(没有主键字段,则新增一个主键字段,然后赋值,然后再添加主键)
alter table REPORT_ABNORAML  add ID number(11) null;
--删除序列
--drop SEQUENCE SEQ_REPORT_ABNORAML
--增加序列
CREATE SEQUENCE SEQ_REPORT_ABNORAML
INCREMENT BY 1 -- 每次加几个 
START WITH 1 -- 从1开始计数 
NOMAXVALUE -- 不设置最大值 
NOCYCLE -- 一直累加,不循环 
NOCACHE;

--设置默认值
UPDATE  REPORT_ABNORAML SET ID=SEQ_REPORT_ABNORAML.nextval;
commit;
--设置主键属性
alter table REPORT_ABNORAML  add primary key (ID);
--更新主键字段不为空
alter table REPORT_ABNORAML MODIFY ID number(11) not null;

--按条件删除此表中重复的数据
delete 
from Report_ABNORAML  t
where 
t.id in (select id from (
select row_number() over(PARTITION BY t.report_id,t.abnoraml_no order by t.abnoraml_no) as row1,t.id
 from REPORT_ABNORAML t
where  1=1 
and report_id in (
select report_id FROM 
(select ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY report_time desc,report_id desc) as Row1, 
report_id,customer_id,orgain_id from report_info 
where 1 = 1  and orgain_id in (1) /*and report_time >= to_char('2015-04-01') 
and report_time < to_char('2015-09-01') and customer_id in (select customer_id from customer_info 
where work_unit in ('第三采油厂') */) )TT where TT.Row1 = 1)
)a where a.row1!=1);
commit;

--删除列
alter table REPORT_ABNORAML drop COLUMN ID ;

<think>我们参考了引用内容,特别是引用[1]和[4]中关于在OceanBase的Oracle模式下实现自增主键的方法。用户的问题是如何将现有主键字段修改为自增字段。在OceanBase的Oracle模式中,通常使用序列(Sequence)和触发器(Trigger)来实现自增主键的功能。但是,直接修改主键字段为自增字段,OceanBase并不像MySQL那样有AUTO_INCREMENT属性,而是需要借助序列和触发器。 步骤概述: 1. 创建一个序列(Sequence)用于生成自增数字。 2. 创建一个触发器(Trigger),在插入数据之前,将序列的下一个值赋给主键字段。 但是,如果已经存在,并且主键字段已经存在数据,我们需要考虑如何将已有的主键数据迁移到新的自增方式。这里我们假设主键字段是数字类型,并且我们希望后续的插入能够自动生成自增的主键。 详细步骤: 第一步:创建序列 我们可以使用CREATE SEQUENCE语句创建一个序列。例如: ```sql CREATE SEQUENCE your_sequence_name START WITH 1 -- 起始值 INCREMENT BY 1 -- 每次增加1 CACHE 20 -- 缓存大小,提高性能 NOCYCLE; -- 不循环 ``` 第二步:创建触发器 创建一个BEFORE INSERT触发器,在插入数据前为主键字段赋值。 ```sql CREATE OR REPLACE TRIGGER your_trigger_name BEFORE INSERT ON your_table_name FOR EACH ROW BEGIN IF :new.id IS NULL THEN -- 如果插入时主键字段为NULL,则使用序列生成的值 SELECT your_sequence_name.nextval INTO :new.id FROM DUAL; END IF; END; ``` 注意:这里假设主键字段名为`id`,并且当插入操作没有指定主键值时,我们才使用序列生成的值。如果插入时指定了主键值,则不会触发序列(但需要确保不重复,否则会违反主键约束)。 但是,如果已经存在,并且我们希望将已有的主键值保留,同时让后续插入使用自增序列,那么我们需要确保序列的起始值大于当前中已有的最大主键值。因此,在创建序列时,我们可以这样设置: ```sql CREATE SEQUENCE your_sequence_name START WITH (SELECT MAX(id)+1 FROM your_table_name) -- 注意:这里不能直接使用子查询,需要先查询出来再设置 ``` 然而,在OceanBase中,START WITH子句不能直接使用子查询,所以我们需要先查询出最大值,然后动态设置。 因此,实际操作步骤为: 1. 查询当前的最大主键值: ```sql SELECT MAX(id) FROM your_table_name; ``` 假设最大值为100,那么序列的起始值应该设置为101。 2. 创建序列: ```sql CREATE SEQUENCE your_sequence_name START WITH 101 INCREMENT BY 1 CACHE 20 NOCYCLE; ``` 3. 创建触发器(同上)。 另外,如果中原有数据主键值已经存在,我们不需要修改已有的数据,只需要确保新插入的数据使用序列生成的值即可。 但是,如果用户希望将主键字段完全改为自增,并且不允许手动指定,那么可以在触发器中去掉条件判断,总是使用序列: ```sql CREATE OR REPLACE TRIGGER your_trigger_name BEFORE INSERT ON your_table_name FOR EACH ROW BEGIN :new.id := your_sequence_name.nextval; END; ``` 这样,无论插入时是否指定了主键值,都会使用序列生成的值覆盖。 注意事项: - 在分布式数据库OceanBase中,序列可以保证全局唯一,但因为是递增的,所以不能保证连续(因为缓存机制可能会跳过一些值)。 - 引用[2]中提到OceanBase序列的当前限制,如最大值为10^27-1,如果超过这个值,则需要考虑其他方案(如分库分或者使用UUID等)。 - 触发器可能会对性能有一定影响,但通常对于主键赋值操作,影响较小。 如果用户需要将主键字段改为自增字段,并且已经存在,那么我们需要按照上述步骤创建序列和触发器。同时,我们还需要考虑在已有数据迁移过程中的主键冲突问题,确保新生成的主键值不会与已有数据重复。 总结:在OceanBase的Oracle模式中,通过序列和触发器的组合,可以实现类似MySQL的AUTO_INCREMENT功能。 相关问题: 1. 如何修改OceanBase序列的起始值? 2. 如何删除OceanBase中的触发器? 3. OceanBase序列的缓存大小如何设置? 4. 如何避免在OceanBase中使用序列时产生的性能问题?</think>在 OceanBase 中将现有主键字段修改为自增字段,需要结合序列(Sequence)和触发器(Trigger)实现,因为 OceanBase 不支持类似 MySQL 的 `AUTO_INCREMENT` 原生语法。以下是详细操作步骤: --- ### 一、修改主键为自增字段的完整步骤 #### 1. 创建序列(Sequence) ```sql CREATE SEQUENCE your_sequence_name START WITH 1 -- 起始值 INCREMENT BY 1 -- 每次增加1 CACHE 20 -- 缓存大小(提高性能) NOCYCLE; -- 不循环(避免主键重复) ``` **说明**: - 序列名称建议按 `名_seq` 格式命名(如 `user_id_seq`) - `CACHE` 值根据并发量设置(20~100),过高可能导致序列断号[^2] #### 2. 修改结构(添加默认值) ```sql ALTER TABLE your_table MODIFY id NUMBER DEFAULT your_sequence_name.NEXTVAL; ``` **注意**: - 仅当为空时才能直接修改主键默认值 - 若中有数据,需使用触发器方案(见步骤3) #### 3. 创建触发器(处理非空) ```sql CREATE OR REPLACE TRIGGER trg_auto_id BEFORE INSERT ON your_table FOR EACH ROW BEGIN IF :new.id IS NULL THEN SELECT your_sequence_name.NEXTVAL INTO :new.id FROM DUAL; END IF; END; / ``` **作用**: - 插入数据时自动填充主键 - 兼容手动指定主键的场景(如数据迁移) --- ### 二、关键操作示例 假设 `employees` 需要将主键 `emp_id` 改为自增: ```sql -- 1. 创建序列 CREATE SEQUENCE emp_id_seq START WITH 1001 CACHE 30; -- 2. 创建触发器 CREATE OR REPLACE TRIGGER trg_emp_id BEFORE INSERT ON employees FOR EACH ROW BEGIN IF :new.emp_id IS NULL THEN SELECT emp_id_seq.NEXTVAL INTO :new.emp_id FROM DUAL; END IF; END; / -- 3. 插入数据(自动生成ID) INSERT INTO employees (name, dept) VALUES ('张三', 'IT'); -- 此时emp_id自动填充为1001 ``` --- ### 三、注意事项 1. **序列限制**: - 最大值为 $10^{27}-1$(约 1e27)[^2] - 不支持跨租户共享序列 - 无法直接查看当前值(只能查 `LAST_NUMBER`) 2. **主键冲突处理**: ```sql -- 手动同步序列值(避免插入冲突) SELECT emp_id_seq.NEXTVAL FROM DUAL; -- 消耗一个值 ALTER SEQUENCE emp_id_seq INCREMENT BY -1; -- 回退 ``` 3. **性能优化**: - 设置合理的 `CACHE` 值减少磁盘 I/O - 避免在触发器内编写复杂逻辑 - 大批量导入时临时禁用触发器: ```sql ALTER TRIGGER trg_auto_id DISABLE; -- 执行数据导入 ALTER TRIGGER trg_auto_id ENABLE; ``` --- ### 四、替代方案比较 | **方案** | **优点** | **缺点** | 适用场景 | |----------------|--------------------------|--------------------------|----------------------| | 序列+触发器 | 严格递增,易读 | 有序列断号风险[^2] | 需要连续ID的业务 | | UUID | 全局唯一,无需集中生成 | 无序存储影响性能 | 分布式系统 | | 时间戳+随机数 | 实现简单 | 可能冲突,不适合主键 | 临时数据标识 | | 应用层生成 | 完全可控 | 增加应用复杂度 | 分库分环境 | --- ### 五、自增主键设计建议 1. **值域规划**: $$ \text{最大记录数} \leq 10^{k} - 1 \quad (k = \text{主键字段长度}) $$ 例如 `NUMBER(10)` 最大支持 $9999999999$(约 100 亿条) 2. **分库分场景**: ```sql -- 使用复合ID:分片ID + 序列 CREATE SEQUENCE shard_seq START WITH 10000 INCREMENT BY 100; -- 每个分片分配不同步长(shard1: INCREMENT 100, shard2: INCREMENT 101) ``` 3. **监控序列使用**: ```sql -- 检查序列状态 SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'EMP_ID_SEQ'; ``` > ⚠️ **重要限制**:OceanBase 不支持 `ALTER SEQUENCE ... START WITH` 修改起始值[^2],创建时需预留足够空间。 --- ### 相关问题 1. 如何解决 OceanBase 序列的缓存断号问题? 2. 在分库分环境下如何设计全局唯一自增ID? 3. OceanBase 中如何实现类似 MySQL 的 `AUTO_INCREMENT` 偏移量设置? 4. 序列值达到最大值 $10^{27}-1$ 后应该如何处理? [^1]: 在迁移过程中,使用序列实现自增主键是 OceanBase 的推荐方案 [^2]: OceanBase 序列存在最大值限制和修改限制,设计时需提前规划 [^3]: 通过触发器绑定序列是实现自增主键的核心方法 [^4]: 插入数据时直接引用序列的 `NEXTVAL` 可自动生成主键
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值