DML一定会影响数据库中表的数据
数据库对象通常包含表、视图、索引、序列
NUMBER是oracle提供的,表示数字
ename CHAR(n) 固定长度类型,n表示字节量,而不是字符
job VARCHAR2(n) 可变长度类型,VARCHAR2是oracle独有的东西
目前VARCHAR2跟VARCHAR没有任何区别,VARCHAR2特性不变,VARCHAR以后可能会变
DATE 固定7个字节,格式:DD-MON-RR
DESC table_name查看表结构
看到列名,对应的类型,长度等
数据库中的引号表示字符串
数据库中字段无论是什么类型,默认值都是null
若使用default指定了默认值,则使用指定的。
not null约束,创建表的时候,确保字段值不为空
ALTER TABLE emp ADD(hiredate DATEDEFAULT SYSDATE);
ALTER TABLE emp DROP(hiredate);
ALTER TABLE emp MODIFY(id NUMBER(5) );
修改表字段时的注意事项:
1:尽量不修改字段类型
2:字段长度尽量不减少
3:修改后的字段,只对新插入的数据产生影响,
修改前的所有数据不影响
COMMIT 提交事务
ROLLBACK 回滚事务:本次事务中所有的增删改操作全部失效
DROP TABLE emp2;
create table emp2 (
id number(4),
name varchar2(20) NOT NULL,
gender char(1) DEFAULT'M',
salary number(8,2)
);
RENAME emp2 TO emp3;
DELETE FROM emp3;(效率低,可以回退)
TRUNCATE TABLE emp3;(效率高,无法回退)
LONG 在数据库中是字符串
||在数据库中是连接字符串操作,相当于java中的“+”
java中:"hello"+"world" ==> "helloworld"
数据库中:
'hello'||'world' ==> 'helloworld'
或者CONCAT('hello','world') ==> 'helloworld'SELECT'hello'||'world' FROM DUAL;SELECT TO_DATE('2009-12-31','yyyy-mm-dd') FROM DUAL;
DUAL:虚表,没有这个表,只是为了满足SELECT的语法要求
常用虚表来测试表达式的结果。
数据库中,想测试某个表达式的结果只能用SELECT语句实现
什么时候用虚表:当SELECT语句中没有任何表中的字段参与时
拼接显示为1列(2个字段一个冒号)
SELECT name||':'||salary AS abc FROM emp;
或SELECT CONCAT(CONCAT(name,':'),salary) FROM emp;
name字符个数:
select name,length(name) from emp;
大小写:
SELECT UPPER('hello world'),LOWER('HELLO,WORLD'),INITCAP('hello,world') from dual;SELECT UPPER(name),LOWER(name),INITCAP(name) from emp;
trim中from前面的东西只能是单一字符
select trim('e' from 'eeeeetrimeeee') from dual;select trim(' hello ') from dual;--去空白select Ltrim('eeehelloeeee','e') from dual;--去左边select Rtrim('eeehelloeeee','e') from dual;--去右边select Ltrim(' hello ') from dual;--去左边空格select lpad(salary,20,'$') from emp;
作用:要求显示20个字符,若salary值不足长度,左边补若干个$,以达到20个字符
select LPAD('aaaAAAAAA',5,'$') from dual;--aaaAAselect RPAD('aaaAAAAAA',5,'$') from dual;--aaaAAselect substr('abcd5fg hello, world',5,3) from dual;--5fg
从第五个字符开始,连续显示3个字符,(oracle的字符串下标从1开始)
select substr('abcd5fg hello, world',-5,3) from dual;--wor
字符串倒数第5个开始,连续往后连续取3个字符,若干最后一个参数没有,则取到末尾
select Instr('abcd5fg hello, world','hello') from dual;--9
相当于java中的indexOf,即字符串中hello的位置
select Instr('doctor,who,who who who world','who') from dual;--8
who第一次出现的位置
select Instr('doctor,who,who who who world','who',9) from dual;--12
第9位之后第1个who的位置
select Instr('doctor,who,who who who world','who',9,2) from dual;--16
第9位之后第2个who的位置
select Instr('doctor,who,who who world','who',9,3) from dual;--00,没找到
四舍五入:
select round(45.678,2) from dual;--45.68,保留小数后2位,然后四舍五入
select round(45.678,1) from dual;--45.7,保留小数后1位,然后四舍五入
select round(45.678) from dual;--46,保留整数,然后四舍五入
select round(45.678,0) from dual;--46,保留整数,然后四舍五入
select round(45.678,-1) from dual;--50,保留十位,个位四舍五入,个数补0select round(45.678,-2) from dual;--0,保留百位,十位四舍五入,结果为0select round(55.678,-2) from dual;--100,保留百位,十位四舍五入,为100
截取:
select trunc(45.678,2) from dual;--45.67select trunc(45.678,0) from dual;--45select trunc(45.678) from dual;--45select trunc(45.678,-1) from dual;--40select trunc(45.678,-2) from dual;--0MOD(m,n):返回m初一n的余数,若n为0则直接返回m(与数学不一样)
select name,salary,mod(salary,1000) from emp;
selectmod(3,0) from dual;--0selectmod(3,2) from dual;--1select ceil(4.5) from dual;--5,比4.5大的最小的整数
select floor(4.5) from dual;--4,比4.5小的最大的整数
DATE:可表示公元前4712年-9999年之间的日期,7 字节(分别为世纪、年月日时分秒)
TIMESTAMP:11个字节,前7个字节跟date相同,后4个字节表示纳秒
SYSDATE:当前系统时间,精确到秒
SYSTIMESTAMP:内部函数,当前系统时间,精确毫秒
TO_DATE
select to_date('2014-12-31 23:13:44','yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR:
SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss') FROM DUAL;
--2015-10-2113:20:29SELECT TO_CHAR(SYSDATE,'yyyy"年"mm"月"dd"日" hh24:mi:ss') FROM DUAL;
--2015年10月21日 13:18:53
“年月日”不是特殊字符或者符号,需要加双引号,否则出错。
2个日期可以做减法运算,差为相差的天数
SELECT SYSDATE-hiredate, hiredate,name from emp;
SELECT SYSDATE-hiredate, TRUNC(SYSDATE-hiredate),hiredate, name from emp2;
LAST_DAY:括号里日期所在月的最后一天
SELECT LAST_DAY(sysdate) FROM DUAL;
SELECT LAST_DAY(TO_DATE('2014-02-15','yyyy-mm-dd')) FROM DUAL;SELECT LAST_DAY('09-3月-14') FROM DUAL;
ADD_MONTHS(date,i):返回date加上1个月后的日期
SELECT name,hiredate,ADD_MONTHS(hiredate,20*12) as"20周年"FROM emp2;
SELECT name,hiredate,ADD_MONTHS(hiredate,1) FROM emp2;
MONTHS_BETWEEN(date1,date2)计算2个日期之间隔了多少个月(date1-date2)
SELECT name,MONTHS_BETWEEN(SYSDATE,hiredate) FROM emp2;
NEXT_DAY(date,char):返回离date之后最近的周几的日期
SELECT NEXT_DAY(SYSDATE,4) AS"near_Wedn"FROM DUAL;
--返回离系统时间最近的周三的日期(周日是1)
GREATEST()最大值
LEAST()最小值 参数要一致才可以比较,可传多个参数
SELECT LEAST(SYSDATE,'10-10月-08') FROM DUAL;
EXRACT(dateFROM datetime),提取date指定的年月日等
SELECT EXTRACT(YEAR FROM SYSDATE) Currentyear FROM DUAL;
SELECT EXTRACT(HOUR FROM TIMESTAMP '2009-10-29 23:30:00') FROM DUAL;
NULL跟任何数据计算结果都为NULL,若跟字符串拼接的话还是那个字符串
NVL(expr1,expr2),如果参数1是null,就返回参数2的值,否则返回参数1(参数2是参数1的替补)
SELECT name,NVL(gender,'M') from emp2;SELECT name salary,NVL(comm,0) FROM EMP2;
SELECT name,salary+comm FROM EMP2;--null跟数字计算结果为null
SELECT name,salary+NVL(comm,0) FROM EMP2;
NVL2:若不是null,显示为有奖金;若是null,显示无奖金
SELECT name,NVL2(comm,'有奖金','没奖金') FROM emp2;SELECT name,NVL2(comm,salary,salary) FROM emp2;
别名:
SELECT ename id FROM emp_ls;
SELECT ename "i d"FROM emp_ls;--加双引号,别名为小写
--表达式用别名来显示,可增加可读性
Select To_Char(Hiredate,'yyyy-mm-dd') Hiredate From Emp_Ls;
>, <, >=, <=, !=, <>, =(不等于通用符号为<>)
Select * From Emp_Ls Where Hiredate > To_Date('1981-12-31','yyyy-mm-dd') and sal > 1000;
Select * From Emp_Ls Where job='CLERK' or Sal > 2000;and优先级高于orSelect * From Emp_Ls Where job='CLERK' and Sal > 1300 or job='SALESMAN';
上一句等价于下一句:
Select * From Emp_Ls Where (job='CLERK' and Sal > 1300) or job='SALESMAN';Select * From Emp_Ls Where Ename Like'_A%';
--第二个是大写A,后面多少无所谓(一个下划线“_”代表一个模糊字符)
Select * From Emp_Ls Where Job='MANAGER' Or Job='CLERK' Or Job='SALESMAN';Select * From Emp_Ls Where job in('MANAGER','CLERK','SALESMAN');Select * From Emp_Ls Where job notin('MANAGER','CLERK','SALESMAN');
--下面2句等价
Select * From Emp_Ls Where sal between 1500and3000;
Select * From Emp_Ls Where sal >=1500and sal <= 3000;
Select * From Emp_Ls Where Sal > Any(1300,4000,4500);
>any 大于最小的
<any小于最大的
>all 大于最大的
<all 小于最小的
去掉重复行
Selectdistinct job From Emp_Ls;
多列去重,可以达到组合不重复
Selectdistinct Deptno,job From Emp_Ls;
ORDERBY只能出现在SELECT语句最后
Select * From Emp_Ls orderby sal;
Select * From Emp_Ls orderby sal DESC;
desc倒序
Select * From Emp_Ls orderby sal,deptno;
先排sal,sal相同的情况下再排deptno
Select * From Emp_Ls OrderBy Sal DESC,Deptno;
先sal降序排,sal相同的话,deptno升序
Select * From Emp_Ls OrderBy Sal,Deptno DESC;
先sal升序排,sal相同的话,deptno降序
若sal没有重复,第二列的排序会被忽略
多行数据参与运算返回一行结果,也称为分组函数、多行函数、集合函数。
Select Max(Sal) max_sal, Min(sal) min_sal From Emp_Ls;
Select Max(hiredate) late_hire, Min(hiredate) early_hire From Emp_Ls;
日期越大,时间越近。日期越小,入职越早
max和min不可以在where中使用
-------------------------------------------------
Select Avg(comm),Sum(Sal) From Emp_Ls;
avg(comm)聚合函数忽略空值(平均奖金仅仅除以了非空个数)
解决办法:
Select Avg(NVL(comm,0)),Sum(comm) From Emp_Ls;
Select Count(*) From emp_ls;
Select Count(*) From emp_ls where deptno=30;
Select Max(Sal),Min(Sal),Avg(Sal),Sum(Sal),Deptno
From Emp_Ls GroupBy Deptno;
值相同的deptno看成一组,然后取各组的最大工资,最小工资,平均工资,总和
只要在SELECT中使用了分组函数,那么,
select中其他非分组函数的列若出现,那么也必须同时出现在
groupby子句中。
反过来没有限制。
Select Max(Sal),Min(Sal),Avg(Sal),Sum(Sal),Deptno,job
From Emp_Ls GroupBy Deptno,job;
若groupby中出现了多列,那么就按照
这几列组合值相同的记录看作一组
Select Max(Sal),Min(Sal),Avg(Sal),Sum(Sal),Deptno
From Emp_Ls GroupBy Deptno Having Avg(Sal)>1800;
having用于在进行分组查询后,二次过滤数据的。
having不能独立存在,必须跟在groupby语句后面。
having中可以使用组函数的结果进行过滤。
与where的区别在于:
where是用于第一次检索数据时过滤的。
having是用于在检索后,进行二次过滤的。
顺序:where... groupby... having... orderby...
sql优化建议:
from:数据量少的表尽量放后面
where:将能过滤掉最大数量记录的条件写在where子句的最右边
groupby: 最好在groupby之前使用where将不需要的记录在groupby之前过滤掉
having:消耗资源,尽量避免使用(检索出结果之后才对结果集过滤,需要排序等操作)
select:少用*号,尽量使用字段名(解析过程中*号转为所有字段的时候消耗资源)
orderby:从左到右排序,消耗资源
n张表联合查询至少要n-1个连接条件
Select Ename, A.Deptno,Dname From Emp_Ls A,Dept_Ls B
Where A.Deptno=B.Deptno;
2张表中重复的字段名需要加"别名.",例如: A.Deptno,
好的习惯最好都加上别名。
Select Ename, sal, A.Deptno,Dname From Emp_Ls A,Dept_Ls B
Where A.Deptno=B.Deptno And a.sal>3000;
Select Ename, A.Deptno,Dname From Emp_Ls A,Dept_Ls B
Where A.Deptno=B.Deptno
and A.Deptno=(select Deptno from Emp_Ls where ename='FORD'); Select A.Ename, A.Sal, A.Deptno,B.Dname From Emp_Ls A,Dept_Ls B
Where A.Deptno=B.Deptno And B.dname='SALES';
内连接(跟上面等价):
select e.ename ,d.dname from emp_ls e JOIN dept_ls d on (e.Deptno=d.Deptno);
自然连接:自动寻找2张表列名相同的做等值连接。
(需要保证2张表中只有一列名字一样,
如果有2个或者2个以上的列名一样的话则不能使用自然连接):
select e.ename ,d.dname from emp_ls e natural JOIN dept_ls d;
外连接的应用场景:
当我们查看部门表时,因为在进行与emp连接查询
时,40号部门不存在任何员工,导致查询结果该记录被忽略。
这时,我们需要主要查看部门有哪些时,就使用外连接。
left OUTER JOIN 左外连接:左边的表内容全列出来,右边表没有的则补null
RIGHT OUTER JOIN 右外连接:右边的表内容全列出来,左边表没有的则补null
full Outer Join 全外连接:两边所有的都显示出来,哪边不足哪边补null
Select E.Ename ,D.Dname From Emp_Ls E left OUTER JOIN Dept_Ls D On (E.Deptno=D.Deptno);
Select E.Ename ,D.Dname From Emp_Ls E RIGHT OUTER JOIN Dept_Ls D On (E.Deptno=D.Deptno);
Select D.Dname,E.Ename From Emp_Ls E full Outer Join Dept_Ls D On (E.Deptno=D.Deptno);
自连接:
Select E.Ename||'的领导是'||M.Ename From Emp_Ls E,Emp_Ls M Where E.Mgr=M.Empno;
---------------------------------------
子查询:
当前查询需要建立在另一个查询结果基础之上,
这里就要利用到子查询。
单行单列 和 多行单列子查询通常用在where子句中
多行多列子查询通常用在from子句中
单行单列
Select Ename,Sal,Deptno From Emp_Ls Where Deptno=
(Select Deptno From Emp_Ls Where Ename='SCOTT')And Ename<>'SCOTT';Select Ename,Sal,Deptno From Emp_Ls Where sal>
(Select sal From Emp_Ls Where Ename='SCOTT');
> < >= <= = <> 这些都只能使用单行单列子查询
Select Ename,Sal From Emp_Ls Where Sal<
(Select AVG(sal) From Emp_Ls);
Select Ename,Sal,Deptno From Emp_Ls Where Deptno In
(Select Deptno From Emp_Ls Where Job='SALESMAN')and job<>'SALESMAN';Select Ename,Sal,Deptno From Emp_Ls Where Sal>
all(select sal from emp_ls where job='SALESMAN');
Exists:只要子查询结果为true(即能查到数据)就显示外面select语句的结果
Select Deptno,Dname From Dept_Ls D Where Exists
(Select * From Emp_Ls E Where D.Deptno=E.Deptno);
比30号部门最低工资高的部门
Select Min(Sal),deptno From Emp_Ls
GroupBy Deptno Having Min(Sal) >
(Select Min(Sal) from emp_ls where deptno=30);
Select E.Deptno,E.Ename,E.Sal From Emp_Ls E,
(Select Deptno,Avg(Sal) Avg_Sal From Emp GroupBy Deptno) X
Where E.Deptno=X.Deptno
And E.Sal > X.Avg_Sal
OrderBy E.Deptno;
子查询结果当作表看待,子查询中的函数或表达式一定要加别名。
Select Ename,Sal,
(Select Dname From Dept_Ls D Where D.Deptno=E.Deptno)
from emp_ls e;
外连接的一种表现,不常用,实际就是左连接
Select Rownum Empno,Ename,Sal From Emp_Ls;
Select Rownum Empno,Ename,Sal From Emp_Ls Where Rownum <=5;
-----------------------------------------------
Select Rownum Empno,Ename,Sal From Emp_Ls Where Rownum >3;(无结果)
rownum是当oracle进行select查询表数据时,
确定一条数据需要时,才会对其进行编号(伪劣的值),
这就导致,没有数据被查处前,rownum永远没有值。
所以rownum不能在第一次查询时作为where条件。
rownum:有了数据才有值
where里出现:有值才有数据
所以这里有一个矛盾
Select * From
(Select Rownum Rn, E.* From Emp E)
where rn >3;(有结果)
分页的三步:
1:排序
2:编号
3:取范围
Select Empno,Ename,Sal From Emp_Ls OrderBy Empno;
分页标准算法(排序、编号、取范围):
Select *
From (
Select Rownum Rn, E.*
From(
Select Empno,Ename,Sal From Emp_Ls orderby empno
) e
)
Where Rn between 1and3;
分页的算法:
int start : (page-1)*pagesize+1;
int end : page*pagesize;
DECODE(类似java中的switch case):
Select Ename,Job,Sal,
Decode(Job,
'MANAGER',Sal*1.2,'ANALYST',Sal*1.1,'SALESMAN',sal*1.05,
sal
) Bonus
from emp_ls;
或者:
Select Ename,Job,Sal,
Case Job when'MANAGER' then Sal*1.2When'ANALYST' Then Sal*1.1When'SALESMAN' Then Sal*1.05else sal end
Bonus
from emp_ls;
用decode自定义排序:
Select * From Dept_Ls
OrderBy Decode(
Dname,
'OPERATIONS',0,'ACCOUNTING',1,'SALES',2,3);
部门号20的看成1组,其他的部门统一看为一组
Select Sum(Sal),Decode(Deptno,20,'20','other') deptnoFrom Emp_Ls
GroupBy Decode(deptno,20,'20','other');
ROW_NUMBER()函数:生成组内连续且唯一的编号。
根据deptno分组,根据每组内的sal排序:
Select Ename ,Sal ,Deptno,
Row_Number()
Over(Partition By Deptno
OrderBy Sal Desc) rank
from emp ;
RANK()函数:如果sal一样的话,编号一样
生成组内不连续且不唯一的编号,
排序的列若相同,会得到相同的编号
Select Ename ,Sal ,Deptno,
RANK() Over(Partition By Deptno OrderBy Sal Desc) Rank
from emp ;
DENSE_RANK()函数:如果sal一样的话,编号一样
生成组内连续且不唯一的编号,
排序的列若相同,会得到相同的编号
Select Ename ,Sal ,Deptno,
DENSE_RANK() Over(Partition By Deptno OrderBy Sal Desc) Rank
from emp ;
select ename ,job,sal from emp
where job='MANAGER'
UNION
select ename ,job,sal from emp
where sal>2500;
UNION:并集
UNION ALL:全并集
INTERSECT:交集
MINUS:差集
Select Ename ,Job,Sal From Emp
Where Job='MANAGER'
INTERSECT
Select Ename ,Job,Sal From Emp
where sal>2500 ;
ROLLUP等价于同一日分1次组,同月分1次组,
同年分一组,所有的分为1组,取sum(Sales_Value)的值
Select Year_Id,Month_Id,Day_Id,Sum(Sales_Value)
From Sales_Ls
GroupBy Rollup(Year_Id,Month_Id,Day_Id)
orderby Year_Id,Month_Id,Day_Id;
GROUPBY CUBE:所有组合的结果都来一遍(一般意义不大)
Select Year_Id,Month_Id,Day_Id,Sum(Sales_Value)
From Sales_Ls
GroupBy cube(Year_Id,Month_Id,Day_Id)
orderby Year_Id,Month_Id,Day_Id;
GROUPING SETS可指定排序组合(较灵活)
Select Year_Id,Month_Id,Day_Id,Sum(Sales_Value)
From Sales_Ls
GroupBy
GROUPING SETS(
(Year_Id,Month_Id,Day_Id),
(Year_Id,Month_Id),
(Year_Id)
)
orderby Year_Id,Month_Id,Day_Id;
SELECT * FROM emp_ls;select * from v_emp_ls;
创建视图:
CREATEVIEW V_EMP_ls asselect empno,ename,sal,deptno from emp_ls where deptno=10;
DESC v_emp_ls;
CREATEORREPLACE:
创建视图,如果视图已经存在就替换掉现有视图:
CREATEORREPLACEVIEW V_EMP_ls asselect empno id,ename name,sal salary,deptno deptno from emp_ls where deptno=10;
若视图已经创建别名,则使用别名来select:
select name from v_emp_ls;
尽量避免使用DML(增删改)操作视图
WITH CHECK OPTION:不符合视图条件的插入语句不允许
(即不允许插入脏数据)
CREATEORREPLACEVIEW V_EMP_ls asselect empno id,ename name,sal salary,deptno deptno from emp_ls where deptno=10WITHCHECKOPTION;INSERTINTO v_emp_ls values(1235,'doctor',4000,20);--此句出错(部门不符合视图条件)
WITH READ ONLY:只读,不允许增删改(DML)
CREATEORREPLACEVIEW V_EMP_ls asselect empno id,ename name,sal salary,deptno deptno from emp_ls where deptno=10WITHREADONLY;
和视图相关的数据字典:
user_objects
user_views
user_update_columns
SELECT object_NAME FROM user_objects WHERE object_type='VIEW';select * from user_views;
复杂视图:
CREATEVIEW v_emp_salary_ls
ASSELECT d.dname ,avg(e.sal) avg_sal,sum(e.sal) sum_sal,
max(e.sal) max_sal,min(e.sal) min_sal
FROM emp_ls e join dept_ls d
ON e.deptno=d.deptno
GROUPBY d.dname;
★★复杂视图是不能进行DML操作的★★
删除视图:
DROPVIEW v_emp_salary_ls;-------------------------------------
序列:
UUID 32位不重复
SELECT sys_guid() FROM DUAL;
java中生成uuid:
import java.util.UUID;
public class Test {
public static void main(String[] args) {
String uuid= UUID.randomUUID().toString();
System.out.println(uuid);
}
}
CREATE SEQUENCE emp_seq_ls STARTWITH100 INCREMENT BY10;SELECT emp_seq_ls.NEXTVAL FROM DUAL;SELECT emp_seq_ls.CURRVAL FROM DUAL;
NEXTVAL:下一个值
CURRVAL :当前值
利用序列将数据插入表
INSERTINTO emp_ls (empno,ename,sal,deptno)
values (emp_seq_ls.NEXTVAL,'JACK',5000,50);
删除序列:
DROP SEQUENCE emp_seq;
不是所有数据库都支持序列
索引:
oracle自动维护,树形结构,为了加快检索效率
索引指定的列通常是在查询时where中经常出现的列。
检索时自动去找索引,不需要指定索引
CREATE INDEX idx_emp_ename ON emp_ls(ename);
若经常order by job,sal 作为排序依据,可建立复合索引:
CREATE INDEX idx_emp_job_sal09 ON emp_ls(job,sal);
当做下面的查询时,会自动引用索引idx_emp_job_sal09
select empno,ename,sal,job from emp_ls orderby job,sal;
若经常使用ename的大小写无关搜索:
CREATE INDEX emp_ename_uppser_idx09 ON emp_ls(Upper(ename));SELECT * FROM EMP WHERE UPPER(ENAME)='KING';
如果执行了DML操作,需要定期重建索引,提高索引的空间利用率:
ALTER INDEX emp_ename_uppser_idx09 REBUILD;
删除索引:
drop index emp_ename_uppser_idx09;
列级约束
在创建表指定的列的同时声明的约束
CREATETABLE emp_ls1(
eid NUMBER(6),
name VARCHAR2(30) notnull,
salary NUMBER(7,2),
hiredate DATECONSTRAINT emp_hiredate_nn NOTNULL
);
NOT NULL只能是列级约束
非空约束加别名:
hiredate DATE CONSTRAINT emp_hiredate_nn NOT NULL
修改表时添加非空约束:
ALTERTABLE emp_ls1 modify(eid number(6) notnull);
去掉非空约束:
ALTERTABLE emp_ls1 modify(eid number(6) null);
唯一性约束UNIQUE:不重复,可为null(null可以多条)
CREATETABLE emp_ls1(
eid NUMBER(6) UNIQUE,--列级约束
name VARCHAR2(30) notnull,
email VARCHAR2(50),
salary NUMBER(7,2),
hiredate DATE,
CONSTRAINT emp_mail_uk UNIQUE(email) --表级约束,表建好后给email加唯一约束
);
追加约束:
ALTERTABLE emp_ls ADDCONSTRAINT emp_ls_name_uk1111 UNIQUE(ename);
主键约束:不能为空,同时不可重复
一张表中只能有一个字段加主键约束
永远不要更新主键,尽量建立在单列上
CREATETABLE emp_ls2(
eid NUMBER(6) PRIMARYKEY,
ename VARCHAR2(30),
email VARCHAR2(50),
salary NUMBER(7,2),
hiredate DATE
);
添加主键(针对无主键的表):
ALTERTABLE emp_ls1 ADDCONSTRAINT emp_idsss_pk PRIMARYKEY(eid);
外键:emp_ls9 的deptno针对 dept的主键deptno
外键允许null,给的值必须在主表上存在,否则不允许插入。
当主表的值被参照时,主表的该行记录不允许被删除。
(实际开发中几乎不用外键约束,基本用程序处理)
ALTERTABLE emp_ls9 ADDCONSTRAINT emp_deptno_fk
foreignKEY(deptno) references dept_ls9(deptno);
检查约束(薪水范围限定,超范围不可插入):
ALTERTABLE emp_ls9 ADDCONSTRAINT emp_salxxx_check CHECK(salary > 2000AND salary < 4000);ALTERTABLE emp_ls9 ADDCONSTRAINT emp_salxxx_check CHECK(gender in('男','女'));
删除约束:
ALTERTABLE emp_ls9 DROPCONSTRAINT emp_salxxx_check;
数据字典:
SELECT table_name,constraint_name,constraint_type,search_condition
FROM user_constraints where table_name like'EMP_LS%';