伪列
-
rowID 列的id 物理地址 不变的
-
rownum 列的编号 逻辑地址 可变的
a.select rowid,rownum,e.* from emp e ;
b. select rowid,rownum,e.* from emp e where deptno = 20;
-
业务查询:
查询emp中工资最高的前三个员工信息
(1)错误做法:
此时查询的表还是没有排序之前的表emp,因此rownum没有发生变化
(2)正确做法使用子查询:
select rownum,ename,sal from (select * from emp order by sal desc) where rownum <4 ;
此时查询的表是一个子查询中排序后的表,此时的rownum已经发生变化
(3)总结:
遇到top-n 问题全都套用以下公式即可:
select rownum,… from (select * from xxx****表 order by xxx) where rownum < n ;
注: 在使用rownum之前,先解决排序问题!!
-
插入重复项
(1)创建student表
(2)插入重复数据
-
删除重复数据
(1)错误方式:
① 以stuno为依据删除,是错误的!
此删除将会删除所有stuno相同的所有数据,并没有去重
② 以distinct方式删除数据,也是错误的!
select distinct stuno from mystudent ;
此方式只能比较数据,不能依据rowID进行操作
(2)正确方式:
手动:Delete from mystudent where rownum=1;
Delete from mystudent where rownum=3;
思路:根据stuno分组,将重复的数据放在一组中,然后在每组中只保留一个数据即可
a.先根据stuno分组
b. 根据rowid来去重,保留rowid中最小或最大的都行
c. 删除非保留的数据
delete from mystudent where rowid not in (select min(rowid) from mystudent group by stuno);
-
Rowid: 物理伪列
18位真实的存在物理硬盘上的地址
AAAAAA AAA AAAAAA AAA
对象 文件 块 行
约束简介
-
数据表只支持数据的存储操作,数据库中保证数据完整性,增加了数据约束,如果有些数据需要满足若干条件后才可以进行操作,例如:某些数据不能重复,假设定义用户信息,身份证编号绝对不能重复。
-
数据库约束有六种:
检查(check)
唯一(Unique)
非空(Not null)
默认约束(Default)
主键(Primary key)
外键(Foreign Key)
-
创建student表
√ 插入数据:
x 主键约束:
√ 有默认值:
x 唯一约束:
x 非空约束:
x 检查约束:
-
约束分类
-
约束的命名
(1)规范:CONSTRAINT 约束类型_字段名
(2)注意事项:约束名是 多个表公用的 (多个表中的约束 不能重名)
create table student2( id number(3) constraint PK_stuno primary key , name varchar2(10) );
检查约束(CHECK,CK)
-
检查约束指:在数据列上设置一些过滤条件,当过滤条件满足的时候才可以进行保存数据,如果不满足则不允许保存数据。
-
检查约束案例:如果设置年龄的信息,年龄0~250,性别男/女
CREATE TABLE member(
mid NUMBER,
mname VARCHAR2(20)
age NUMBER(3)
CONSTRAINT pk_mid PRIMARY KEY(mid)
CONSTRAINT ck_age CHECK(age BETWEEN 0 AND 250)
);
请问,除了“年龄”检查,在age上应该还要做什么约束??从实际的开发来讲,检查约束往往不会设置,而检查一般都会通过程序完成。
唯一约束
-
唯一约束的特点是在某一列上的内容不允许出现重复
例如,收集用户的信息,包含编号,姓名,email;明显email数据是不可能重复的,所以可以使用UNIQUE约束。
-
范例:使用唯一约束
CREATE TABLE member( mid NUMBER , mname VARCHAR2(20) NOT NULL UNIQUE, email VARCHAR2(20) UNIQUE );
-
向member增加数据
(1)范例:增加正确的数据
INSERT INTO member(mid,mname,email)VALUES(1,‘JACK’,‘[email protected]’);
(2)范例:增加错误的数据(邮箱不可以有重复的)
INSERT INTO member(mid,mname,email)VALUES(2,‘TOM’,‘[email protected]’);
非空约束
-
非空约束指表中某个字段的内容不允许为空值,如果要使用非空约束,只需要在每个列后面使用“NOT NULL”声明即可。
-
范例:使用非空约束
注意:在mname列定义时,增加NOT NULL表示该列不允许出现NULL值。
CREATE TABLE member( mid NUMBER, mname VARCHAR2(20) NOT NULL );
-
向member增加数据
(1)范例:正确的增加语句
INSERT INTO member(mid,mname)VALUES(1,‘JACK’);
(2)范例:错误的增加数据
INSERT INTO member(mid,mname)VALUES(1,NULL);
INSERT INTO member(mid)VALUES(1);
注意:在设置了非空约束后,如果出现了违反非空约束的操作,什么自动准确 的定位到哪个模式、哪张表、哪个字段,这样在进行错误排查时最方便所在
默认约束
-
默认约束指定某列的默认值,
在没有明确插入数据时默认添加指定的默认值。
-
范例:使用默认约束
在sex列定义时,增加default表示该列默认值为‘男’。
CREATE TABLE member( mid NUMBER, mname VARCHAR2(20) NOT NULL, sex VARCHAR2(20) default '男' );
主键约束
-
主键约束=非空约束+唯一约束
-
设置主键列,不能为空也不能重复。像用户的编号,也不能为空
-
范例:定义主键约束
推荐使用第二种方法,错误时提示的信息,可以精确定位到列。
CREATE TABLE member( mid NUMBER PRIMARY KEY, mname VARCHAR2(20) NOT NULL); 或 CREATE TABLE member( mid NUMBER , mname VARCHAR2(20) NOT NULL, CONSTRAINT pk_mid PRIMARY KEY(mid) );
-
在正常情况下一张表只能够定义一个主键,在SQL中也允许定义多个列为主键,这样的操作称为:复合主键,如果是复合主键表示若干个列的内容完全重复的时候会违反约束。
-
范例:定义复合主键
**注意:**数据库设计第一原则,不要使用复合主键,即一张表一个主键。
CREATE TABLE member( mid NUMBER, mname VARCHAR2(20) NOT NULL, CONSTRAINT pk_mid PRIMARY KEY(mid,mname) );
外键约束
-
外键约束主要是在父子表关系中体现的一种约束操作。下面通过一个具体操作观察为什么会有外键。例如:现在希望描述一种概念:一个人有多本书,如果设计表需要设计两张数据表,则初期的设计如下。
-
范例:初期设计(不使用外键)
CREATE TABLE member( mid NUMBER, mname VARCHAR2(20), constraint pk_mid primary key(mid) ); CREATE TABLE book( bid NUMBER, title VARCHAR2(20), mid NUMBER );
-
于是下面开始为表增加相关的数据。
范例:增加正确数据
insert into member(mid,mname)values(1,‘jack’);
insert into member(mid,mname)values(2,‘tom’);
insert into book(bid,title,mid)values(10,‘java开发’,1);
insert into book(bid,title,mid)values(11,‘PHP开发’,1);
insert into book(bid,title,mid)values(12,‘C开发’,2);
insert into book(bid,title,mid)values(13,‘NET开发’,2);
但也有可能出现如下的信息:
insert into member(bid,title,mid)values(13,‘神精是如何炼成’,9);
此时member表中并没有编号为9的成员信息。但由于没有设置约束,所以即使用父表(member)中不存在对应的编号,子表也可以使用,这就是一个错误。
-
实际上,book表中的mid列的内容的取值应该是由member表中的mid列所决定 ,所以现在可以利用外键约束来解决此类问题。在设置外键约束时必须要设置指定外键列(book.mid列)需要和哪张表的哪个列有关联。
-
范例:添加外键
CREATE TABLE book( bid NUMBER, title VARCHAR2(20), mid NUMBER, CONSTRAINTS fk_mid FOREIGN KEY(mid) REFERENCES member(mid) );
-
对外键而言最麻烦的是有一堆的限制。
限制一:在删除父表之前需要先删除掉它对应的全部子表后才可以删除。
范例:member是父表,book是子表,如果没删除book,member表是不能够删除的。
DROP TABLE book;
因此,先删除book,再删除member
列级约束
create table student(
stuno number(3) constraint PK_stuno primary key ,
stuname varchar2(10) constraint NN_stuname not null constraint UQ_stuname unique ,
stuaddress varchar2(20) default '天津' constraint CK_stuaddress
check(length(stuaddress)>2),
stubid number(3)
);
insert into student values(1, 'zzz',default,1) ;
表级约束
create table student2(
stuno number(3) ,
stuname varchar2(10) ,
stusex varchar2(10),
stuaddress varchar2(20) ,
stubid number(3),
constraint PK_sno primary key(stuno) ,
constraint UQ_sname_subid unique(stuname,stubid),
constraint CK_saddress check( length(stuAddress)>2)
);
表级约束只有四个,没有默认和非空 这俩只有列级约束
外键约束补充
-
创建课程表
create table sub( sid number(3) primary key, sname varchar2(10) );
-
添加数据
insert into sub values(1,‘java’);
insert into sub values(2,‘oracle’);
-
创建学生表
create table student3( stuno number(3) , stuname varchar2(10) , stuaddress varchar2(20) , subid number(3) , constraint FK_student3_sub foreign key(subid) references sub(sid) );
-
插入数据:
insert into student3(stuno,stuname,subid) values(1,‘zs’,1);
insert into student3(stuno,stuname,subid) values(2,‘ls’,1);
insert into student3(stuno,stuname,subid) values(3,‘ww’,2); -
尝试插入非法数据:
insert into student3(stuno,stuname,subid) values(4,‘zl’,3);ORA-02291∶违反完整约束条件(SCOTT.FK_STUDENT3_SUB)- 未找到父项关键字
-
sub表和student3
如果删除父表中 外键所指向列的数据,会报错
delete from sub where sid=1;
ORA-02292∶违反完整约束条件(SCOTT.FK_STUDENT3_SUB)- 已找到子记录
级联删除
-
先删除原来的学生表
drop table student3;
-
再重新创建学生表,此时再创建表的同时设置级联删除属性
create table student3(
stuno number(3) ,
stuname varchar2(10) ,
stuaddress varchar2(20) ,
subid number(3) ,
constraint FK_student3_sub foreign key(subid) references sub(sid) on delete cascade
);
-
插入数据
insert into student3(stuno,stuname,subid) values(1,‘zs’,1);
insert into student3(stuno,stuname,subid) values(2,‘ls’,1);
insert into student3(stuno,stuname,subid) values(3,‘ww’,2);
-
删除sub表中sid为2的数据
delete from sub where sid=2 ;
加了联级删除,如果要删除主表数据的话,则会联动子表数据一起被删除
级联置空
-
drop table student3;
-
再重新创建学生表,此时再创建表的同时设置 级联置空属性
create table student3(
stuno number(3) ,
stuname varchar2(10) ,
stuaddress varchar2(20) ,
subid number(3) ,
constraint FK_student3_sub foreign key(subid) references sub(sid) on delete set null
);
-
插入数据
insert into student3(stuno,stuname,subid) values(1,‘zs’,1);
insert into student3(stuno,stuname,subid) values(2,‘ls’,1);
-
删除sub表中sid为1的数据
delete from sub where sid=1 ;
加了联级置空,如果要删除主表数据的话,则会联动子表数据被置空