数据库基础知识

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 DATE DEFAULT 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;--aaaAA
select RPAD('aaaAAAAAA',5,'$') from dual;--aaaAA

select 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;--129位之后第1个who的位置
select Instr('doctor,who,who who who world','who',9,2) from dual;--169位之后第2个who的位置
select Instr('doctor,who,who who world','who',9,3) from dual;--0
0,没找到

四舍五入:
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,保留十位,个位四舍五入,个数补0
select round(45.678,-2) from dual;--0,保留百位,十位四舍五入,结果为0
select round(55.678,-2) from dual;--100,保留百位,十位四舍五入,为100

截取:
select trunc(45.678,2) from dual;--45.67
select trunc(45.678,0) from dual;--45
select trunc(45.678) from dual;--45
select trunc(45.678,-1) from dual;--40
select trunc(45.678,-2) from dual;--0

MOD(m,n):返回m初一n的余数,若n为0则直接返回m(与数学不一样)
select name,salary,mod(salary,1000) from emp;
select mod(3,0) from dual;--0
select mod(3,2) from dual;--1

select 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-21 13:20:29
SELECT TO_CHAR(SYSDATE,'yyyy"年"mm"月"dd"日" hh24:mi:ss') FROM DUAL;
--2015102113: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(date FROM 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优先级高于or
Select * 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 not in('MANAGER','CLERK','SALESMAN');

--下面2句等价
Select * From Emp_Ls Where sal between 1500 and 3000;  
Select * From Emp_Ls Where sal >=1500 and sal <= 3000;

Select * From Emp_Ls Where Sal > Any(1300,4000,4500);
>any 大于最小的
<any小于最大的
>all 大于最大的
<all 小于最小的

去掉重复行
Select distinct job From Emp_Ls;
多列去重,可以达到组合不重复
Select distinct Deptno,job From Emp_Ls;
  ORDER BY只能出现在SELECT语句最后

Select * From Emp_Ls  order by sal;  
Select * From Emp_Ls  order by sal DESC;
desc倒序

Select * From Emp_Ls  order by sal,deptno;
先排sal,sal相同的情况下再排deptno

Select * From Emp_Ls  Order By Sal DESC,Deptno;
先sal降序排,sal相同的话,deptno升序

Select * From Emp_Ls  Order By 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 Group By Deptno;
值相同的deptno看成一组,然后取各组的最大工资,最小工资,平均工资,总和

只要在SELECT中使用了分组函数,那么,
select中其他非分组函数的列若出现,那么也必须同时出现在
group by子句中。
反过来没有限制。

Select Max(Sal),Min(Sal),Avg(Sal),Sum(Sal),Deptno,job
 From Emp_Ls Group By Deptno,job;
若group by中出现了多列,那么就按照
这几列组合值相同的记录看作一组


Select Max(Sal),Min(Sal),Avg(Sal),Sum(Sal),Deptno
 From Emp_Ls Group By Deptno Having Avg(Sal)>1800;
having用于在进行分组查询后,二次过滤数据的。
having不能独立存在,必须跟在group by语句后面。
having中可以使用组函数的结果进行过滤。
与where的区别在于:
where是用于第一次检索数据时过滤的。
having是用于在检索后,进行二次过滤的。

顺序:where... group by... having... order by...

sql优化建议:
from:数据量少的表尽量放后面
where:将能过滤掉最大数量记录的条件写在where子句的最右边
group by: 最好在group by之前使用where将不需要的记录在group by之前过滤掉
having:消耗资源,尽量避免使用(检索出结果之后才对结果集过滤,需要排序等操作)
select:少用*号,尽量使用字段名(解析过程中*号转为所有字段的时候消耗资源)
order by:从左到右排序,消耗资源

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 
Group By 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 Group By Deptno) X
Where E.Deptno=X.Deptno 
And E.Sal > X.Avg_Sal
Order By 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 Order By Empno;

分页标准算法(排序、编号、取范围):
Select * 
From (
    Select Rownum Rn, E.* 
    From(
        Select Empno,Ename,Sal From Emp_Ls order by empno
        ) e
)
Where Rn between 1 and 3;

分页的算法:
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.2
           When 'ANALYST' Then Sal*1.1
           When 'SALESMAN' Then Sal*1.05
           else sal end

  Bonus 
  from emp_ls;
用decode自定义排序:
  Select * From Dept_Ls
  Order By Decode(
    Dname,
     'OPERATIONS',0,
     'ACCOUNTING',1,
     'SALES',2,
     3);

部门号20的看成1组,其他的部门统一看为一组
Select Sum(Sal),Decode(Deptno,20,'20','other') deptno
From Emp_Ls 
Group By Decode(deptno,20,'20','other');

ROW_NUMBER()函数:生成组内连续且唯一的编号。
根据deptno分组,根据每组内的sal排序:
Select Ename ,Sal ,Deptno,
 Row_Number() 
     Over(Partition By Deptno
     Order By Sal Desc) rank
from emp ;

RANK()函数:如果sal一样的话,编号一样
  生成组内不连续且不唯一的编号,
  排序的列若相同,会得到相同的编号
Select Ename ,Sal ,Deptno,
RANK() Over(Partition By Deptno  Order By Sal Desc) Rank
from emp ;


DENSE_RANK()函数:如果sal一样的话,编号一样
  生成组内连续且不唯一的编号,
  排序的列若相同,会得到相同的编号
Select Ename ,Sal ,Deptno,
DENSE_RANK() Over(Partition By Deptno  Order By 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 
 Group By Rollup(Year_Id,Month_Id,Day_Id) 
 order by Year_Id,Month_Id,Day_Id;

GROUP BY CUBE:所有组合的结果都来一遍(一般意义不大)
Select  Year_Id,Month_Id,Day_Id,Sum(Sales_Value) 
 From Sales_Ls 
 Group By cube(Year_Id,Month_Id,Day_Id) 
 order by Year_Id,Month_Id,Day_Id;

GROUPING SETS可指定排序组合(较灵活)
 Select  Year_Id,Month_Id,Day_Id,Sum(Sales_Value) 
 From Sales_Ls 
 Group By 
   GROUPING SETS(
      (Year_Id,Month_Id,Day_Id),
      (Year_Id,Month_Id), 
      (Year_Id)
    ) 
 order by Year_Id,Month_Id,Day_Id;
SELECT * FROM emp_ls;
select * from v_emp_ls;

创建视图:
CREATE VIEW V_EMP_ls as 
  select empno,ename,sal,deptno from emp_ls where deptno=10;

DESC v_emp_ls;
CREATE OR REPLACE:
创建视图,如果视图已经存在就替换掉现有视图:
CREATE OR REPLACE VIEW V_EMP_ls as 
  select empno id,ename name,sal salary,deptno deptno from emp_ls where deptno=10;

若视图已经创建别名,则使用别名来selectselect name from v_emp_ls;

尽量避免使用DML(增删改)操作视图

WITH CHECK OPTION:不符合视图条件的插入语句不允许
(即不允许插入脏数据)
CREATE OR REPLACE VIEW V_EMP_ls as 
  select empno id,ename name,sal salary,deptno deptno from emp_ls where deptno=10
  WITH CHECK OPTION;
INSERT INTO v_emp_ls values(1235,'doctor',4000,20);--此句出错(部门不符合视图条件)

WITH READ ONLY:只读,不允许增删改(DML)
CREATE OR REPLACE VIEW V_EMP_ls as 
  select empno id,ename name,sal salary,deptno deptno from emp_ls where deptno=10
  WITH READ ONLY;

和视图相关的数据字典:
user_objects
user_views
user_update_columns

SELECT object_NAME FROM user_objects WHERE object_type='VIEW';
select * from user_views;

复杂视图:
CREATE VIEW v_emp_salary_ls
AS
SELECT 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
GROUP BY d.dname;

★★复杂视图是不能进行DML操作的★★

删除视图:
DROP VIEW 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 START WITH 100 INCREMENT BY 10;
SELECT emp_seq_ls.NEXTVAL FROM DUAL;
SELECT emp_seq_ls.CURRVAL FROM DUAL;
NEXTVAL:下一个值
CURRVAL :当前值

利用序列将数据插入表
INSERT INTO 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 order by 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;

列级约束
在创建表指定的列的同时声明的约束
CREATE TABLE emp_ls1(
eid NUMBER(6),
name VARCHAR2(30) not null,
salary NUMBER(7,2),
hiredate DATE CONSTRAINT emp_hiredate_nn NOT NULL 
);
NOT NULL只能是列级约束
非空约束加别名:
hiredate DATE CONSTRAINT emp_hiredate_nn NOT NULL 
修改表时添加非空约束:
ALTER TABLE emp_ls1 modify(eid number(6) not null);
去掉非空约束:
ALTER TABLE emp_ls1 modify(eid number(6) null);

唯一性约束UNIQUE:不重复,可为null(null可以多条)
CREATE TABLE emp_ls1(
eid NUMBER(6) UNIQUE,--列级约束
name VARCHAR2(30) not null,
email VARCHAR2(50),
salary NUMBER(7,2),
hiredate DATE,
 CONSTRAINT emp_mail_uk UNIQUE(email) --表级约束,表建好后给email加唯一约束
);

追加约束:
ALTER TABLE emp_ls ADD CONSTRAINT emp_ls_name_uk1111 UNIQUE(ename); 

主键约束:不能为空,同时不可重复
一张表中只能有一个字段加主键约束
永远不要更新主键,尽量建立在单列上
CREATE TABLE emp_ls2(
eid NUMBER(6) PRIMARY KEY,
ename VARCHAR2(30),
email VARCHAR2(50),
salary NUMBER(7,2),
hiredate DATE
);

添加主键(针对无主键的表):
ALTER TABLE emp_ls1 ADD CONSTRAINT emp_idsss_pk PRIMARY KEY(eid);


外键:emp_ls9 的deptno针对 dept的主键deptno
外键允许null,给的值必须在主表上存在,否则不允许插入。
当主表的值被参照时,主表的该行记录不允许被删除。
(实际开发中几乎不用外键约束,基本用程序处理)
ALTER TABLE emp_ls9 ADD CONSTRAINT emp_deptno_fk
foreign KEY(deptno) references dept_ls9(deptno);

检查约束(薪水范围限定,超范围不可插入):
ALTER TABLE emp_ls9 ADD CONSTRAINT emp_salxxx_check CHECK(salary > 2000 AND salary < 4000);
ALTER TABLE emp_ls9 ADD CONSTRAINT emp_salxxx_check CHECK(gender in('男','女'));

删除约束:
ALTER TABLE emp_ls9 DROP CONSTRAINT emp_salxxx_check;

数据字典:
SELECT table_name,constraint_name,constraint_type,search_condition
FROM user_constraints where table_name like 'EMP_LS%';
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值