您的位置:首页 > 数据库

数据库(个人学习笔记,不断更新修改中)

2015-07-11 11:49 441 查看
SQL可分为:

1,数据定义语言(DDL) : Data Definition Language

CREATE TABLE创建表,

ALTER TABLE修改表,

DROP TABLE删除表等动作

2,数据操纵语言(DML) : Data Manipulation Language

INSERT语句用于将数据插入到数据库中,

UPDATE语句用于更新数据库中已存在的数据,

DELETE用于删除数据库中已存在的数据

3,事务控制语言(TCL):Transaction Control Language

COMMIT用来确认已经进行的数据库改变,

ROLLBACK语句用来取消已经进行的数据库改变

SAVEPOINT语句用来设置保存点,使当前的事务可以回退到指定的保存点,便于取消部分改变

4,数据查询语言(DQL):Data Query Language

SELECT用来查询所需要的数据。使用最广泛,语法灵活复杂。

5,数据控制语言(DCL) : Data Control Language

GRANT用于给用户或角色授予权限,

REVOKE用于收回用户或角色已有的权限。

CREATE USER语句

Oracle数据类型

NUMBER(6,2)表示数字类型/NUMBER(2)

CHAR(20)表示固定长度的字符类型

VARCHAR2(100);表示变长的字符类型

DATE定义日期时间的数据

创建表:CREATE TABLE emp()

查看表格结构:DESC emp

查看表中数据:SELECT * FROM emp1_liuwenshou 查看表中数据(把*号换成字段号,字段号可以查看指定字段的数据)

查看表中指定字段数据:SELECT ename,job,sal FROM myemp1_liuwenshou

删除表格:DROP TABLE emp

赋默认值:DEFAULT ‘M’

非空(NOT NULL)

修改表名:RENAME old_name TO new_name;

增加列:ALTER TABLE employee ADD (hiredate DATE DEFAULT sysdate);

删除列:ALTER TABLE employee DROP (hiredate);

修改列:ALTER TABLE employee MODIFY(job VARCHAR2(40) DEFAULT 'CLERK' );

插入列:INSERT INTO employee(id, name, job, birth)

VALUES(1003, 'donna', 'MANAGER', TO_DATE('1978-09-01', 'YYYY-MM-DD'))

更新记录:UPDATE employee SET salary = 8500,gender='F' WHERE name = 'ROSE';

删除记录:DELETE FROM employee WHERE job is null;

字符串类型

SELECT CONCAT(ename,job) FROM myemp1_liuwenshou;在数据库中返回ename和job在同一个字段

SELECT CONCAT(CONCAT(ename,':'),job) FROM myempq_liuwenshou;在数据中返回ename和job在同一个字段,并且中间用:连接

SELECT ename||‘:’||sal FROM myempq_liuwenshou;在数据中返回ename和sal在同一个字段,并且中间用:连接

SELECT ename, LENGTH(name) FROM emp; 将列出name和name的字符串长度

SELECT UPPER('hello') FROM myemp1_liuwenshou;将字符转换为大写形式

SELECT LOWER('HELLO WORLD') FROM DUAL;将字符转换为小写形式

SELECT INITCAP('hello world') FROM DUAL;将字符串中每个单词的首字符大写,其它字符小写,单词之间用空格和非字母字符分隔

SELECT TRIM('e' from 'elite')FROM DUAL;表示从elite的前后截去e,e只能为单个字符

SELECT RTRIM('eeeefuckeqeeeeeqqq','eq') FROM DUAL;表示从eeeefuckeqeeeeeqqq右边截去e/q/eq/qe字符

SELECT LTRIM('eqqqeeeefuckeqeeee','eq') FROM DUAL;表示从eeeefuckeqeeeeeqqq左边截去e/q/eq/qe字符

SELECT ename,LPAD(sal,6,‘¥’) FROM emp_liuwenshou;把sal变成6个字符,不足的话用左边的¥补齐6,右边只能为单个字符

SELECT ename,RPAD(sal,6,‘¥’) FROM emp_liuwenshou;把sal变成6个字符,不足的话用右边的¥补齐6,左边只能为单个字符

SELECT SUBSTR('Doctor Who travels in TARDIS', 8, 3)FROM DUAL;//Who 在一个字符串中第8位开始连续截取3个数子串,8可以为负数

SELECT INSTR('think in java in my life','in',2,3)FROM DUAL;//15//从第2个字符开始检索in第3次出现的位置

数值函数

ROUND(n[, m])//SELECT ROUND(45.678,2) FROM DUAL //用于将参数n按照m的数字要求四舍五入,m可取(正,0,负)(- .+)

TRUNC(n[, m])//SELECT TRUNC(45.51,-1)FROM DUAL//的功能是截取,其中n和m的定义和ROUND(n[, m])相同

MOD(m, n)是取模函数//SELECT ename,sal,MOD(sal,1000)FROM myemp1_liuwenshou//返回m除以n后的余数,如果n为0则直接返回m

CEIL(n),//SELECT CEIL(45.678) FROM DUAL; --46/取大于n的最小整数

FLOOR(n)//SELECT FLOOR(45.678) FROM DUAL;//,取小于n的最大整数

日期类型

LECT SYSDATE FROM DUAL;//显示当前时间//将显示“03-MAY-14”的形式,如果是中文环境,将显示“03-5月-14”的形式。

SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd day hh24:mi:ss') FROM DUAL;//显示当前时间//年-月-日 星期1 13:57:32

SELECT SYSTIMESTAMP FROM DUAL;//显示当前时间,精确到毫秒

SELECT TO_CHAR(SYSTIMESTAMP,'SSSS.FF') FROM DUAL;

日期转换函数

TO_DATE(char[, fmt[, nlsparams]]);//SELECT ename, TO_CHAR(hiredate, 'YYYY"年"MM"月"DD"日"') FROM emp;L//08-8月 -08

SELECT ename,sydate-hiredate FROM emp;//计算员工入职到现在多少天

SELECT sysdate-TO_DATE('1990-06-03','YYYY-MM-DD')FROM DUAL//计算出生多少天

SELECT TO_CHAR(sysdate,'YYYY-MM-DD')FROM DUAL//将当前时间以指定格式输出('YYYY-MM-DD'==2015-05-18)('YYYY"年"MM"月"DD"日"'==2015年05月18日)

SELECT TO_CHAR(TO_DATE('09-05-20','RR-MM-DD'),'YYYY-MM-DD')FROM DUAL//显示给定时间的世纪

SELECT LAST_DAY('20-2月-09') FROM DUAL;//查询09年2月的最后一天

SELECT ename, ADD_MONTHS(hiredate, 20 * 12) "20周年" FROM emp;//返回日期date加上i个月后的日期值//计算职员入职20周年纪念日:

SELECT ename,MONTH_BETWEEN(date1, date2) FROM emp://计算date1和date2两个日期值之间间隔了多少个月

SELECT NEXT_DAY(SYSDATE, i) FROM DUAL;//查询下个星期i是几号

SELECT LLEAST(expr1[, expr2[, expr3]]…) FROM DUAL//返回结果是参数列表中最小值

SELECT GREATEST(expr1[, expr2[, expr3]]…) FROM DUAL//返回结果是参数列表中最大值

SELECT EXTRACT(YEAR FROM SYSDATE) FROM DUAL;//取出当前日期的年

SELECT EXTRACT(HOUR FROM SYSTIMESTAMP) FROM DUAL;//取出当前日期的小时

SELECT EXTRACT(HOUR FROM TIMESTAMP '2008-10-10 10:10:10') FROM DUAL;取出指定时间的小时

空值操作

UPDATE student SET gender = NULL; //全表gender都被更新为null

SELECT * FROM mystudent_liuwenshou WHERE gender IS NULL;//用“列名 IS NOT NULL”来查询空数据。

SELECT * FROM mystudent_liuwenshou WHERE gender IS NOT NULL;//用“列名 IS NOT NULL”来查询非空数据。

空值函数

NVL(expr1, expr2):将NULL转变为非NULL值

SELECT ename, sal, comm, sal + NVL(comm, 0) FROM emp;//将取NULL值的comm列转换为0再进行运算,结果就不会为NULL了

SELECT ename,NVL2(comm,'有奖金','没奖金') FROM myemp1_liuwenshou//comm值不为NULL返回有奖金,为NULL返回没奖金

WHERE子句

在SELECT语句中使用WHERE子句可以添加过滤条件,当我们添加了WHERE后,数据库在检索对应的表时,会将表中每一条数据取出后使用WHERE进行判断,查看这条记录

中的字段值是否满足WHERE的要求,满足的话,这条记录将被查询出来,不满组就忽略。

WHERE是在第一次查询表中数据时进行过滤。***********************************************************************************************

所以表中有多少条数据,WHERE就会被执行几次,WHERE是在查询表中数据的时候被使用的

>:大于

< :小于

>= :大于等于

<=:小于等于

< >:不等于(!=,)数据库不等于常用< >,

= :等于

AND :相当于java中的 && 且

OR : 相对于java中的 || 或

AND的优先级是高于OR的

LIKE条件

%:表示0到多个字符

_:标识单个字符

eg:SELECT ename, job FROM emp WHERE ename LIKE '_A%';//查询职员姓名中第二个字符是‘A’的员工信息

IN和NOT IN 可以理解为一个范围比较操作符

SELECT ename, job FROM emp WHERE job IN ('MANAGER', 'CLERK');//查询职位是MANAGER或者CLERK的员工

IN通常被利用在子查询中,所以IN的功能不能被OR完全代替

SELECT ename, job FROM emp WHERE deptno NOT IN (10, 20);//查询不是部门10或20的员工

BETWEEN…AND…操作符用来查询符合某个值域范围条件的数据

SELECT ename, sal FROM emp WHERE sal BETWEEN 1500 AND 3000;//查询薪水在1500-3000之间的职员信息

ANY和ALL条件

> ANY(list):大于列表中最小的即可

< ANY(list):小于列表中最大的即可

> ALL(list):大于列表中最大的即可

< ALL(list):小于列表中最小的即可

ANY与ALL通常是用在判断一个子查询结果,几乎不会在列表中给定值,否则没什么意思

eg:查看比20号部门工资都高的员工有谁

SELECT ename,sal,deptin

FROM lwsemp

WHERE sal > ALL(SELECT sal FROM lwsemp WHERE deptin=20)

查询条件中使用表达式和函数

select ename,sal from myemp1_liuwenshou where UPPER(ename) = upper('ward')//名字为WARD的

SELECT ename,sal FROM myemp1_liuwenshou WHERE sal*12>50000//年薪大于50000的

DISTINCT过滤重复,会将其后定义的字段中重复的记录去除掉

SELECT DISTINCT job FROM myemp1_liuwenshou --查看公司有哪些职位

多列去重:当DISTINCT 后面有多个重复的时候,后面字段值没有的重复的输出

SELECT DISTINCT job,deptin FROM myemp1_liuwenshou//eg:1,1~2,2-3,3,3~2,3~3,3~4

DISTINCT只与SELECT连接

ORDER BY字句 :询出的数据按一定规则进行排序操作 NULL为最大值

ASC用来指定升序排序,DESC用来指定降序排序

SELECT <*, column [alias], …> FROM table [WHERE condition(s)] [ORDER BY column [ASC | DESC]] ;默认ASC,

eg:SELECT ename,sal FROM myemp1_liuwenshou ORDER BY sal//按工资升序排列 最后面加DESC按照将需排列

ORDER BY 也可以按照多个字段排序,每个字段都需要单独指定升序将需(有优先级的,第一次排列相同字段再拍第二级排列)

eg:SELECT ename,deptin,sal FROM myemp1_liuwenshou ORDER BY deptin DESC,sal

聚合函数:又叫做分组函数,多行函数。可以将一组数据进行统计然后得出一个结果。

MAX和MIN:取该列的最大值,最小值 只能操作数字类型,忽略NULL值

SELECT MAX(sal) max_sal, MIN(sal) min_sal FROM myemp1_liuwenshou;//获取机构下的最高薪水和最低薪水

AVG和SUM求平均值和总和 忽略null值的,如果有null值的,求平均值的时候需转换为0

SELECT AVG(NVL(sal,0)),SUM(sal) FROM myemp1_liuwenshou

COUNT函数用来计算表中的记录条数,同样忽略NULL值

SELECT COUNT(ename) FROM myemp1_liuwenshou//为了避免null值,ename用*代替可准确的查看表中有多少条目

SELECT COUNT(*) FROM myemp1_liuwenshou

分组

GROUP BY子句:需要把整个数据表按部门划分成一个个小组,每个小组中包含一行或多行数据,在每个小组中再使用分组函数进行计算,每组返回一个结果

通常GROUP BY子句中出现的字段应当是重复值较多的,否则分组没有意义

SELECT AVG(sal),deptin FROM myemp1_liuwenshou GROUP BY deptin--按部门计算平均工资 (前面能加deptin是因为该分组中deptin值相同)

HAVING字句,必须跟在GROUP BY后面

SELECT deptno, MAX(sal) max_sal FROM emp GROUP BY deptno HAVING MAX(sal) >4000;

//查询每个部门的最高薪水,只有最高薪水大于4000的记录才被输出显示

SELECT AVG(sal),deptin FROM myemp1_liuwenshuou GROUP BY deptin HAVING MAX(sal)>4500//按照部门最高工资大于4500的部门的平均工资

当一条查询语句中包含所有的子句,执行顺序依下列子句次序:

FROM 子句:执行顺序为从后往前、从右到左。数据量较少的表尽量放在后面。

WHERE子句:执行顺序为自下而上、从右到左。将能过滤掉最大数量记录的条件写在WHERE 子句的最右。

WHERE语句中不能限制分组结果

GROUP BY:执行顺序从左往右分组,最好在GROUP BY前使用WHERE将不需要的记录在GROUP BY之前过滤掉。

HAVING 子句:消耗资源。尽量避免使用,HAVING 会在检索出所有记录之后才对结果集进行过滤,需要排序等操作。

SELECT子句:少用*号,尽量取字段名称。ORACLE 在解析的过程中, 通过查询数据字典将*号依次转换成所有的列名, 消耗时间。

ORDER BY子句:执行顺序为从左到右排序,消耗资源。

关联的概念

eg:查看SALES部门工作的员工的所有名字

SELECT e.ename,d.dname

FROM myemp1_liuwenshou e,mydep1_liuwenshou d --标名太长,可在FROM语句中取别名便于其他代码中书写

WHERE e.deptin=d.depton

AND d.dname='SALES'

查询时,若使用N张表联合查询,那么必须只要有N-1个连接条件(WHERE后面的语句),若不添加连接条件,将出现笛卡尔积

笛卡尔积:A表中每条数据与B表每条数据连接生成的结果,对系统的资源占用大的破坏是严重的

内连接

SELECT e.ename, d.dname

FROM emp e JOIN dept d

ON(e.deptno = d.deptno);

WHERE d.dname='SALES'//效果同上 。查看SALES部门工作的员工的所有名字

外连接

当进行关联查询时,不满足连接条件的数据不会被显示在结果中,我们需要将不满足连接条件的记录也显示出来,就需要使用到外连接

外连接分为左外连接,右外连接,全外连接

左外连接:以左面的表作为驱动表,会将该表中所有记录都显示出来,对于不满足连接条件的记录,结果都集中若包含右面的表中的字段时,

这些字段的值全部填写为NULL

SELECT e.ename,e.deptin,d.depton,d.dname,d.loc

FROM myemp1_liuwenshou e LEFT JOIN mydep1_liuwenshou d

ON( e.deptin=d.depton)

||

也可以写成

SELECT e.ename, d.dname

FROM myemp1_liuwenshou e LEFT JOIN mydep1_liuwenshou d

WHERE e.deptin=d.depton(+)//+号加在相反的位置

右外连接:以右面的表作为驱动表

全外连接:两面的数据都要显示,不满足连接条件的记录哪边不满足哪边的字段补NULL

SELECT table1.column, table2.column

FROM table1 [ LEFT | RIGHT | FULL] JOIN table2

ON table1.column1 = table2.column2;

自连接

自己表中的记录对应自己表中的其他记录,自己表与自己表及你想那个关联查询,这种设计通常是为了解决不知道层级数的树状结构数据的保存

例如:淘宝的宝贝分类:类别下面还有类别

公司的员工设计:员工可能管理其他员工

SELECT e.empno,e.ename,m.ename,m.empno

FROM myemp1_liuwenshou e,myemp1_liuwenshou m

WHERE e.mgr=m.empno(+)

子查询:子查询可以被引用的地方很多

外层查询的SELECT子句中可以嵌套子查询

外层查询的FROM子句中可以嵌套子查询

外层查询的WHERE子句中可以嵌套子查询(最常见)

DDL语句也可以嵌入子查询

DML语句也可以嵌入子查询

eg:查找和SCOTT同职位的员工

SELECT ename,job,deptin

FROM lwsemp

WHERE deptin=(SELECT deptin FROM lwsemp WHERE ename='FORD')

将查询结果作为表创建出来:CREATE TABLE+新表名+AS+查询结果

CREATE TABLE newname

AS

SELECT ...

子查询根据查询结果分为:

单行单列:查询的结果只有一行且只有一列

单行多列:查询的结果有多行但是只有一列

多行多列:查询结果有多列,单行多行无所谓

单列子查询用于WHERE

多列子查询用于FROM

当子查询的结果为多行单列的,那么判断“=”时要使用“IN”,判断等于列表中一项

eg:和职位是MANAGER相同部门的员工

SELECT ename,job

FROM lwsemp

WHERE deptin IN(SELECT deptin FROM lwsemp WHERE job='MANAGER')

AND job <> 'MANAGER'

若子查询结果为多行单列,那么判断“=”

EXISTS后面根一个子查询,EXISTS会判断查询是否能查处至少一条记录,能查询就返回true,否则返回false

eg:查询有员工的部门 /没有员工的部门只需在EXISTS前加NOT

SELECT depton,dname FROM lwsdept d

WHERE

EXISTS(SELECT * FROM lwsemp e WHERE e.deptin=depton)

子查询在HAVING部分

eg:查看最低薪水高于30号部门最低薪水的部门信息

SELECT MIN(sal),deptin

FROM lwsemp

GROUP BY deptin

HAVING MIN(sal)>(SELECT MIN(sal) FROM lwsemp WHERE deptin=30)

子查询在FROM部分

eg:查看那些比自己比自己部门的平均工资高的员工信息

SELECT e.ename,e.sal

FROM lwsemp e,(SELECT AVG(sal) sa,deptin

FROM lwsemp

GROUP BY deptin) s

WHERE e.deptin=s.deptin

AND e.sal>s.sa

子查询在SELECT部分可以认为是外连接的另一种表现形式

SELECT e.ename, e.sal, e.deptno,

(SELECT d.deptno FROM dept d

WHERE d.deptno = e.deptno) deptno

FROM emp e;

分页查询

ROWNUM是伪列,用于返回标识行数据顺序的数字。本身不存在任何一张表上,但是在查询任何一张表时

都可以查询该列,该列的值是行号

在编号的过程中,不要使用ROWNUM做 > 判断,否则查不到数据

利用ROWNUM截取结果集中的部分数据

eg:查看4-6行字段

SELECT *

FROM (SELECT ROWNUM rn,ename,sal,deptin

FROM lwsemp)

WHERE rn BETWEEN 4 AND 6

在分页时,需要结果按照某个字段进行排序时,要注意,由于使用ROWNUM编号是在查询数据的过程中进行的,而

排序是在查询结果之后进行的,这会导致编号后在进行排序,使得编号错乱

为此,要有排序工作时,我们先排序,再编号,做后根据编号取范围

使用子查询进行分页

每一页显示4条,显示第2页

pageSize=4

page=2

start=(page-1)*pageSize+1

end=page*pageSize

DECODE函数

DECODE (expr, search1, result1[, search2, result2…][, default])

用于比较参数expr的值,如果匹配到哪一个search条件,就返回对应的result结果,可以有多

组search和result的对应关系,如果任何一个search条件都没有匹配到,则返回最后default的

值。default参数是可选的,如果没有提供default参数值,当没有匹配到时,将返回NULL

eg:查询职员表,根据职员的职位计算奖励金额,当职位分别是’MANAGER’、’ANALYST’、’SALESMAN’时,

奖励金额分别是薪水的1.2倍、1.1倍、1.05倍,如果不是这三个职位,则奖励金额取薪水值

SELECT ename, job, sal,

DECODE(job, 'MANAGER', sal * 1.2,

'ANALYST', sal * 1.1,

'SALESMAN', sal * 1.05,

sal

) bonus

FROM lwsemp;

DECODE函数功能相似的有CASE语句,实现类似于if-else的操作

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;

若希望将给定字段不同的值看作一组,其他作为另一组统计结果

eg:job中MANNAGER,ANALYST两种职位看作一组,其他看作一组

由于GROUP BY只能根据后面给定的内容值相容的记录分为一组,所以我们需要将MANAGER,ANALYST转换为相同的值才能被分为一组

这时我们可以使用DECODE函数来实现

SELECT DOUNT(*),DECODE(jpb,

'MANAGER','VIP',

'ANALYST','VIP',

'OTHER')

FROM lwsemp

GROUP BY DECODE(job,

'MANAGER','VIP',

'ANALYST','VIP',

'OTHER')

按照自定义顺序排序

SELECT depton,dname,loc

FROM dept

ORDER BY

DECODE(dname,

'OPERATIONS',1,

'ACCOUNTING',2,

'SALES',3 )

排序函数:

可以根据给定的字段进行分组,再根据给定的另外的字段排序,给予组内编号

分组的字段可以是多个

排序的字段也可以是多个

ROW_NUMBER()

给予组内连续且唯一的编号

eg:统计每个部门的工资排名

SELECT

ename,deptin,sal,

ROW_NUMBER()

OVER(PARTITION BY deptin ORDER BY sal DESC) rank

FROM lwsemp

RANK()函数生成组内不连续不唯一的数字

组内记录中排序的字段值相同的生成的数字也相同

SELECT

ename,deptin,sal,

RANK()

OVER(PARTITION BY deptin ORDER BY sal DESC) rank

FROM lwsemp

DENSE_RANK()函数生成组内连续不唯一的数字

SELECT

ename,deptin,sal,

DENSE_RANK()

OVER(PARTITION BY deptin ORDER BY sal DESC) rank

FROM lwsemp

集合操作:两个查询结果集可以进行并集,交集,差集

查询的字段,顺序,数量必须完全一样

SELECT statement1

[UNION | UNION ALL | INTERSECT | MINUS]

SELECT statement2;

UNION和UNION ALL用来获取两个或两个以上结果集的并集:

UNION操作符会自动去掉合并后的重复记录。

UNION ALL返回两个结果集中的所有行,包括重复的行。

UNION操作符对查询结果排序,UNION ALL不排序

查看每天的销售总额

SELECT year_id,month_id,day_id,SUM(sales_value)

FROM lwssales_tab

GROUP BY year_id,month_id,day_id

ORDER BY year_id,month_id,day_id

--每月的销售总额

SELECT year_id,month_id,SUM(sales_value)

FROM lwssales_tab

GROUP BY year_id,month_id

ORDER BY year_id,month_id

--每年的销售总额

SELECT year_id,SUM(sales_value)

FROM lwssales_tab

GROUP BY year_id

ORDER BY year_id

--总销售额

SELECT SUM(sales_value)

FROM lwssales_tab

ROLLUP()函数

ROLLUP BY ROLLUP(a,b,c)

等价于

ROLLUP BY a,b,c

UNION

ROLLUP BY a,b

UNION

ROLLUP BY a

UNION

全表

eg:把所有的分类放一张表上

SELECT year_id,month_id,day_id,SUM(sales_value)

FROM lwssales_tab

GROUP BY ROLLUP(year_id,month_id,day_id)

ORDER BY year_id,month_id,day_id

CUBE()函数:GROUP BY CUBE(a, b, c)等价于 a, b, c & a, b & b, c & a , c & a & b & c & 全表

eg:SELECT year_id,month_id,day_id,SUM(sales_value)

FROM lwssales_tab

GROUP BY CUBE(year_id,month_id,day_id)

ORDER BY year_id,month_id,day_id

GROUPING SETS()

可以根据给定的字段组合进行分组,将结果并在一起返回

eg:显示每天的销售额与每月的销售额

SELECT year_id,month_id,day_id,SUM(sales_value)

FROM lwssales_tab

GROUP BY GROUPING SETS((year_id,month_id,day_id),(year_id,month_id))

ORDER BY year_id,month_id,day_id

视图与表一样,也是数据库对象,视图不是真实的表,但是在SQL语句中出现的位置与表相同

试图对应的是一条SQL语句,使用视图可以简化SQL的编写,重用子查询,或者限制数据访问

创建视图的语法:

CREATE [OR REPLACE] VIEW view_name[(alias[, alias…])]//创建或替换,建议加上OR REPLACE

AS subquery ;

eg:创建一个试图v_emp_10来显示部门10中的员工的编码,姓名,薪水

CREATE OR REPLACE VIEW lws_v_emp_10

AS

SELECT empno id,ename name,sal salary,deptno

FROM clc_emp

WHERE deptno=10

查看试图结构:DESC v_emp_10

简单视图可以进行DML操作,但是复杂试图不行,但通常不会对试图进行DML操作

视图对应的查询语句中的字段可以使用别名,这样视图中的该字段就用别名作为字段名了,在查询视图中对应字段的值时,需使用别名来查询

向视图中插入数据等于向基表中插入了数据。并且插入的这条记录中只有视图看得到的字段会有值,其他字段全部插入NULL。

这里就西药注意了,若视图看不见的字段在emp表中被定义为NOT NULL那么就会导致插入失败,因为会违反emp表的非空约束

修改或删除视图中的数据,只能修改或删除视图现在能看的到的数据

向emp中插入一条这个视图自己看不见的数据

删除视图中的数据实际上就是删除了emp表中的该条记录

CHECK OPTION约束的视图

语法如下:

CREATE [OR REPLACE] VIEW view_name[(alias[, alias…])]

AS subquery

[WITH CHECK OPTION];

其中:WITH CHECK OPTION短语表示,通过视图所做的修改,必须在视图的可见范围内

假设INSERT,新增的记录在视图仍可查看

假设UPDATE,修改后的结果必须能通过视图查看到

假设DELETE,只能删除现有视图里能查到的记录

eg:创建带有CHECK OPTION约束的视图:

CREATE OR REPLACE VIEW v_emp_10

AS

SELECT empno id, ename name, sal salary, deptno

FROM emp

WHERE deptno = 10

WITH CHECK OPTION;

READ ONLY约束的视图:只读选项

当一个视图被定义为只读的,那么该视图不允许执行DML操作

eg:创建带有READ ONLY约束的视图:只读选项

CREATE OR REPLACE VIEW v_emp_10

AS

SELECT empno id, ename name, sal salary, deptno

FROM emp

WHERE deptno = 10

WITH READ ONLY;

USER_VIEWS获取相关信息,数据字典

和视图相关的数据字典有:

USER_OBJECTS

USER_VIEWS

USER_UPDATABLE_COLUMNS

例一:在数据字典USER_OBJECTS中查询所有视图名称:

SELECT object_name FROM user_objects

WHERE object_type = 'VIEW';

例二:在数据字典USER_VIEWS中查询指定视图:

SELECT text FROM user_views

WHERE view_name = 'V_EMP_10';

例三:在数据字典USER_UPDATABLE_COLUMNS中查询视图:

SELECT column_name, insertable, updatable, deletable

FROM user_updatable_columns

WHERE table_name = 'V_EMP_10';

查看用户创建过的表

SELECT * FROM user_tables

/SELECT table_name FROM user_tables

查看 用户创建过的视图

SELECT * FROM user_views

SELECT test FROM user_views 查看视图对应的查询语句

查看用户创建过的所有数据库对象

SELECT object_name FROM user_objects

创建复杂视图:

复杂视图中对应的SELECT语句会出现表达式,函数,分组等操作

并且还有表达式,函数的字段必须给别名,复杂视图不允许执行DML,所以复杂函数不需加只读约束

eg:创建一个实现各部门薪水的视图

CREATE OR REPLACE VIEW v_emp_sal

AS

SELECT MAX(sal) max_sal,MIN(sal) min_sal,AVG(sal) avg_sal,SUM(sal) sun_sal,deptno

FROM emp

GROUP BY deptno

删除视图,只是将视图对应的SELECT语句删掉了,不会对基表产生影响

序列(SEQUENCE)是一种用来生成唯一数字值的数据库对象。序列的值由Oracle程序按递增或递减顺序自动生成,通常

用来自动产生表的主键值,是一种高效率获得唯一键值的途径。

语法:CREATE SEQUENCE [schema.]sequence_name

[ START WITH i ] [ INCREMENT BY j ]

[ MAXVALUE m | NOMAXVALUE ]

[ MINVALUE n | NOMINVALUE ]

[ CYCLE | NOCYCLE ][ CACHE p | NOCACHE ]

其中:

sequence_name是序列名,将创建在schema方案下序列的第一个序列值是i,步进是j

如果j是正数,表示递增,如果是负数,表示递减

序列可生成的最大值是m,最小值是n

如果没有设置任何可选参数,序列的第一个值是1,步进是1

CYCLE表示在递增至最大值或递减至最小值之后是否继续生成序列号,默认是NOCYCLE

CACHE用来指定先预取p个数据在缓存中,以提高序列值的生成效率,默认是20

创建序列:用来生成一组数字

CREATE SEQUENCE seq_emp_lws

START WITH 100

INCREMENT BY 10

序列有两个伪列

NEXTVAL:使序列生成下一个数字

CURRVAL:获取序列的当前值

需要注意,当序列刚创建完毕后,一定要先调用一次NEXTVAL使序列生成一个数(START WITH)之后才可以调用CURRAVL

每调用一次NEXTVAL,序列都会用当前生成的数字加上步长来生成下一个

所以若需要使用之前生成的数字而不希望序列增长,可以使用CURRVAL

SELECT seq_emp_id.NEXTVAL FROM dual -->110

SELECT seq_emp_id.CURRAVL FROM dual -->110

向表中插入主键

INSERT INTO clc_emp

(empno,ename,sal,job,deptno)

VALUES

(seq_emp_lws.NEXTVAL,'MARRY',5000,'CLERK',30)

删除序列emp_seq:

DROP SEQUENCE emp_seq;

索引的原理:索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是独立于表的对象,可以存

放在与表不同的表空间(TABLESPACE)中。索引记录中存有索引关键字和指向表中数据的指针(地址)。对索引进行的I/O操作

比对表进行操作要少很多

索引一旦被建立就将被Oracle系统自动维护,查询语句中不用指定使用哪个索引,是一种提高查询效率的机制。

ROWID: 伪列,唯一标识一条数据记录,可理解为行地址

创建索引的语法:

CREATE [UNIQUE] INDEX index_name

ON table(column[, column…]);

其中:

index_name表示索引名称

table表示表名

column表示列名,可以建立单列索引或复合索引

UNIQUE表示唯一索引

eg:为lwsemp表的ename字段添加索引

CREATE INDEX idx_emp_ename_lws ON lwsemp(ename)

复合索引也叫多列索引,是基于多个列的索引。

如果经常在ORDER BY子句中使用job和salary作为排序依据,可以建立复合索引:

CREATE INDEX idx_emp_job_sal ON emp(job, sal);

当做下面的查询时,会自动应用索引idx_emp_job_sal

SELECT empno, ename, sal, job FROM emp

ORDER BY job, sal;

创建基于函数的索引

如果需要在emp表的ename列上执行大小写无关搜索,可以在此列上建立一个基于UPPER函数的索引:

CREATE INDEX emp_ename_upper_idx

ON emp(UPPER(ename));

当做下面的查询时,会自动应用刚刚建立的索引:

SELECT * FROM emp

WHERE UPPER(ename) = 'KING';

修改和删除索引,如果经常在索引列上执行DML操作,需要定期重建索引,提高索引的空间利用率,

语法如下:ALTER INDEX index_name REBUILD;

重建索引idx_emp_ename:

ALTER INDEX idx_emp_ename REBUILD;

当一个表上有不合理的索引,会导致操作性能下降,删除索引的语法:

DROP INDEX index_name;

删除索引idx_emp_ename:

DROP INDEX idx_emp_ename;

********************************************************************************************************************

*合理使用索引提升查询效率

*1,不要在小表(数据量不大)上创建索引

*2,为经常出现在WHERE子句中的列创建索引

*3,为经常出现在ORDER BY、DISTINCT后面的字段建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致

*4,为经常作为表的连接条件的列上创建索引

*5,不要在经常做DML操作的表上建立索引

*6,限制表上的索引数目,索引并不是越多越好

*7,删除很少被使用的、不合理的索引

*******************************************************************************************************************

约束:约束(CONSTRAINT)的全称是约束条件,也称作完整性约束条件。约束是在数据表上强制执行的一些数据校验规则,当执行DML操作时,

数据必须符合这些规则,如果不符合则无法执行。

约束条件可以保证表中数据的完整性,保证数据间的商业逻辑。

约束条件包括:

非空约束(Not Null),简称NN

唯一性约束(Unique),简称UK

主键约束(Primary Key),简称PK

外键约束(Foreign Key),简称FK

检查约束(Check),简称CK

1,非空约束(Not Null)

当执行INSERT操作时,必须提供这个列的数据

当执行UPDATE操作时,不能给这个列的值设置为NULL

eg:CREATE TABLE employees (

eid NUMBER(6),

name VARCHAR2(30) NOT NULL,

salary NUMBER(7, 2),

hiredate DATE CONSTRAINT employees_hiredate_nn NOT NULL //创建表的时候自定义约束名

);

修改表时添加非空约束

可以在建表之后,通过修改表的定义,添加非空约束:

ALTER TABLE employees

MODIFY (eid NUMBER(6) NOT NULL);

取消非空约束

如果业务要求取消某列的非空约束,可以采用重建表或者修改表的方式:

ALTER TABLE employees

MODIFY (eid NUMBER(6) NULL);

唯一性约束:唯一性(Unique)约束条件用于保证字段或者字段的组合不出现重复值。

当给表的某个列定义了唯一约束条件,该列的值不允许重复,但允许是NULL值

eg:在建表employees的同时,在eid、email列上创建唯一约束条件,并在建表后

在name列上建立一个名为employees_name_uk的唯一约束条件

CREATE TABLE employees (

eid NUMBER(6) UNIQUE,//唯一约束

name VARCHAR2(30),

email VARCHAR2(50),

salary NUMBER(7, 2),

hiredate DATE,

CONSTRAINT employees_email_uk UNIQUE(email)//创建的时候增加一个约束名

);

在建表之后增加唯一性约束条件:

ALTER TABLE employees

ADD CONSTRAINT employees_name_uk UNIQUE(name);

主键约束:主键(Primary Key)约束条件从功能上看相当于非空(NOT NULL)且唯一(UNIQUE)的组合。主键字段可以是单字

段或多字段组合,即:在主键约束下的单字段或者多字段组合上不允许有空值,也不允许有重复值。

主键可以用来在表中唯一的确定一行数据。一个表上只允许建立一个主键,而其它约束条件则没有明确的个数限制。

在建表时添加主键约束条件:

CREATE TABLE employees2 (

eid NUMBER(6) PRIMARY KEY,

name VARCHAR2(30),

email VARCHAR2(50),

salary NUMBER(7, 2),

hiredate DATE

);

建表后创建主键约束条件,并自定义约束条件名称:

ALTER TABLE employees3

ADD CONSTRAINT employees3_eid_pk PRIMARY KEY (eid);

外键约束:外键约束条件定义在两个表的字段或一个表的两个字段上,用于保证相关两个字段的关系。比如emp表的deptno列参照dept表

的deptno列,则dept称作主表或父表,emp表称作从表或子表。在实际开发当中几乎不用

添加外键约束:先建表,在建表后建立外键约束条件:

CREATE TABLE employees4 (

eid NUMBER(6),

name VARCHAR2(30),

salary NUMBER(7, 2),

deptno NUMBER(4)

);

ALTER TABLE employees4

ADD CONSTRAINT employees4_deptno_fk

FOREIGN KEY (deptno) REFERENCES dept(deptno);

检查约束:检查(Check)约束条件用来强制在字段上的每个值都要满足Check中定义的条件。当定义了Check约束的列新增或修改数据时,

数据必须符合Check约束中定义的条件。

添加检查约束:员工的薪水必须大于2000元,增加检查约束:

ALTER TABLE employees4

ADD CONSTRAINT employees4_salary_check

CHECK (salary > 2000);

当插入大于2000的数据,操作成功:

INSERT INTO employees4(eid, name, salary, deptno)

VALUES(1236, 'donna noble', 2500, 40);

*性能最好Oracle分页查询

*select * from (

* select a.*,rownum RN from (

* select * from lwsmoney

* ) A where rownum <=10

*) where RN >=6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: