oracle学习之基本查询和条件过滤,分组函数使用
oracle是殷墟出土的甲骨文的第一个单词,所以在中国叫做甲骨文,成立于1977年,总部位于美国加州。
在安装好后,主要有两个服务需要开启:
1,实例服务,OracleServiceORCL,决定是否可以连接上数据库
2,监听服务,OracleOraDb11g_home1TNSListener,决定是否可远程连接数据库
在安装好客户端后,登录方式:
sqlplus 用户名/密码
如果是远程登录,需要加上连接别名,或者IP:
sqlplus 用户名/密码@//IP地址/实例名 or sqlplus 用户名/密码@连接名
数据库基本查询:
select * from tab;
tab是一个数据字典,字义了当前用户有哪些表,以及类型,查看表结构:
desc dept
注意,如果显示行大小和宽度不正确,可以通过修改登录设置文件改变:
路径:\app\Administrator\product\11.2.0\client_1\sqlplus\admin set linesize 140;//设置行大小 set pagesize 120;//设置页宽度 col empno for 99999;//修改数值型字段长度 col ename for a20;//设置字符型字段长度
sql语法的注意事项:关键字不能缩写,不能换行,以分号结尾!
查看sqlplus的所有命令:
? topic
查询SQL语句语法:
select [distinct]*|column_name|expr|alias from tablename
查询员工号,姓名,月薪,奖金,年薪:
注意,奖金字段有为null的结果,可以通过虑空函数解决,即:nvl(a,b),如果a为null,返回b,否则返回a
如果需要查看员工表不同的部门编号,并且去除重复的,可以这么做:
通常,我们还可以借助伪表来进行一些的数学计算或函数操作:
select 3+20*5,sysdate from dual;
比较运算符的查询条件过滤: = != <> < > <= >= (between and)
case1: 查询入职日期为1981年11月17日的员工信息:
select * from emp where hiredate = '1981-11-17'
这里要注意,如果显示文字与格式字符串不匹配的问题,通常必须按照具体日期格式写:
如果自己想修改这个日期格式,可以进入管理员用户后修改,如下:
SQL> select sysdate from dual; //修改会话日期格式 SQL> alter session set nls_date_format='yyyy-mm-dd'; //后面就可以这样查询了: SQL> select * from emp where hiredate ='1981-11-17';
逻辑运算符 and or not,这里特别说明一下,查找工资在1000~2000的员工信息:
select * from emp where sal >= 1000 and sal <= 2000; //或者 select * from emp where sal between 1000 and 2000;
between and 是属于闭区间,从小到大!
如何正确查询奖金为空的员工信息 - null
select * from emp where comm is null;
当and or 存在多个条件写,如何来写才更优?
sql语句是从右到左执行,and情况,应该将易假的放在右侧,or情况,应该将真的放在右侧。
like ->模糊查询,'%'匹配任意多个字符,'_'匹配任意一个字符
重点:查询带在下划线'_'的应该怎么查询:
select * from emp where ename like '%/_%' escape '/';
排序:group by; having; order by;语法如下:
order by col|expr|alias|number
员工薪水按从大到小排序(序号)
select * from emp order by sal desc; //或者 select * from emp order by 6 desc; //或者 select empno,ename,job,mgr,sal,comm,deptno from emp order by 5 desc;
这里更要注意null的情况,默认无穷大:
解决办法是:
select * from emp where deptno = 30 order by comm desc nulls last;
//或者
select * from emp where deptno = 30 order by nvl(comm,-1) desc;
oracle的单行函数:
什么叫单行函数,即对一行进行变换,只产生一个结果。
lower(小写),upper(大写),initcap(首字母大写),||(可以进行字符串连接)
select lower('hello WorLD') one,upper('HeLLo woRld') two,initcap('hello WOrld') from dual; select 'aaaa'||'bbbb'||'cccc' from dual;
substr(字符串,位置,长度),从位置开始截取长度,长度可以省略,代表截取到未尾:
select substr('helloworld',1,3) one,substr('helloworld',1) two ,substr('helloworld',-3) three from dual;
length求字符串长度,lengthb求字节长度:
instr(str1,str2) ,判断str2是否在str1中,如果存在返回出现的首位置,否则返回0:
select instr('hello world','llo') from dual;
lpad,rpad,左右填充l(r)pad(str,len,char) 返回len长度的字符串,如果str不够长度,则是char字符填充:
select lpad('hello',10,'#') from dual;
trim(str)去首尾空格,replace(str,substr,strto)替换
select 'aaa'||trim(' hello world ')||'bbb' from dual;
还能这么玩:
重要:数值函数,round四舍五入,trunc截断,mod取模
select round(45.926, 2) 一, round(45.926, 1) 二, round(45.926, 0) 三, round(45.926, -1) 四, round(45.926, -2) 五 from dual; select trunc(45.926, 2) 一, trunc(45.926, 1) 二, trunc(45.926, 0) 三, trunc(45.926, -1) 四, trunc(45.926, -2) 五 from dual; select mod(600,1000),mod(1000,600) from dual; //ceil 和floor 向上取整,向下取整 select ceil(121/60),floor(121/60) from dual;
重要:转换函数,to_char,to_number,to_date
把薪水转换为本地货币字符型:
select sal,to_char(sal,'L9,999') from emp;
如果要将这个在转回数值型,语句是一样的:
select to_number('¥1,250','L9,999') from dual;
to_char 与 to_date 显示 'yyyy-mm-dd hh24:mi:ss 今天是 星期几'
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss "今天是" day') from dual;
将上述字符串反转为日期:
select to_date('2017-11-10 15:48:13 今天是 星期五','yyyy-mm-dd hh24:mi:ss "今天是" day') from dual;
此处可以解决一个隐式日期转换问题:
select * from emp where to_char(hiredate,'yyyy-mm-dd')='1981-11-17';
上面的能显示转换,尽量显示转换。
重要:日期函数,months_between add_months last_day next_day
1,显示昨天,今天,明天:
select sysdate-1 昨天,sysdate 今天,sysdate+1 明天 from dual;
2,计算员工工龄,可以按日,周,月,年,日期差减方法
select months_between(sysdate,to_date('2017-10-10','yyyy-mm-dd')) from dual;
3,求明年的今天:
select add_months(sysdate,12) from dual;
4,求指定日期所在月份最后一天
select last_day(sysdate) from dual;
5,求指定日期的下一个星期几日期:
select next_day(sysdate,'星期一') from dual;
条件表达示:
CASE expr WHEN comparison_expr1 THEN return_expr1 [WHEN comparison_expr2 THEN return_expr2 WHEN comparison_exprn THEN return_exprn ELSE else_expr] END
老板打算给涨工资,总裁1000,经理800,其它400,将涨前,涨后根据职业列出:
select empno,ename,job,sal 涨前薪水,case job when 'PRESIDENT' then sal+1000 when 'MANAGER' then sal+800 else sal+400 end 涨后薪水 from emp
另外在oracle中,还可以使用decode函数,其它Sql不支持:
语法:decode(expr,search1,res1,search2,res2,…,default)
select empno,ename,job,sal 涨前薪水,decode(job,'PRESIDENT',sal+1000,'MANAGER',sal+800,sal+400) 涨后薪水 from emp
分组函数:avg,sum,min,max,count
1,求员工的工资总和:
select sum(sal) from emp;
2,求员工的总人数:
select count(empno),count(*) from emp;
3,求emp表中工种数:
4,求平均工资(三种方式):
分组数据:在select中出现的非组函数的列,必须在group by中出现
1,查询各部门平均工资:
select deptno,avg(sal) from emp group by deptno;
2,查询各部门,各工种平均工资:
select deptno,job,avg(sal) from emp group by deptno,job;
3,查询平均薪水大于2000的部门:
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
4,求10号部门员工的平均薪水:
select deptno,avg(sal) from emp where deptno=10 group by deptno;
此处注意,第3和第4条,where后不能放分组函数,deptno不是,所以可以在where后
where 是先过滤,后分组,having是先分组后过滤,所以相对来说where要好些。
常见的非法使用组函数情况:
最后对null进行一个总结:
1,null不能用 = 或者 !=,应该使用 is
2,not in的集合中不能有null
3,null无穷大,默认排在最前
4,表达式中null参与运算,结果为null,应使用nvl(a,b)
5,分组函数会自动过滤null