SQL大全------之oracle

*********************************
**  oracle  学习笔记            **
**  author    Cindy                          **
***********************************
初始化表的位置:
cd $ORACLE_HOME/rdbms    cd demo        summit2.sql
这个角本可以初始化练习用的表
set  LANG = AMERICAN_AMERICA.US7ASCII
*********************************
我们目前使用的是oralce 9i    9201 版本
恢复练习表命令:
sqlplus  openlab/open123 @summit2.sql
登陆oracle的命令:
sqlplus    用户名/密码
show    user              显示当前登陆的身份.
set      pause on
set      pause off    分页显示.
oracle中默认日期和字符是左对齐,数字是右对齐
table or view does  not  exist ; 表或示图不存在
edit 命令用于自动打开vi修改刚修执行过的sql的命令。
修改方法二:
l  3 先定位到行      c    /旧串/新串
执行出错时,利用错误号来查错误:
!oerr ora 942  (装完系统后会装一个oerr工具,用于通过错误号来查看错
误的具体信息)
想在sql中执行unix命令时,把所有的命令前加一个!就可以, 或者host( 用
于从sql从切换至unix环境中去)
/*** 初次使用时注意  ****
运行角本时的命令:
先切换到unix环境下,cd $oracle_home    cd sqlplus  cd demo 下面有两
个角本建表语句。
@demobld.sql
sqlplus nanjing/nanjing @demobid.sql 直接运行角本,后面跟当前目录或
者是绝对路径
保存刚才的sql语句:    save 命令        第二次保存时要替换之前的角本
save 文件名    replace
把刚才保的sql重新放入  buffer中
spool  文件名
此命令会把所有的操作存在某个文件中去
spool off
练习1:查看s_emp表中员工的年工资
select  first_name  , salary*12  salary from s_emp;
给列起别名的命令:
利用关键字  as  或者用空格  "别名"  双引号内大小写敏感保持引号内容
原样输出,如果不加双引号时,默认为大写
拼接字段:
select    first_name||last_name  "employees"  from    s_emp ;
oracle中表达字符串用单引号来表达:
select first_name||' '||last_name  from    s_emp;(在两个字段之间拼接
一个空格)
查看当前用户所有的表:
练习2:(常用于批量更改数据)
set  echo off
spool  selecttab.sql;
select 'select * from ' || table_name ||' ; ' "table name " from
user_tables;
spool off;
set  head off(去除第一行)
set  feed off(去除最后一行)
练习3:(查出s_emp表中所有员工的一年的总收入)
select first_name , salary*12*( 1+nvl(commission_pct/100 , 0 ) ) "
year salary " from s_emp;
nvl函数 专用于处理空值的影响.
*******************************************************************
***************************************************************
column  定义格式化输出
column last_name  Heading    format a15;
column last_name;
column salary justify left format $99,999.00  ( 定义工资的显示形式
)
$ echo $LANG
zh_CN.hp15CN
$ echo $NLS_LANG
simplified chinese_china.zhs16cgbk
ORDER BY 排序  升序和降序    ASC  升序(默认)      DESC 降序
select * from s_emp  order by dept_id , salary desc  部门号升序,工
资降序
关键字distinct也会触发排序操作。
过滤操作:  where 子句
select * from s_emp  where dept_id=42;  查看部门号为42的所有员工
select * from s_emp  where salary>1000  查看工资高于1000的所有员工
select salary from  s_emp where first_name='Geroge'  找出名字为
Geroge的员工的工资数
select  table_name from  user_tables  where table_name='S_EMP';  查
某个具体表名时,表名的字符串必须要为大写
日期的默认的格式  DD-MON-RR(天-月-年)
BETWEEN  AND    在什么之间                      NOT              BETWEEN          AND
注意区间:[  ]是一个闭区间
IN( LIST)          在某个集合中                  NOT              IN                (list)
空值会有影响                (等于list其中任何一个就行,为提高效率常把比例
高的放在前面)
LIKE                    模糊配置                          NOT              LIKE
通配比较
IS NULL              是空
AND
OR
NOT
练习4:(找出表名以S_开头的所有表)对于一些特殊字符,要用到escape转义,
并不是一定要用\,escape后面定义是什么字符为转义字符,那就用哪个字符
select  table_name from user_tables where  table_name like    'S\_%'
escape '\';
当有多个条件时,要用逻辑运算符:AND OR
写对where语句:正确的数据类型判断、逻辑运算符
sql函数的作用:
sql函数的分类:单行函数、多行函数
单行函数: (dual    哑表 )
字符函数:
lower         转小写                  select  lower('SQLPLUS')  from dual;-->
对纯字符串处理的时候
upper          转大写                  select  upper('sqlplus')  from dual;
initcap      首字符大写          select  initcap('tarena') from dual;
concat        连接字符串          select  concat(first_name , last_name)
from s_emp;等效于
substr       求子串                  select  substr('tarenasd0603' ,1,6) from
dual; (取前六个字符)    select substr('tarenasd0603',-2) from dual;
(取后两个字符)
length       求字符长度          select  length('tarena') from dual;
nvl              空值函数      两个参数的类型要匹配,统一的,表示:如果有,
则返回前面的参数,如果没有就返回后面的参数
eg:select first_name,salary from s_emp where lower(first_name)
='george';
select  first_name , substr(first_name , -2 ) from  s_emp;  (查出
s_emp表中所有用户名字的最后两个字符)
默认的是从左向右,如果是-2则表示从右向左数
练习5:    select    first_name  , salary  from s_emp    where  lower
(first_name)='george';
数值函数:
round 函数(四舍五入)    select  round(45.935, 2) from dual;    不带参
数时默认为0位小数
trunc 函数(截取,不管后面的数字)      select  trunc(45.995, 1) from dual;
日期函数:DD-MON-RR ,默认不显示世纪、时、分、秒            日期格式敏感
世纪、年、月、日
sysdate 返回当前系统时间            select sysdate from dual;
更改当前会话的设置格式:
alter session set nls_date_format='yyyy mm dd hh24:mi:ss';
select  sysdate-1, sysdate+1, sysdate , sysdate+1 from dual;  注意
单位是以天为单位,也可以得到多少小时、多少分钟之后的时间
MONTHS_BETWEEN (DATE1 , DATE2 ) 求两个日期之前相差的月数
add_months(date , 4 ) 在 date上再添加4个月
select round(last_day(sysdate),'month') from dual;
select  next_day(sysdate,'FRIDAY') from dual ; 求这个日期的下一个
FRIDAY
last_day 求月的最后一天
round 函数:        select    round(sysdate, 'MONTH') from dual;        参
数可以为:  MONTH YEAR(看上半年还是下半年)
select  trunc(last_day(sysdate)+1)  from  dual;
select  add_months(trunc(sysdate, 'MONTH'), 1 )  from  dual ;
关于 日期的两种形式:
转换函数:
to_char显示日期:
从数字转化为char  to_char(date,'格式')
从日期转化为char                    to_char(date,  'fmt' )
select to_char(sysdate, 'yyyy mm dd hh24:mi:ss') from dual;
 
 
 
select to_char(sysdate, 'fmyyyy mm
dd hh24:mi:ss') from dual;去掉前导名
select  to_char(sysdate ,'YEAR MONTH
dy
eg:查出三月分入职的员工:select first_name,start_date from s_emp
where to_char(start_date,'mm')='03';
to_date表达日期:
字符转日期        select    to_date('2000 11 20', 'yyyy mm dd ')
from dual;
select  round(to_date('10-OCT-06'
,'dd-mon-RR') ) from    dual;
to_number
字符转数字
select to_number('10')  from  dual ;
 
where 条件一定是根据某个字段来进行过滤操作.
多表连接操作:
两表没有任何关联时会产生迪卡尔机:
select    first_name , name  from      s_emp , s_dept;
等值连接:
练习一:查看员工的姓名和员工部门号:(要考虑到表中实际数据中空值的影响)
select    first_name ,    name from  s_emp e, s_dept  d where e.dept_id=d.id;同时起了别名
select    first_name ,    name from  s_emp e, s_dept  d where e.dept_id=d.id and e.first_name='George';具体到哪个人所在的部门
练习二:每个员工所在的部门和部门所在的地区
select first_name , name    from s_emp, s_dept,  s_region  where  s_emp.dept_id=s_dept.id and s_dept.region_id=s_region.id;
eg:select first_name,d.name,r.name
from s_emp e,s_dept d,s_region r
where e.dept_id=d.id and d.region_id=r.id;
等值连接:
练习三:找出每个员工和每个员工的工资级别
select      a.ename , a.sal, b.grade from emp a , salgrade b  where a.sal between b.losal and b.hisal;
select      a.ename , a.sal, b.grade from  emp a , salgrade b  where a.sal>=b.losal  and  a.sal<=b.hisal;
自连接:当一个表的插入行之间有了关系时就发生了(又名:内连接)
select    first_name    , manager_id    from  s_emp;
查出所有员工的部门领导的名称:( 这种sql会少一条记录,总经理没有被配置上)
select  e.first_name , m.first_name    from s_emp e , s_emp m  where    e.manager_id=m.id;
外连接:(防止空值时,用(+)的一方会模拟一条记录配置另一方)这就称为外连接,一个记录都不能少;
select  e.first_name , m.first_name    from s_emp e , s_emp m  where    e.manager_id=m.id(+);
+号放在哪边就表示在哪边补空,来跟对方来匹配,使得数据一个都不会漏掉,这个例子中的领导有可能会没有(最高领导就再没有领导了,所以就
方法领导的那边)
标准写法:select e.deptno,d.name from emp e,dept d where e.deptno(+)=d.depton and e.depton is null;
查看员工分部的部门:
select  distinct(deptno) from emp ;
找出没有员工的部门:(很经典的一个例子,用外连接来解决的标准做法,这是一种方式)
第一步:
select        e.deptno , d.deptno  from emp e , dept d  where  e.deptno(+)=d.deptno;
第二步:
select        e.deptno , d.deptno  from emp e , dept d  where  e.deptno(+)=d.deptno    and    e.deptno is null;
组函数(group function):
group by  分组子句      对分组后的子句进行过滤还可以用having      条件  对分组后的条件进行过滤    where 是对记录进行过滤
avg(distinct | all )求平均值
count(distinct | all )统计
max(distinct | all ) 求最大值
min(distinct | all )求最小值
sum(distinct | all )  求和
(所有组函数会忽略空值 , avg    sum只能作用于数字类型)
求有提成员工的提成的平均值;
select      avg(nvl(commission_pct ,0 )  ) from s_emp;
有多少人有提成:
select  count( commission_pct ) from      s_emp ;
count(*)  用于统计记录数:
select    sum(commission_pct)/ count(*)    from        s_emp;
员工分部在多少个不同的部门:count  默认为作all的动作
select    count(dept_id)  from s_emp;
select    count(distinct dept_id) from    s_emp;
求各个部门的平均工资:group  by  子句也会触发排序
select  dept_id ,  avg(salary) aa      from      s_emp      group by    dept_id    order by  aa ;
select  dept_id ,  avg(salary) aa      from      s_emp      group by    dept_id      ;
注意:group by 子句后面跟有条件只能是查询的结果中的字段,所以我们会人为在结果要加入一些group by  要用的字段
select    region_id , count(*)  from  s_dept 此句会有错
select    max(region_id)  , count(*) from            s_dept;  (强制语法上可以正确,但是不能保证结果也会正确)
求各个部门不同工种的平均工资:
select        dept_id , title,  avg(salary)  from s_emp    group    by dept_id , title  ;
哪些部门的平均工资比2000高:
select      dept_id,  avg(salary) aa  from s_emp    group by (dept_id)      having          avg(salary)>2000;
除了42部门以外的部门的平均工资:
select    dept_id  ,  avg(salary)    from  s_emp  group by (dept_id ) having      dept_id!=42;
select    dept_id  ,  avg(salary)    from  s_emp    where    dept_id!=42  group by (dept_id ) ;(此种sql效率要高,先过滤再计算)
where            单行函数。
having          组函数。
求各个部门的平均工资:
// 这样统计不详细
select      max(d.name) ,  avg (s.salary)    from    s_emp  s,  s_dept  d where      s.dept_id=d.id    group by      d.name;
//****这问题很经典,为了过 oracle sql 语法关而写max(d.name)  ***
select    max(d.name)  , avg(e.salary)  , max(r.name)  from s_emp e,    s_dept  d ,    s_region  r  where  e.dept_id = d.id  and  d.region_id=r.id group  by    d.id ;
 
关于子查询:  Subqueries
找出所有员工中,工资最低的那个员工:( 利用子查询 )
select      first_name,  salary      from s_emp    where    salary = (  select  min(salary)  from s_emp)      ;
//这样写会出错姓名和工资不一致
select max(first_name),  min(salary)  from s_emp;(利用子查询可以解决)
子查询运行的顺序:先运行子查询再运行主查询      子查询一般出现在运算符的右边
单值运算符:运算后面只能跟一个值
多值运算符:可以对两个以上的值进行操作
查询谁跟Smith干一样的活:
select    last_name from  s_emp  where last_name='Smith';
//下种写法可能还存在bug,没有考虑到数据的全面性,有潜在性问题
select  last_name  , title  from s_emp    where title =(  select    title  from s_emp  where  last_name='Smith'  )      and  last_name <> 'Smith'  ;
//这种写法才考虑的比较全面
select  last_name  , title  from s_emp    where title    in    (  select    title  from s_emp  where  last_name='Smith'  )      and  last_name <> 'Smith'  ;
使用子查询时应注意:  单行子查询返回多个结果时会有错误      single-row  subquery returns  more  than one value
查出哪些员工的工资比平均工资低:
select      *  from s_emp  where        salary    <  ( select  avg(salary)  from    s_emp)  ;
哪些部门的平均工资比32部门的平均工资要低:
第一步先查出各个部门的平均工资:
select  min(avg(salary  )  ) from    s_emp    group by  dept_id;
第二步再查出哪个部门的工资是最低的:
select      dept_id,  avg(salary)  from  s_emp    group by dept_id    having    avg(salary) =  (select  min(avg(salary)  ) from  s_emp  group by  dept_id ) ;
哪个部门里没有员工:
select    deptno  from      dept      where    deptno    not  in ( select        deptno      from    emp );
哪些人是普通员工:(用子查询形式来做)
select    *    from  s_emp    where    id  not      in (  select  manager_id    from    s_emp);
E--R图  实体关系图entity  relation
开发流程先进行需求分析,进行系统设计,建表,再进行开发编码,测试最终产品上线试运行。
把软件设计模型转化为数据中的表,设计时要考虑性能的设计
第一范式:最简单的一种建方式,一张表只有一个主键。
第二范式:表的自连接存在原因,一张表,学生表中也有班级的信息。
第三范式:表连接存在的原因,两张表,其中一张表引用其它一张表。
 

你可能感兴趣的:(oracle,数据库,职场,休闲)