1.显示格式化{
整体显示格式化{
SET LINNESIZE 300;//设置每行显示的数据长度
SET PAGESIZE 30;//设置没页显示的数据长度
}
对某一行进行格式化{
COL 列名称 FOR A长度;
eg:COL job FOR A8;
}
}
2.在已经连接上SQLPlus的控制台上使用 "ed 文件名"命令,会在系统用户目录下寻找 "文件名.sql"的文件,
如果没有找到,则会有提示框提示是否创建,该文件;
在SQLPlus中要执行包含SQL脚本的文件输入以下命令即可:@文件名(不用后缀);
使用@命令执行文件系统上的脚本时,使用@文件路径 即可,如果文件是以 .sql 结尾的,后缀可以省略,
不然应该使用全路径资源定位符,eg:@F:/data.sql
3.用户相关{
1)显示当前登录的用户:show user;
2)切换用户:CONN 用户名[/密码][AS SYSDBA]
eg:CONN system/manager
注意:如果是想切换到sys用户"AS SYSDBA"必须选上,否则无法登陆。
3)访问其他用户的表,需要写上完整的表名称:模式名.表名称(目前的模式名一般就是用户名),
例如当前登陆的是"sys"用户,直接以"SELECT * FROM emp;"查询Scott用户下的emp表会报"
表或视图不存在的错误",完整的查询命令应该是:"SELECT * FROM scott.emp;"
}
4.调用本机程序{
例如:windows 下的文件拷贝:copy 源文件路径 目标文件路径;
在sqlplus中调用需要在命令之前加上"HOST",即,"HOST COPY 源文件路径 目标文件路径";
eg:HOST COPY f:\data.sql f:\hello.sql;
}
5)表相关{
查看当前用户的所有的表:select * from tab;
查看表结构:DESC 表名称;
}
6)数据投影:即将数据表的字段查询出来映射到指定的名称([别名])或者是原字段名上。
7)基本查询{
SELSECT *|字段名 [别名],字段名 [别名],字段名 [别名]... from 表名称;
除基本的查询列外,简单查询也支持四则运算,并且可以直接使用列的内容进行四则运算,例如,现在
要求查询出scott用户下emp表中用户的编号、姓名、工作、年薪:SELECT empno,ename,job,sal*12 FROM emp;
数据连接:SELECT empno||ename from emp;
普通数字:SELECT ename||1 from emp;
字符串:SELECT '姓名:'||ename from emp;
eg:查询并格式(编号:xxx,姓名:xxx)输出:SELECT '编号:'||empno ||',姓名:'||ename from emp;
DISTINCT关键字:消除重复内容,eg:SELECT DISTINCT job FROM emp;
注意:但是要消除重复内容是指的是所有查询出来数据的所有的列的内容都重复。
}
8)限定查询{
一个查询语句执行的顺序:
[③选出所需要的数据列]SESLECT [DISTINCT] *|列名 [ 别名],列名 [ 别名],列名 [ 别名]...
[①确定数据的来源]FROM XXX
[②筛选数据行] [WHERE 限定条件(s)];
Select 子句是整个语法最后才会被执行到的子句,但是如果要进行数据行的筛选,必须要使用若干个条件:
·关系运算:>、=、<、>=、<=、!=(<>);
·范围运算:BETTEN...AND;
·空判断:IS NULL、IS NOT NULL;
·IN判断:IN、NOT IN、exits();
·模糊查询:LIKE、NOT LIKE;
关系运算:AND 、OR
}
9)单行函数{
字符串函数(需要完整的查询语句):{
UPPER(列|数据)---->将字符串转换为大写: select UPPER(ename) from emp;//select UPPER('hello World') from emp;
LOWER(列|数据)---->将字符串转换为小写: select LOWER(ename) from emp;//select LOWER('hello World') from emp;
length(列|数据)---->求字符串的长度:select length('hello World') from emp;//select length(ename) from emp;
INITCAP(列|数据)---->将字符串(中间无空格,否则会认为是多个字符串)的首字母变为大写,其他的转为小写:select INITCAP(ename) from emp;//select INITCAP('helloWORLD') from emp;
REPLACE(列|数据,要替换的字符串,替换内容)----->将指定数据列或字符串中指定的字串替换为其他内容:select REPLACE(UPPER('hello WORLD'),' ','&') from emp;
SUBSTR(列|数据,开始点)或者SUBSTR(列|数据,开始点,长度)---->SELECT SUBSTR(LOWER('HEllo WOrld'),7,2) FROM emp;//SELECT SUBSTR(LOWER(ename),3) FROM emp;
}
数值函数:{
ROUND(带四舍五入的数据[,保留小数位数(不写此项表示默认舍去小数部分)])----->
{
SELECT
ROUND(78915.67823823), #78916 小数点后的内容直接进行四舍五入
ROUND(78915.67823823,2), #78915.68 保留两位小数
ROUND(78915.67823823,-2), #78900 把不足5的数据取消了
ROUND(78965.67823823,-2), #79000 如果超过了5则进行进位
ROUND(-15.65) #-16
FROM dual;
}
TRUNC(列|数字[,小数位]):直接进行小数截取,不进行进位处理
{
SELECT
TRUNC(78915.67823823), #78915
TRUNC(78915.67823823,2), #78915.67
TRUNC(78915.67823823,-2), #78900
TRUNC(78965.67823823,-2), #78900
TRUNC(-15.65) #-15
FROM dual;
}
MOD(列1|数字1,列2|数字2):求模操作(取余数):
{
--第一个操作数为被除数,第二个操作数为除数
SELECT MOD(10,3) from dual;
}
}
日期函数:{
·数据伪列:SYSDATE、SYSTIMESTAMP
·实际上对于日期、时间有以下的三种计算形式:
日期+数字=日期(若干天后的日期)
日期-数字=日期(若干天前的日期)
日期-日期=数字(两个日期间的天数)
·eg:10天后的日期:SELECT SYSDATE+10 FROM DUAL;
·MONTHS_BETWEEN(日期1,日期2):计算两个日期之间的月数:{
eg:计算emp表中每个雇员至今的雇佣月数:SELECT MONTHS_BETWEEN(SYSDATE,hiredate) FROM emp;
计算emp表中每个雇员至今的雇佣年数:SELECT TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) FROM emp;
}
·ADD_MONTHS(日期,月数):计算增加若干月后的日期:{
eg:测试增加4个月后的日期:SELECT ADD_MONTHS(SYSDATE,4) FROM dual;
}
·LAST_DAY(日期):计算日期所在月最后一天的日期{
eg:计算当前所在月的最后一天:SELECT LAST_DAY(SYSDATE) FROM dual;
eg:查询出雇佣所在月倒数第一天的前两二天被雇佣的雇员的信息:SELECT ename,hiredate,LAST_DAY(hiredate) FROM emp WHERE hiredate=LAST_DAY(hiredate)-1;
}
·NEXT_DAY(日期,一周的时间数量):{
eg:计算下一个周四:SELECT NEXT_DAY(SYSDATE,'星期四') FROM dual;
}
}
转换函数:{
TO_CHAR(要转换的内容,转换的格式):{
eg:格式化日期:SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd hh:mm:ss') FROM dual;
eg:实现年月日拆分:
查询每个雇员的编号、姓名、雇佣年份:SELECT empno,ename,TO_CHAR(hiredate,'yyyy') year FROM emp;
查询所有在二月份雇佣的雇员的信息:SELECT * FROM emp WHERE TO_CHAR(hiredate,'mm')='02';
eg:数字转换为指定格式的字符串:
将指定的数字转换为当地的货币:SELECT TO_CHAR(531876381638,'L999,999,999,999,99,999,999,999') FROM dual;//L 表示的是当地的货币
}
TO_DATE(字符串,转换格式):SELECT TO_DATE('2018-04-05','yyyy-mm-dd') from dual;
TO_NUMBER(由数字组成的字符串):SELECT TO_NUMBER('2')+TO_NUMBER('3') FROM dual;
}
通用函数:{
NVL(列|NULL,列为空的默认值):处理NULL,Oracle在对值为NUll的列进行计算时,得到的结果都是NULL,而处理该问题方法是使用NVL(列,列为NULL时的默认值)来处理。
eg:查询emp表中所有员工的信息和年薪:SELECT empno,ename,job,(sal+comm)*12 income from emp;得到的结果中凡是comm为NULL的员工的年薪都是NULL,
这显然是不合理的,使用NVL函数解决如下:SELECT empno,ename,job,(sal+NVL(comm,0))*12 income from emp;
DECODE(列,匹配内容1,显示内容1,匹配内容2,显示内容2,...[,默认值])
eg:SELECT empno,ename,sal,DECODE(job,'CLERK','销售','MANAGER','经理','暂无此信息') job from emp;
}
查询表中的数据量:COUNT(*):SELECT COUNT(*) sum FROM emp;
}
10)多表查询{
注意:{
只要是多表查询,这多这表之间一定要有关联关系,如果没有关联关系则会产生笛卡儿积(使用WHERE子句和多表之间的关联关系可以有效的控制查询结果的行数);
如果数据库的数据量较大,单张表接近10W,如果使用多表查询则速度将会非常的慢。
eg:查询每个雇员的编号,姓名,工作,工资等级:SELECT e.empno,e.ename,e.job,s.grade from emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;
}
表的连接:{
内连接------->满足关联条件的数据出现,不满足的不出现(以上的示例实际上就是内连接);
外连接:左(外)连接,右(外)连接,全连接--------->指定一张表中的数据全部都显示,但是没有对应其他表的数据都为NULL;
eg:右外连接----->通用SQL:1999语法:SELECT e.*,m.ename m_name,m.job m_job from emp e RIGHT OUTER JOIN emp m ON(e.mgr=m.empno);
Oracle 语法:SELECT e.empno,e.ename,e.job,d.deptno from emp e,dept d WHERE e.deptno(+)=d.deptno;
左外连接----->通用SQL:1999语法:SELECT e.*,m.ename m_name,m.job m_job from emp e LEFT OUTER JOIN emp m ON(e.mgr=m.empno);
Oracle 语法:SELECT e.empno,e.ename,e.job,d.deptno from emp e,dept d WHERE e.deptno=d.deptno(+);
在Oracle中使用了"(+)"来控制连接的方式:
·左外连接:关联字段1=关联字段2(+)
·右外连接:关联字段1(+)=关联字段2
全连接:SELECT e.*,m.ename m_name,m.job m_job from emp e FULL OUTER JOIN emp m ON(e.mgr=m.empno);
内连接和外连接二者的选择:一般情况下考虑使用内链接即可,但是所需要的数据不全的时候就可以考虑外连接。
自身连接:eg:查询每个雇员的empno,ename,job 和对应领导的ename,job------------------>SELECT e.empno,e.ename,e.job,m.ename m_ename,m.job m_job from emp e,emp m WHERE e.mgr=m.empno(+);
}
数据集合操作:{
UNION:{
将两条语句的结果合并,但是将重复的内容去除;
eg:SELECT * FROM emp
UNION
SELECT * FROM emp WHERE deptno=10;
}
UNION ALL{
将两条语句的结果直接合并不做处理;
eg:SELECT * FROM emp
UNION ALL
SELECT * FROM emp WHERE deptno=10;
}
INTERSECT:{
返回两个语句执行结果的交集(相同的部分);
eg:SELECT * FROM emp
INTERSECT
SELECT * FROM emp WHERE deptno=10;
}
MINUS:{
返回两个语句执行结果的差集(注意如果第一条语句执行的结果数量少于第二条,那么将不会有数据返回)
eg:SELECT * FROM emp
MINUS
SELECT * FROM emp WHERE deptno=10;
}
注意:数据的集合操作最终是将多个查询合并为一个查询,所以要求这若干个查询返回的结果的结构必须相同。
}
}
11)分组统计查询{
COUNT(){
·COUNT(*):可以准确返回表中的全部记录数;
eg:SELECT COUNT(*) FROM emp;---------------->14
·COUNT(字段):统计不为NULL的所有数据。
eg:SELECT COUNT(comm) FROM emp;------------->4
·COUNT(DISTINCT 字段):消除重复数据之后的结果。
eg: SELECT COUNT(JOB) FROM emp;--------------->14
SELECT COUNT(DISTINCT JOB) FROM emp;------>5
}
SUM(){
eg:SELECT SUM(sal) from emp;
}
MIN()、MAX()、AVG()...
分组查询通过GROUP BY 子句进行分组操作:{
eg:按照job分组,查询各个job下的员工数量,最高工资,最低工资:SELECT job ,COUNT(*),MIN(sal),MAX(sal) FROM emp GROUP BY job;
eg:按照deptno分组,查询各个部门下的员工数量,最高工资,最低工资,平均工资:SELECT Deptno ,COUNT(*),MIN(sal),MAX(sal),AVG(sal) FROM emp GROUP BY deptno;
注意:使用GROUP BY 子句的约定条件:
·如果查询不使用GROUP BY 子句,那么SELECT子句中不允许出现除了统计函数外的其他任何字段.
·如果查询语句中使用了GROOUP BY子句,那么SELECT子句中只允许出现分组字段、统计函数,其他任何字段不允许出现;
分组函数可以嵌套使用,但是在组函数嵌套的时候不能再出现分组条件的查询语句.
·统计函数允许嵌套,但嵌套后的SELECT语句中只允许出现嵌套函数,不允许出现其他字段,包括分组字段.
}
这些统计函数都可以和其他语句嵌套使用;当查询的数据表中没有数据时,只有COUNT()函数有返回值为0,其他的几个统计函数的都没有返回为NULL;
多表分组统计查询:{
·以部门名称分组,查询各个部门的部门名称,人数,平均工资:
--由于分组统计函数中除了COUNT()外其他分组函数如果查询内容为空,则不会返回内容,故而使用NVL通用函数来处理为空的情况,注意,单行函数可以出现在任意位置
SELECT d.dname,COUNT(e.deptno),NVL(AVG(e.sal),0) FROM emp e,dept d WHERE e.deptno(+)=d.deptno GROUP BY d.dname;
·查询每个部门的部门编号,名称,位置,人数,平均工资:
--多字段分组,当查询的结果及中有重复数据并且重复的数据行中有多个字段是的值是重复的,那么此时就可以使用多字段分组
SELECT d.deptno,d.dname,d.loc,COUNT(e.empno),NVL(AVG(sal),0) FROM dept d,emp e WHERE d.deptno=e.deptno(+) GROUP BY (d.deptno,d.dname,d.loc);
}
HAVING子句:{
查询每个job的名称,该职位的平均工资,并且只保留平均工资大于2000的职位信息:
/*
由于SELECT语句执行顺序的问题分组统计函数的执行顺序是在WHERE子句之后的,故而此处并不能使用
WHERE子句来进行条件过滤消除笛卡儿积,而针对于这种需要以分组结果再次进行条件筛选的情况,提供
了HAVING子句来解决,该子句必须与GROPUP BY子句同时出现,但是GROUP BY子句可以单独出现。
*/
SELECT job,AVG(sal) FROM emp GROUP BY job HAVING(AVG(sal)>2000) ORDER BY AVG(sal);
}
分组统计总结:{
·显示所有非销售人员的工作名称以及从事同一工作雇员的月工资总和,并且要求满足从事同一工作的月工资合计大于5000,显示结果按照月工资合计升序排序:
SELECT e.job,SUM(sal) FROM emp e WHERE e.job <>'SALESMAN' GROUP BY (e.job) HAVING(SUM(sal)>5000) ORDER BY SUM(sal);
·查询所有销售和非销售人员的人数,平均工资:
SELECT '非销售' info, COUNT(*),AVG(sal) FROM emp WHERE comm IS NULL
UNION
SELECT '销售' info,COUNT(*),AVG(sal) FROM emp WHERE comm IS NOT NULL;
}
}
13)子查询{
·在WHERE子句中出现子查询:{
子查询返回单行单列{
--查询所有工资大于公司平均工资的员工信息
SELECT * FROM emp WHERE sal>(SELECT AVG(sal) FROM emp);
}
子查询返回多行单列{
--查询所有工资范围不在职位为MANAGER的工资范围之内的员工信息
SELECT * FROM emp WHERE sal NOT IN (SELECT sal from emp where job='MANAGER');
--查询出工资小于任何职位为MANAGER的员工信息(比最小的大)
SELECT * FROM emp WHERE sal >ANY (SELECT sal from emp where job='MANAGER');
--查询出工资大于任何职位为MANAGER的员工信息(比最大的小)
SELECT * FROM emp WHERE sal ALL,比最大值大)
SELECT * FROM emp WHERE sal >ALL (SELECT sal from emp where job='MANAGER');
--查询出工资比任何职位为MANAGER的员工的工资都低的员工的信息('SCOTT';
}
}
·在HAVING子句中出现:{
--查询出部门平均工资大于公司平均工资的部门编号,人数,平均工资
SELECT deptno,COUNT(*),AVG(sal) FROM emp GROUP BY deptno HAVING (AVG(sal)>(SELECT AVG(sal) FROM emp));
}
·在FROM子句中出现子查询:{
--查询部门的部门编号,名称,位置,人数,平均工资
SELECT d.dname,d.deptno,d.loc,NVL(temp.count,0),NVL(temp.avg,0)
FROM dept d,(
SELECT deptno,COUNT(empno) count,AVG(sal) avg
FROM emp
GROUP BY deptno
)temp
WHERE d.deptno=temp.deptno(+);
/*
其实以上的语句也可以使用分组查询来完成
*/
SELECT d.deptno,d.dname,d.loc,COUNT(empno),AVG(sal)
FROM dept d,emp e
WHERE d.deptno=e.deptno(+)
GROUP BY (d.deptno,d.dname,d.loc);
}
}
14)复杂查询案例{
--列出所有与SCOTT用户用户从事相同工作的员工及部门名称,部门人数,领导姓名。
SELECT e.ename,e.deptno,e.job,d.dname,temp.count,m.ename mgr
FROM emp e,dept d,(
SELECT e.deptno deptno,COUNT(empno) count
FROM emp e
GROUP BY e.deptno
)temp,emp m
WHERE e.job=(
SELECT job
FROM emp
WHERE ename='SCOTT'
)
AND e.ename<>'SCOTT'
AND d.deptno=e.deptno
AND temp.deptno=d.deptno
AND e.mgr=m.empno;
--列出薪金比'SMITH'或者'ALLEN'高的所有员工的编号,姓名,部门名称,其领导姓名,部门人数,平均工资,最低工资,最高工资。
SELECT e.empno,e.ename,d.dname,m.ename mgr,temp.count count,temp.avg avg,temp.min min ,temp.max max
FROM emp e,dept d,emp m,(
SELECT deptno,COUNT(*) count,AVG(sal) avg,MIN(sal) min,MAX(sal) max
FROM emp
GROUP BY deptno
) temp
WHERE e.deptno=d.deptno
AND e.sal>ANY(
SELECT sal
FROM emp
WHERE ename IN('SMITH','ALLEN')
)
AND e.ename NOT IN('SMITH','ALLEN')
AND e.mgr=m.empno(+)
AND temp.deptno=e.deptno;
}
15)事务处理{
·Oracle 在进行事务处理的时候会有行级锁定的概念,即在提交或回滚更新之前,只能有一个session操作当前行数据。----事物的隔离性
·事务处理本身是保护数据一致性的一种手段,但是在用户更新数据并且还未提交之前,如果发生了DDL(数据定义语言)操作那么所有的事务都将自动提交.
}
16)约束创建与管理:{
1)非空约束(NOT NULL):{
·在创建表的时候指定非空约束:{
CREATE TABLE xxx(
id NUMBER(11) NOT NULL,
...
);
}
}
2)唯一约束(UNIQUE):{
·在创建表的时候指定约束:{
CREATE TABLE xxx(
id NUMBER(11) NOT NULL,
email VARCHAR2(20),
...
CONSTRAINT uk_xxx_email UNIQUE(email)
);
}
注意:如果指定UNIQUE约束的字段插入的值唯一,数据库不会报错,即非空并不在UNIQUE的约束范围内
}
3)主键约束(PRIMARY KEY):{
·在创建表的时候指定约束:{
CREATE TABLE xxx(
id NUMBER(11),
email VARCHAR2(20),
...
CONSTRAINT pk_xxx_id PRIMARY KEY(id)
);
}
注意:主键约束,实质上是NOT NULL和UNIQUE的结合;主键可以指定多个,即复合主键:CONSTRAINT pk_xxx_id PRIMARY KEY(id,email)
}
4)检查约束(CHECK CK):{
·在创建表的时候指定约束:{
CREATE TABLE xxx(
id NUMBER(11),
email VARCHAR2(20),
age NUMBER(3)
...
CONSTRAINT ck_xxx_age CHECK(age BETWEEN 0 AND 300)
);
}
}
5)外键约束(FOREING KEY FK):{
·在创建表的时候指定约束:{
DROP TABLE person purge;
DROP TABLE book purge;
CREATE TABLE person(
mid NUMBER(11),
email VARCHAR2(20),
age NUMBER(3),
CONSTRAINT ck_xxx_age CHECK(age BETWEEN 0 AND 300),
CONSTRAINT pk_person_mid PRIMARY KEY (mid)
);
CREATE TABLE book (
bid NUMBER(11),
name VARCHAR2(20),
mid NUMBER(11),
CONSTRAINT pk_book_bid PRIMARY KEY(bid),
CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES person(mid)
);
}
注意:如果要作为子表外键的父表列必须设置唯一约束或者主键约束;
在删除父表之前必须先删除子表,否则只能使用强制删除 "DROP TABLE xxx CASCADE CONSTRAINT";
在删除父表数据之前,如果子表中有与父表要删除记录对应的子记录那么,删除不会成功,当然在创建表的时候可以指定级联删除或者级联更新来指定
级联删除:CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES person(mid) ON DELETE CASCADE
级联更新:CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES person(mid) ON DELETE SET NULL
}
6)修改约束:{
增加除NOT NULL外的其他约束:ALTER TABLE xxx ADD CONSTRAINT 约束名称 约束类型(字段) --增加约束(但是如果表中有数据违反约束类型的规则时,增加约束失败)
--利用以上的语法可以增加主键、唯一、检查、外键约束,但是不能增加外键约束
增加非空约束:ALTER TABLE XXX MODIFY (字段名,字段类型,NOT NULL);--增加非空约束;也就是说,增加非空约束仅能依靠修改表结构的方法来增加
--但是如果修改表结构来增加非空约束时,表中对应的列上存在值为NULL的字段,那么修改表结构将会失败.
删除约束:ALTER TABLE xxx DROP CONSTRAINT 约束名称;
}
}
17)序列:{
·创建序列:{
CREATE SEQUENCE 序列名
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE/ MINVALUE n|NOMAXVALUE}]
[{CYCLE|NOCYCLE}]
[{CACHE n|NOCACHE}];
}
}