主键设计
ROWNUM 和 ROWID(Oracle特有)
ROWID
特点:唯一,且固定,是在行数据生成时产生的id;
1
2
3
4
5
6
select rowid, empno from emp;
-- 此时的查询结果中,所有行的rowid字段是唯一的
select rowid, empno from emp where empno = 7369;
-- 该结果中
-- empno=7369的rowid 和
-- 上一条 select 语句结果中empno=7369的rowid 相同
ROWID是永远不变的, 永远跟行记录走,不因查询条件而变化
ROWNUM
特点:一个伪列,对查询结果返回的行编号即行号,由1开始 依次递增
-- 返回该表全部14条数据
select rownum, emp.* from emp; -- 结果的rownum为1-14
-- 返回部门号为30的6条数据
select rownum, emp.* from emp where deptno = 30; -- 结果的rownum为1-6
-- 选取rownum的前五条数据
select rownum, emp.* from emp where rownum < 5;
ROWNUM数值是在获取每行之后才赋予的。
且:在 order by 之前赋予
要想在 order by 之后进行 rownum 的赋值,则只能:
1
2
3
4
5
select rownum, T.* from
(
select * from emp order by sal
) T
where rownum < 5
分页问题
1
2
3
4
5
select rownum, T.* from
(
select * from emp order by '一些条件'
)
between 'page1' and 'page2'
SQUENCE序列 (自增)
首先要有 Create sequence 或者 create any sequence 权限
创建sequence对象
1
2
3
4
5
create sequence emp_sequence -- 'sequence名称(自拟)'
increment by 1 -- '每次增加的数量'
start with 1 -- '从几开始'
nomaxvalue -- '一直累加,不循环'
cache 10 -- '缓存大小'
sequence对象的查询使用
1
2
3
4
5
-- 自增查询:查一次当前这个sequence的数值就增一次
-- 增多少取决于创建时,用increment给其定义的大小
select emp_sequence.nextVal from dual;
-- 当前查询:无论查多少次都是和第一次查询一样的值
select emp_sequence.currval from dual;
sequence对象的插入使用
1
2
3
-- 一半都是使用nextval插入,保证使用该序列的表不会拥有相同的一个id值
insert into dept(deptno, dname, loc)
values (emp_sequence.nextval, 'PROGRSAMER', 'BEIJING');
使用sequence序列号时需注意:
序列号只是用于保证某一列为唯一整数的方法。
不要试图赋予它更多的意义。如:
试图保证其连续性
如下情况会导致序列号的值不连续。
- 回滚
- 系统错误,导致数据添加失败
- 同一个sequence序列对象用于多张表
一般sequence都是以主键的形式使用,一张表一个sequence对象
主键生成方式
sequence
由Sequence对象生成一个不重复的整数。
其他数据库如:sqlserve、mysql 有一个identity类型的自增字段。
UUID
UUID简介
由四个连字号(-)将32个字节长的字符串分割后生成的字符串,一共36个字节。
比如:550e8400-e29b-41d4-a716-446644330000
UUID实现方式GUID
Oracle中生成UUID的函数为:sys_guid()
1
2
3
4
5
6
7
8
9
10
-- PL/SQL 编辑器的话,生成的就是一个正常的uuid
select sys_guid() from dual;
insert into emp(...)
values(sys_guid()...)
-- 但如果用的其他客户端的话,生成的可能时乱码
-- 这是需要加上:rawtohex()
select rawtohex(sys_guid()) from dual;
insert into emp(...)
values(rawtohex(sys_guid())...)
Java 中使用uuid
1
2
3
4
5
import java.util.UUID;
String uuid = UUID.randomUUID();
uuid = uuid.replaceALL("-", "");
System.out.println(uuid);
UUID 只起到维护表之间关联关系的作用。
为什么不使用业务字段作为主键
如:学号、产品号、工号。。。
因为:业务上的标识是有可能会更改的,而主键大部分情况可能会作为其他表的外键,如果用业务字段作为主键,当这些业务字段更改时,会很麻烦。