sqlplus /as sysdba登陆
spool c:\基本查询.txt--清屏 host clear(linux)
host cls
showuser查看当前用户
select *from tab 数据字典,管理员给我们提供的表
exit 退出命令行
desc emp 查询表结构信息
setlinesize 120表示每一行显示120个字符
col namefor a8 表示8个字符 a字符
cols salfor 9999
/ 表示执行上一条sql语句
Sql优化:
尽量使用列名代替*,因为使用*,需要解析所有的列名
但是在oracle 9i之后,他们两个是一样的,
修改错误的sql语句
-c命令 change
2*form emp
c/form/from
ed会把sql语句存入一个文件并打开
3种别名的方式(别名之间如果有空格、sql关键字就必须要添加双引号)
selectsal,sal*12,name as “姓名”,age “年龄”,sex 性别, from emp
selectsal,sal*12 年薪,comm 奖金,sal*12+comm 年收入 from emp
如果奖金没有年收入就为0了,
Sql语句中的null值
包含null的表达式都为null
Sql中null != null。
控制是无效的,未指定的,未知的或不可预知的值
Sal * 12 +nu1(comm,0)//如果comm为null,就返回0
查询奖金为null的员工
Select * from emp where comm=null这是不对的
Select * from emp where comm Is null(is not null)
Select distinct name from emp;
Select distinct deptno,job from emp;
Distinct作用于后面所有的列
Sql语言大小写不敏感
连接符:
concat链接字符串 selectconcat(‘hello’,’world’) from emp
如果emp有14条记录,就会显示14条语句
select concat(‘hello’,’world’) from dual
dual表:伪表,是管理员提供的,不是我们创建的
sql 99 ANSI发布的标准所以oracle中select后面必须有from,而mysql可以没有
select‘hello’| | ‘world’from dual;//helloworld
selectename | |’的薪水是’ | | sal fromemp
sql语句与sql*plus命令:
SQL:一种语言
是ANSI的标准
关键字不能缩写
使用语句控制数据库中的表的定义信息和表中的数据
SQL*PLUS:一种环境
oracle的特性之一
关键字可以缩写
命令不能改变数据库中的数据的值
集中运行
Select、update、insert、delete
Desc、Col 、set、ed、change是sql plus语句
使用isql*plus可以:(就是sql plus的web版,11g之后就没有)
描述表结构
Savec:\a.sql
@c:\a.sql加载并且执行
Loadc:\a.sql加载不执行
Spooloff //刚才操作的所有步骤将被记录,也就是录屏命令
过滤:
Select * from emp where empno=10;
Oracle中字符串大小写和日期格式敏感
1981-11-17不叫日期,17-11月-81符合格式,oracle数据库中默认
DD-MON-RR格式的日期,是oracle9i之后的格式,9i之前DD-MON-YY(1998-20982098-98)
千年虫问题,DD-MON-RR解决了这个问题,
查询当前时间
selectnow()//mysql
selectsysdate from dual;//oracle
--查询系统参数
Setlinesize 150
Col parameter for a20
select *from v$nls_parameters; // v$nls_parameters数据字典
--修改日期格式
Altersession | globle(全局)setNLS_DATA_FORMAT =’yyyy-mm-dd’
<<=>between and(含边界,小的在前,大的在后面)inlikeis null
Select *from emp where depot in(10,20); not in(10,20)
那么in(set)这个集合里面能不能有null值呢?如果集合中含有null,不能使用not in操作符,但是可以使用in操作符
Like表示的是模糊查询 %任意长度的任意字符串_ 任意的字符串
查询名字是四个字的员工 select * from emp where enamelike ‘_ _ _ _’.
查询名字中含有下划线的员工
select * from emp where ename like ‘% \ _%’escape ‘\’;
select * from emp where ename like ‘% a_%’escape ‘a’;
rollback;// 回退,可以做这一步的原因就是前面做的事在一个事务中,mysql中通过start Transaction 开启事务,oracle自动开启的事务。
And 逻辑并 or 逻辑或not 逻辑否
Sql优化第二点:
Where condition1 and condition2
Where condition2 and condition1
这两句执行的结果是一样的吗,但是性能不一样。
Oracle解析where条件的时候是从右至左,对于and条件把有可能为false的条件放在右边,因为右边第一个为false,其他的就不会执行
可以使用括号改变优先级
Order by字句 ascend (升序)descend(降序)默认是升序--
--a命令 append
adesc//a后面至少加上两个空格,因为如果一个的话就默认在sql后面加上desc
order by 后面+列名、表达式、别名、序号
order bysal * 12 + ny1(comm.,0)
selectcomm. As ‘年收入’fromemporder by “年收入”
order by4//第四列列数不能超过表中的总列数
order by后面可以有多列吗?
Order bydeptno,sal ;这样排序作用于所有的列,如果第一列相同,则按照第二列排序
Order bydeptno,sal desc // 这样desc是作用于离他最近的一列,如果都要降序
Order bydeptno desc ,sal desc
按照奖金排序(奖金有可能为null)
Setpagesize 20//每一页显示的条数
Order bycomm.;// 升序是没有问题的
Order bycomm. desc;这样的话 comm.为null的都会在前面,而有数据的在后面进行排序
Order bycomm. desc nulls last ;// 这样就可以解决null在后面,oracle有,这个不符合sql 99
函数;
单行函数:一个输入、一个输出,只对一行进行变换。
多行函数:多个输入、一个输出
单行函数:字符、数值、日期、通用、转换等
字符函数:
大小写控制函数:lower、upper、initcap(首字母大写)
字符控制函数
concat、
substr(a,b从a中,第b位开始取)(a,b,c取c位)、
length(字符数)|lengthb(字节数)、instr(a,b在一个串中查找字串,返回下标,从1开始,否则返回0)、lpad|rpad(a,10,‘*’10位多余的*填充,左填充、又填充)、trim(去掉前后指定的字符)、replace
trim(‘H’ from ‘Hello’)
replace (‘hello’,’l’,’L’)
数字函数:
Round 四舍五入
Round (45.926,2)--45.93 小数点后两位
Round (45.926,-1)-- 50
Round (45.926,-2)--0
Trunc 截断
trunk(45.926,2)--45.92
trunk(45.926,0)--45.92
trunk(45.926,-1)--40
trunk(45.926,-2)--0
Mod 求余mod(1600,300)--100
日期:
Oracle中的日期类型数据实际含有两个值:日期和时间
默认的日期格式DD-MON-RR
Select to_char(sysdate,’yyyy-mm-ddhh24:mi:ss’) from dual;
selectto_char(systimestamp,’yyyy-mm-dd hh24:mi:ss*ff’)from dual
日期的数学运算:
在日期上加上或减去一个数字结果为日期(但是不允许日期+日期,因为今天加上明天没有任何意义)
Select (sysdate-1),sysdate,sysdate+1from dual;
在两个日期相减返回日期之间相差的天数
Selectename,hiredate,(sysdate-hiredate)天,(sysdate-hiredate)/7星期,(sysdate-hiredate)/30月,(sysdate-hiredate)/365年.
可以用数子除24来向日期中加上或减去小时
日期函数;
Months_between两个日期相差的天数
Add_month指定日期上加上若干月数
Next_day指定日期的下一个日期select next_day(sysdate,7)下个礼拜的今天
Last_day本月的最后一天
Round日期四舍五入
Trunk日期截断
Selectmonths_between(sysdate,hiredate)(相减) 算准工龄
快照 snapshot 给数据库拍个照片,数据库出问题后可以恢复
Now date----- 25-7-95
round(sysdate,’MONTH’)--à01-8-95
round(sysdate,’YEAR’)---à 01-1-96
trunk(sysdate,’MONTH’)--à01-7-95
trunk(sysdate,’YEAR’)--à01-1-95
日期格式的元素:
YYYY 2011
YEAR
MM 04
MONTH4月
DY|DAY 星期一
DD02
转换函数:
隐性:’123’à123(有一个前提:被转换对象是可以转换的)
Varchar2 --à number
Varchar2 --à date
Char--ànumber
Char--àdate
To_char(123) 、to_number(‘123’)、to_date
显性:
Select to_char(sysdate,’yyyy-mm-ddhh24:mi:ss “今天是” day’)
To_char(number,’fomat’)
9数字0零$美元L本地货币.小数点,千位符
查询员工的薪水,货币符号,两位小数
Selectsal,to_char(sal,’L9,999.99’)-à2598¥2,598.00
???to_number
通用函数;
Nvl(a,b)虑空函数当a为null时返回b
Nvl2(a,b,c)当a为null时返回c否则返回b
Nullif(a,b) a==b时返回null,否则返回a
Coalesce(a,b,c...)从左至右找到第一个不为null的值返回
条件表达式;
在 SQL语句中使用if-then-else逻辑
使用两种方法:
Case表达式:sql99的语法类似Basic,比较繁琐
Decode函数:oracle自己的语法,类似java
Case expr when expr1 then return_expr1
[whenexpr1 then return_expr1
Else else_expr
]
End
Decode(col|expred,search1,result[search1,result][default])
根据职位涨薪水(总裁1000、经理400、其他100)
Select ename,job,sal,case job when‘president’ then sal+100
When‘manager’ then sal+400
Elsesal+100
End ‘涨后薪水’
Selectename,job,sal,decode(job,’president’,sal+1000,
‘manager’,sal+400,
Sal+100) ‘涨后薪水’
使用decode函数:根据80号部门员工的工资,显示税率
Selectlast_name,sal,decode(trunk(sal/2000,0),
0,0.00,
1,0.09,
2,0.20,
3,0.30,
0.45) tax_rate
From employees
Where depart_id = 80
分组函数:作用于一组数据,并对一组数据返回一个数据
Avg
Count:
Max
Min
Sum
组函数会自动虑空,只会统计非空的数据
Count(*) count(nvl(comm,0))
Count(distinct dept_id)
Group by
在select列表中所有没有包含在组函数中的列都应该包含在groupby后面
包含在group by中的列不必包含在select列表中
求各个部门的平均工资
Select depno,avg(sal) from emp group bydepno
Select depno,depname,avg(sal) from empgroup by depno(mysql)
Select depno,depname,avg(sal)
from emp
group by depno,depname(oracle)
如果group by后面有多列怎么分组呢?
先按照第一列分,如果第一列相同,再按照第二列、、、、
上述语句的效果是按照部门中的每个职位分组
不能再where字句中使用组函数
Having:把满足条件的结果选出来,前提条件是必须要分组(过滤分组)
求出部门平均工资大于2000的部门
Selectdeptno,avg(sal)
Fromemp
Groupby deptno
Havingave(sal)>2000;
SQL优化三:
Having 和 where 的区别
求10号部门的平均工资
Select deptno,avg(sal)
From emp
Group deptno
Having deptno = 10;
Selectdeptno,avg(sal)
From emp
wheredeptno = 10;
如果having和where在业务中都可以尽量使用where,效率高于having
Where是先过滤再分组(先选出10号,再求)
Having是先分组再过滤(先对全部的分组,再过滤10号)
有一种情况例外只能使用having:如果条件中含有组函数只能使用having
嵌套组函数max(avg(sal))
Group by 语句增强
按照部门统计个部门不同工种的工资情况,要求如下:
Deptnojobsum(sal)
10clerk1300
Manager2450
3750
20clerk1900
Manager2692
7592
11342
Group by deptno,job
+
Group by deptno
+
Group by null
=
Group by rollup(deptno,job)
同理:
Group by rollup(deptno,job)
=
Group by deptno,job
+
Group by deptno
+
Group by null
Break on deptno skip 2// 以depto分段,跳跃空2行
Select depot,job,sum(sal)
From emp
Group by rollup(deptno,job)
多表的查询:
笛卡尔积:
Table120行5列table2 8行2列
笛卡尔积 20 * 8 = 160行5 + 2 = 7 列
多表查询就是从这个笛卡尔积中选出所符合条件的结果
Oracle链接;
Equijoin :等值链接whereemp.deptno = dep.deptno;
Non-equijion:不等值链接where emp.deptno between 10and 20
Outer join:外连接
Self join:自连接
外连接:
按部门统计员工人数-à部门号、部门名称、人数
Selectd.deptno,d.dname,count(e.empno)
From dept d,emp e
Where d.deptno = e.deptno(1)
Group by d.deptno,d.dname(如果某个部门没有员工,这样查不正确的)
外连接解决的问题:当条件不成立时候,仍然希望在结果中包含不成立的记录
左外连接:== 左边代表的表信息仍然包含在结果中
左外连接的表是在 == 的右边
写法把(1)改为 -à where e.deptno = d.deptno(+);
右外连接:与左外连接相反
自连接:核心是利用表的别名,将同一张表视为多张表
查询XX的老板是YY
Selecte.ename||’的老板是’||b.ename
Fromemp e,emp b
Wheree.mgr = b.empno;
层次查询:
自连接查找大表的时候(1亿行),笛卡尔积会很大,会严重影响性能,因此自连接不适合大表
层次查询可以解决这个问题(就是树操作,对树进行遍历)
层次查询后面from只能有一张表,因为不能有笛卡尔积
在层次查询中不再是表和表做连接操作,而是对同一张表的前后两次操作进行连接
上一层的员工就是下一层员工的老板,要遍历一棵树就必须知道根root
Connect by prior empno = mgr start withmgr is null(总boss)
或者 start with empno = 7566(从某一个管理人员开始)
Select level(伪列,层次1,2,3) ,empno,ename,mgr
From emp
Connect by prior empno = mgr
Start with mgr is null;
应用场景:中国-à江西à九江à都昌à街道
本文出自 “想要跨越,就要付出更多” 博客,请务必保留此出处http://andywuchuanlong.blog.51cto.com/4898493/1381752