sql 使用汇总(PQSQL)
- --sql structured query language
- --DML--Data Manipulation Language--数据操作语言
- query information (SELECT),
- add new rows (INSERT),
- modify existing rows (UPDATE),
- delete existing rows (DELETE),
- perform a conditional update or insert operation (MERGE),
- see an execution plan of SQL (EXPLAIN PLAN),
- and lock a table to restrict access (LOCK TABLE).
- --DDL--Data Definition Language--数据定义语言
- create, modify,drop, or rename objects (CREATE,ALTER,DROP,RENAME),
- remove all rows from a database object without dropping the structure (TRUNCATE),
- manage access privileges (GRANT,REVOKE),
- audit database use (AUDIT,NOAUDIT)
- and add a description about an object to the dictionary (COMMENT).
- --Transaction Control事务控制语句
- save the changes(COMMIT)
- or discard the changes (ROLLBACK) made by DML statements.
- Also included in the transaction-control statements are statements to set a point or marker in the transaction for possible rollback (SAVEPOINT)
- and to define the properties for the transaction (SET TRANSACTION).
- Used to manage the properties of the database.
- There isonly one statement in this category (ALTER SYSTEM).
- --DCL--Data Contro Language--与开发关系不是很密切,用于权限的分配与回收
- grant,revoke,data control
- --Session Control
- control the session properties (ALTER SESSION)
- and to enable/disable roles (SET ROLE).
- --System Control
- --------------------------------------------------------
- select的用法
- --每个员工的所有信息
- select * from emp;
- --每个人的部门编号,姓名,薪水
- select empno, ename, sal from emp;
- --每个人的年薪
- select ename, sal*12 from emp;
- --计算2*3的值
- select 2*3 from emp;
- --计算2*3的值(dual)
- select 2*3 from dual;
- --得到当前时间
- select sysdate from dual;
- --可以给列起别名,比如求每个人的年薪
- select ename, sal*12 annual_sal from emp;
- --如果别名中有空格,需要用双引号
- select ename, sal*12 "annual sal" from emp;
- --如果没有内容,则为空
- select ename, sal, comm from emp; /*null*/
- --当空字段参与计算,则结果是null
- --例如:计算每个人的全年的收入包括月薪和年终奖
- select ename, sal * 12 + comm from emp;
- --可以将多个字符串拼在一起。比如:求每个人的薪水,格式为smith-sal-123
- select ename || '-' || sal || '-' || comm from emp;
- --如果字符串中有单引号,需要用另外一个单引号转义,比如:这样一个字符串: he's friend
- select ename || 'he''s friend' from emp;
- --------------------------------------------------------
- --distinct 关键词的用法
- --求有哪些个部门
- select deptno from emp;
- select distinct deptno from emp;
- --可以用来修饰多个字段
- --求有哪些个部门和job的组合
- select deptno , job from emp;
- select distinct deptno , job from emp;
- --------------------------------------------------------
- where关键词的用法
- --可以是数值类型的等值判断。比如:求10这个部门的所有员工
- select * from emp where deptno = 10;
- --可以是字符串类型的等值判断。比如:求叫KING的这个人的信息
- select * from emp where ename = 'KING';
- --也可以是不等值判断。比如:求薪水小于2000的员工信息
- select * from emp where sal > 2000;
- --字符串也可以做不等值判断,比如:求所有ename大于'CBA'的员工信息。
- select ename from emp where ename > 'CBA';
- --求部门不是10的部门
- select * from emp where deptno <> 10;
- --求薪水在800和1500之间的员工信息
- select * from emp where sal between 800 and 1500;
- --也可以写成
- select * from emp where sal >= 800 and sal <= 1500;
- /*这样写则不可以
- --select * from emp where 800 <= sal <= 1500;
- */
- --where...in..的用法。比如:求薪水是800或者1500或正2000的员工信息
- select ename, empno, sal from emp where sal in (800, 1500, 2000);
- --相当于写成这样
- select ename, empno , sal from emp where sal = 800 or sal = 1500 or sal = 2000;
- --再比如求姓名是KING,SMITH,AA的员工信息
- select ename, empno , sal from emp where ename in ('KING', 'SMITH', 'AA');
- --求入职时间在20-2月-81之后的员工信息
- select ename, hiredate from emp where hiredate > '20-2月-81';
- --------------------------------------------------------
- --and or not的用法
- --求薪水大于1000或者部门在10这个部门的员工信息
- select * from emp where sal > 1000 or deptno = 10;
- --求薪水不是800或者不是1500或者不是3000的员工信息
- select * from emp where sal <> 800 and sal <> 1500 and sal <> 3000;
- --也可以这样来写
- select * from emp where sal not in (800, 1500, 3000);
- --------------------------------------------------------
- --like的用法
- --求名字中包含ALL这三个字符的员工信息
- select ename from emp where ename like '%ALL%';
- --求名字中的第二个字母是A的员工
- select ename from emp where ename like '_A%';
- --特殊字符需要转义。比如:求员工中包含特殊字符%的员工信息
- select ename from emp where ename like '%\%%' escape '\';
- --------------------------------------------------------
- --null的用法
- --求没有年终奖的员工
- select ename from emp where comm is null;
- --求有年终奖的员工
- select ename from emp where comm is not null;
- --------------------------------------------------------
- --order by的用法
- --员工信息按照姓名正序排列
- select ename, sal from emp order by ename asc; --ascent
- --员工信息按照倒叙排列
- select ename, sal from emp order by ename desc; --descent
- --也可以是多个字段组合排列。例如:员工信息按照部门正序排列,并且按照姓名倒叙排列
- select ename, sal, deptno from emp order by deptno asc, ename desc;
- --------------------------------------------------------
- --function的用法
- --把所有姓名变成小写
- select lower(ename) from emp;
- --把所有姓名变成大写
- select upper(ename) from emp;
- --求所有人名中包含'a'的员工信息不区分大小写
- select ename from emp where lower(ename) like '%a%';
- --截取子字符串,比如求Hello的一部分
- select substr('Hello', 2) from dual;
- --求Hello的一部分,并指明长度
- select substr('Hello', 2, 3) from dual;
- --求ascii码对应的字符
- select chr(65) from dual;
- --求字符对应的ascii码
- select ascii('中') from dual;
- --四舍五入
- select round(23.652) from dual;
- --四舍五入小数点后面多少位
- select round(23.652, 1) from dual;
- --四舍五入小数点前面多少位
- select round(23.652, -1) from dual;
- --------------------------------------------------------
- --important!日期转换函数
- --------------------------------------------------------
- --将当前日期转换成1981-03-12 12:00:00这种形式的字符串
- select to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') from dual;
- --将1981-03-12 12:00:00字符串转换成日期
- select to_date('1981-03-12 12:00:00', 'YYYY-MM-DD HH24:MI:SS') from dual;
- --将每个人的薪水转换成固定格式的字符串
- select to_char(sal, 'L00,000.9999') from emp;
- --将固定格式的字符串转换成数值
- select to_number('$1,250.00', '$9,999.99') from dual;
- --null当null参与计算时候,需要要nvl这个函数
- select ename, sal*12+comm from emp;
- select ename, sal*12+ nvl(comm, 0) from emp;
- --------------------------------------------------------
- --group function组函数
- --求所有人的薪水的总和,平均值,最大值,最小值
- select sum(sal) , avg(sal), max(sal) , min(sal) from emp;
- --求总的行数
- select count(*) from emp;
- --求总的行树,(可以指定具体的字段)但如果字段有null值的时候需要小心使用
- select count(comm) from emp;
- --也可以过滤掉重复的行之后统计行数
- select count(distinct deptno) from emp;
- --可以指明按照哪个字段进行分组.比如;分部门统计最高薪水
- select deptno, max(sal) from emp group by deptno;
- --也可以按照多个字段来分组统计,比如:分部门和岗位,统计最高薪水和行数
- select deptno, job , max(sal), count(*) from emp group by deptno, job;
- --------------------------------------------------------
- --重要:出现在select列表中的字段,如果没有在组函数中,那么必须出现在group by 子句中。
- --------------------------------------------------------
- --select ename, deptno, max(sal) from emp group by deptno;
- --select ename, max(sal) from emp;
- --求薪水最高的员工姓名
- select max(sal) from emp;
- select ename, sal from emp where sal = 5000;
- select ename from emp where sal = (select max(sal) from emp);
- --having从句的用法
- --求平均薪水是2000以上的部门
- select avg(sal), deptno from emp group by deptno having avg(sal) > 2000;
- --------------------------------------------------------
- --总结一下select语法
- select
- from
- where
- group by
- having
- order by
- --------------------------------------------------------
- -- 执行顺序very important!
- -- 首先执行where语句将原有记录过滤;
- -- 第二执行group by 进行分组;
- -- 第三执行having过滤分组;
- -- 然后将select 中的字段值选出来;
- -- 最后执行order by 进行排序;
- --------------------------------------------------------
- /*
- 按照部门分组统计,求最高薪水,平均薪水
- 只有薪水是1200以上的才参与统计
- 并且分组结果中只包括平均薪水在1500以上的部门
- 而且按照平均薪水倒叙排列
- */
- select max(sal),avg(sal), deptno
- from emp
- where sal > 1200
- group by deptno
- having avg(sal) > 1500
- order by avg(sal) desc;
- --------------------------------------------------------
- /*
- 把雇员按部门分组,
- 求最高薪水, 部门号,
- 过滤掉名字中第二个字母是'A'的,
- 要求分组后的平均薪水>1500,
- 按照部门编号倒序排列
- */
- select deptno, max(sal)
- from emp
- where ename not like '_A%'
- group by deptno
- having avg(sal) > 1500
- order by deptno desc;
- /* very very important! */
- select ename, deptno from emp;
- select deptno, dname from dept;
- ----员工姓名以及员工所在部门的名字同时显示出来
- select ename, dname from emp , dept;
- select ename, dname from emp , dept where emp.deptno = dept.deptno;
- --要求每位雇员的薪水等级
- select ename, sal, grade from emp, salgrade where emp.sal >= salgrade.losal and emp.sal <= salgrade.hisal;
- select ename, sal, grade from emp e, salgrade s where e.sal between s.losal and s.hisal;
- --求工作职位是’PRESIDENT’的雇员姓名,部门名称和薪水等级时
- select ename, dname, grade
- from emp e, dept d, salgrade s
- where e.deptno = d.deptno and e.sal between s.losal and s.hisal
- and job = 'PRESIDENT';
- --求每位员工的姓名,及其上级经理的姓名
- select empno, ename, mgr from emp;
- select e1.ename, e2.ename from emp e1, emp e2 where e1.mgr = e2.empno;
- --新语法
- --在SQL1992的语法规则中,语句过滤的条件和表连接的条件都被放在了where子句中,当条件过多时,容易造成混淆,
- --SQL1999修正了这个缺点,将连接条件和数据过滤条件区分开来,
- --交叉连接
- --结果会产生这两张表的笛卡尔乘积
- select ename , dname from emp cross join dept; --inner join
- --要用deptno作为等值连接条件,我们可以这样写
- select ename, dname from emp join dept using(deptno);
- --相当于
- select ename, dname from emp join dept on emp.deptno = dept.deptno;
- --也可以写成这样
- select ename, dname from emp join dept on (emp.deptno = dept..deptno);
- --也可以用于非等值连接
- --求每位雇员的薪水等级
- select ename, sal, grade from emp
- join salgrade on (emp.sal >= salgrade.losal and emp.sal <= salgrade.hisal);
- --多个join,where组合使用
- --(求工作职位是’PRESIDENT’的雇员姓名,部门名称和薪水等级时)
- select ename, dname , grade from emp e
- join dept d on (e.deptno = d.deptno)
- join salgrade s on (e.sal between s.losal and s.hisal)
- where job = 'PRESIDENT';
- --外连接--取出表中连接不到一起的多余的数据
- --没有全内连接,没有右内连接
- --其中outer也可以省略,简写为left join , right join , full join
- --left inner join可以缩写成inner join 也可以缩写成join,意思是左内。
- --update emp set deptno=null where ename='SMITH';
- --commit;
- --左内
- select dname,ename from emp left inner join dept using(deptno)
- --左外连接
- select ename,dname from emp left outer join dept using(deptno)
- --右外连接
- select ename,dname from emp right outer join dept using(deptno)
- --全外连接
- select ename,dname from emp full outer join dept using (deptno);
- --左外,右外的区别
- select e1.ename,e2.ename from emp e1 join emp e2 on(e1.mgr = e2.empno);
- select e1.ename,e2.ename from emp e1 left outer join emp e2 on(e1.mgr = e2.empno);
- select e1.ename,e2.ename from emp e1 right outer join emp e2 on(e1.mgr = e2.empno);
- select e1.ename,e2.ename from emp e1 full outer join emp e2 on(e1.mgr = e2.empno);
- --什么时候用外连接呢:
- ----比如领导向你要所有学生的列表,顺便把所属的班级也列出来,就需要外连接
- --在Where语句中使用子查询
- -----------------------------------------------------------------
- --雇员中最高薪水的人员名称
- --1,先求出最高薪水
- --2,再求雇员中最高薪水的人员名称
- select ename from emp where sal = (
- select max(sal) from emp
- );
- --有哪些人的薪水是在整个雇员的平均薪水之上的
- select empno, ename from emp where sal > (select avg(sal) from emp);
- -----------------------------------------------------------------
- --雇员中哪些人是经理人
- --1,首先查询mgr中有哪些号码
- --2,再看有哪些人员的号码在此出现
- select ename from emp where empno in (
- select distinct mgr from emp where mgr is not null
- );
- -----------------------------------------------------------------
- --在From子句中使用子查询
- ------------------------------------------------------------------
- --部门平均薪水的等级
- --1,首先将每个部门的平均薪水求出来
- --2,然后把结果当成一张表,再用这张结果表和salgrade表做连接,以此求得薪水等级
- select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- join salgrade s on (t.avg_sal between s.losal and s.hisal);
- -----------------------------------------------------------------
- --每个部门最高薪水的人员名称
- --1,首先将每个部门的最高薪水求出来
- --2,然后把结果当成一张表,再用emp和这张结果表做连接,以此求得每个部门最高薪水的人员名称
- select ename, sal, emp.deptno from emp join
- (select deptno, max(sal) max_sal from emp group by deptno) t
- on (emp.sal = t.max_sal and emp.deptno = t.deptno);
- -----------------------------------------------------------------
- --哪些人的薪水在部门的平均薪水之上
- --1,首先将每个部门的平均薪水求出来
- --2,然后把结果当成一张表,再用emp和这张结果表做连接,以此求得哪些人的薪水在部门的平均薪水之上
- select ename, sal from emp join
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- on (emp.sal > t.avg_sal and emp.deptno = t.deptno);
- -----------------------------------------------------------------
- --求部门中(所有人的)平均的薪水等级,形式如:
- -- deptno avg_grade
- -- 10 3.67
- -- 20 2.8
- -- 30 2.5
- --1,先求每个人的薪水等级
- --2,再按照部门分组,求平均数
- select deptno , avg(grade) from
- (select ename, deptno, grade from emp e
- join salgrade s on (e.sal between s.losal and s.hisal)
- )
- group by deptno;
- ------------------------------------------------------------------------------------------
- --使用伪字段:rownum,----------------------
- ------------------------------------------------------------------------------------------
- --用来标识每条记录的行号,行号从1开始,每次递增1
- select ename from emp where rownum <= 5;
- --oracle下rownum只能使用 < <=, 不能使用 = > >= 等比较操作符,
- select ename from emp where rownum > 5;
- --当rownum和order by 一起使用时,会首先选出符合rownum条件的记录,然后再排序
- --(错误的写法)例如,当我们要求薪水最高的前5个人时,最直接的想法可以这样写:
- select ename, sal from emp where rownum <= 5 order by sal desc;
- --(正确的写法)可以这样写
- select ename, sal
- from
- (select ename, sal from emp order by sal desc)
- where rownum <= 5;
- --------------------------------------------------------
- --不准用组函数(即MAX()),求薪水的最高值(面试题)
- --第一种解决办法:
- --1,先把所有薪水按照倒序排列
- --2,再取第一行
- select sal from (
- select sal from emp order by sal desc
- )
- where rownum <= 1;
- --第二种解决办法:
- --1,先跨表查询自己,先求出的结果中,e1.sal不可能出现最大数
- --2,然后再not in
- select distinct sal from emp where sal not in (
- select distinct e1.sal from emp e1 join emp e2 on (e1.sal < e2.sal)
- );
- -----------------------------------------------------------------
- --求平均薪水最高的部门的部门编号
- --第一种解决办法:
- --1,先求出每个部门的平均薪水,
- --2,再求每个部门的平均薪水的最高值,
- --3,最后再求第一步结果中avg_sal = 最高薪水的记录.
- select deptno from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- where avg_sal =
- (
- select max(avg_sal) from
- (select deptno, avg(sal) avg_sal from emp group by deptno)
- );
- --第二种解决办法:
- --1,将上面的第一步第二步合并,先求最高平均薪水,用max(avg(sal))的办法
- --2,求出每个部门的平均薪水
- --3,最后再求第二步结果中(即每个部门的平均薪水),avg_sal = (第一步结果)的记录.即avg_sal =最高薪水的记录.
- select deptno from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- where avg_sal = (select max(avg(sal)) from emp group by deptno);
- --第三种解决办法:
- --1,先求出每个部门的平均薪水,
- --2,求最高平均薪水,用max(avg(sal))的办法
- --3,再使用having语句, avg(sal) = 第二步的结果
- 注意:为组函数起的别名在having中不能用
- select deptno, avg(sal)
- from emp
- group by deptno
- having avg(sal) = (select max(avg(sal)) from emp group by deptno);
- -----------------------------------------------------------------
- --求平均薪水最高的部门的部门名称
- --1,部门平均最高薪水
- --2,得到部门编号列表,注意用group by deptno
- --3,再应用having子句, having avg(sal) = (第一步的结果)
- --4,得到平均最高薪水的那个部门的编号
- --5,再得到部门名称
- select dname from dept where deptno in (
- select distinct deptno from emp group by deptno
- having avg(sal) = (
- select max(avg(sal)) from emp group by deptno
- )
- )
- -----------------------------------------------------------------
- --求平均薪水的等级最低的部门的部门名称
- --第一步:部门平均薪水的等级,分成两个小步骤,第一小步是求部门平均薪水
- select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- join salgrade s
- on (t.avg_sal between s.losal and s.hisal)
- --第二步:最低的等级值
- select min(grade) from (第一步的结果)
- --第三步:等于最低值的部门编号
- ------------有错误,应该是grade=
- select deptno from (第一步的结果) where grade = (第二步的结果)
- --第四步:求名称
- select dname from dept where deptno in (第三步的结果)
- select dname from dept where deptno in
- (select deptno from
- (
- select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- join salgrade s
- on (t.avg_sal between s.losal and s.hisal)
- )
- where grade =
- (
- select min(grade) from
- (
- select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- join salgrade s
- on (t.avg_sal between s.losal and s.hisal)
- )
- )
- )
- --也可以用视图的方式来解决
- --conn sys/bjsxt as sysdba
- --grant create table, create view, create sequence to scott
- --根据第一步的结果,建立一个view
- create view v$_dept_info as
- select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t
- join salgrade s
- on (t.avg_sal between s.losal and s.hisal);
- --查看一下
- desc v$_dept_info;
- --查询一下
- select * from v$_dept_info;
- --带入view
- select dname from dept where deptno in (
- select deptno from (
- v$_dept_info
- )
- where grade = (
- select min(grade) from (
- v$_dept_info
- )
- )
- )
- -------------------------------------------------------------
- --为什么in的后面不能order by ?
- select dname from dept where deptno
- in
- (select deptno
- from salgrade s,( select avg(sal) avg_sal,deptno from emp group by deptno ) t
- where t.avg_sal<=s.hisal and t.avg_sal>=s.losal and rownum=1
- order by deptno)
- ---------------------------------------------------------------
- --求部门经理人中平均薪水最低的部门名称 (思考题)
- ----------------------------------------------------------------------------
- --求比普通员工的最高薪水还要高的经理人名称
- --1,求所有经理的编号
- select distinct mgr from emp where mgr is not null
- --2,普通员工的最高薪水
- select max(sal)
- from emp
- where empno not in (select distinct mgr from emp where mgr is not null);
- --3,
- select ename, sal
- from emp
- where empno in (第一步的结果)
- and sal >(第二步的结果)
- --即:
- select ename, sal
- from emp
- where empno in (select distinct mgr from emp where mgr is not null)
- and sal >
- (select max(sal)
- from emp
- where empno not in
- (select distinct mgr from emp where mgr is not null));
- ------------------------------------------------------------------------------
- --求薪水最高的前5名雇员
- --1,先观察一下
- select rownum , ename , sal from emp;
- --2,看看rownum的作用
- select rownum ,ename, sal from emp where rownum <= 5;
- --3,不是我们想要的结果
- select rownum ,ename, sal from emp where rownum <= 5 order by sal desc;
- --4,先order by,再rownum
- select rownum ,ename, sal from (select ename, sal from emp order by sal desc) where rownum <= 5;
- --------------------------------------------------------------------------------
- --求薪水最高的第6到第10名雇员(重点掌握)
- --这种没法实现,oracle下rownum只能使用 < <=, 不能使用 = > >= 等比较操作符
- --注意里面的rownum和外面的rownum的区别,外面要想访问里面的rownum,必须取得一个别名。
- select ename, sal, rownum
- from (select ename, sal from emp order by sal desc)
- where rownum >= 6 and rownum <= 10;
- --所以再套一层select
- select ename, sal from
- (select ename, sal, rownum r from
- (select ename, sal from emp order by sal desc)
- )
- where r >= 6 and r <= 10;
- --还有一种排序方式
- minus
- --------------------------------------------------------------------
- --练习: 求最后入职的5名员工
- --1,每个人的入职时间
- select ename, hiredate from emp order by hiredate desc
- --2,取前5行
- select ename, hiredate
- from (select ename, hiredate from emp order by hiredate desc)
- where rownum <= 5;
- -----------------------------------------------------------------
- --求每个部门中薪水最高的前两名雇员
- --1,每个员工的工资,按部门和工资排列
- select ename, deptno, sal from emp order by deptno, sal desc
- --2,套一层,加上个r
- select ename, deptno, sal, rownum r
- from (select ename, deptno, sal from emp order by deptno, sal desc);
- --3,创建试图
- create view v$_t as
- select ename, deptno, sal, rownum r from (select ename, deptno, sal from emp order by deptno, sal desc);
- --观察一下
- desc v$_t;
- select * from v$_t
- --每个部门中,薪水最高的第一行,并创建试图
- create view v$_t2 as
- select deptno, min(r) min_r from v$_t group by deptno;
- select * from v$_t2
- --两个view跨表连接,大于薪水最高的行数,小于最高的行数+1,并且部门编号要匹配
- select ename, sal from v$_t join v$_t2
- on (v$_t.r >= v$_t2.min_r and v$_t.r <= v$_t2.min_r + 1 and v$_t.deptno = v$_t2.deptno);
- -------------------------------------------------------------------------------
- --面试题: 比较效率
- select * from emp where deptno = 10 and ename like '%A%';
- select * from emp where ename like '%A%' and deptno = 10;
- ---------------------------------------------------------
- --使用union、minus
- --使用union、minus可以用来实现结果集的合并和去除(可以理解为加和减),例如:
- select ename, empno from emp where deptno = 10
- union
- select ename, empno from emp where deptno = 20
- --相当于
- select ename, empno from emp where deptno = 10 or deptno = 20;
- --而下面的语句
- select ename, empno from emp where deptno in (10,20)
- minus
- select ename, empno from emp where sal < 1500
- --相当于
- select ename, empno from emp where deptno in (10,20) and sal >= 1500;
- --求分段显示薪水的个数
- select ename, sal from emp where deptno = 10
- union
- select ename, sal from emp where sal > 2000;
- select ename, sal from emp where deptno = 10
- minus
- select ename, sal from emp where sal > 2000;
- 如:
- scale total
- <800 0
- 801-1000 2
- 1001-2000 3
- 2001-5000 6
- >5000 8
- select '<800' as scale , count(*) as total from emp where sal < 800
- union
- select '801-1000' as scale, count(*) as total from emp where sal between 801 and 1000;
- --或者显示成为
- --注意:使用between .. and .. 的时候,包含了最大和最小值。
- 800-1000 1001-2000 2000-5000
- 2 3 6
- select * from
- (select count(*) as "800-1000" from emp where sal between 800 and 1000),
- (select count(*) as "1001-2000" from emp where sal between 1001 and 2000),
- (select count(*) as "2001-5000" from emp where sal between 2001 and 5000);
- --或显示成为
- DEPTNO 800-2000 2001-5000
- ------ ---------- ----------
- 30 5 1
- 20 2 3
- 10 1 2
- select t1.deptno, "800-2000", "2001-5000" from
- (
- select deptno , count(*) as "800-2000" from emp where sal between 800 and 2000
- group by deptno
- ) t1
- join
- (
- select deptno , count(*) as "2001-5000" from emp where sal between 2001 and 5000
- group by deptno
- ) t2
- on
- t1.deptno = t2.deptno
- -----------------------------------------------------------------------------------
- --每个薪水等级有多少名雇员 ?
- --1,先求出每个雇员的薪水等级
- select ename, sal, grade from emp e join salgrade s on (e.sal between s.losal and s.hisal)
- --2,再group一下
- select grade, count(*)
- from (select ename, sal, grade
- from emp e
- join salgrade s on (e.sal between s.losal and s.hisal))
- group by grade;
- -------------------------------------------------------------------------
- 有3个表S,C,SC
- S(SNO,SNAME)代表(学号,姓名)
- C(CNO,CNAME,CTEACHER)代表(课号,课名,教师)
- SC(SNO,CNO,SCGRADE)代表(学号,课号成绩)
- 问题:
- 1,找出没选过“黎明”老师的所有学生姓名。
- 2,列出2门以上(含2门)不及格学生姓名及平均成绩。
- 3,即学过1号课程又学过2号课所有学生的姓名。
- 请用标准SQL语言写出答案,方言也行(请说明是使用什么方言)。
- -----------------------------------------------------------------------------
- CREATE TABLE SC
- (
- SNO VARCHAR2(200 BYTE),
- CNO VARCHAR2(200 BYTE),
- SCGRADE VARCHAR2(200 BYTE)
- );
- CREATE TABLE S
- (
- SNO VARCHAR2(200 BYTE),
- SNAME VARCHAR2(200 BYTE)
- );
- CREATE TABLE C
- (
- CNO VARCHAR2(200 BYTE),
- CNAME VARCHAR2(200 BYTE),
- CTEACHER VARCHAR2(200 BYTE)
- );
- INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '', '语文', '张');
- INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '', '政治', '王');
- INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '', '英语', '李');
- INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '', '数学', '赵');
- INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '', '物理', '黎明');
- commit;
- INSERT INTO S ( SNO, SNAME ) VALUES ( '', '学生1');
- INSERT INTO S ( SNO, SNAME ) VALUES ( '', '学生2');
- INSERT INTO S ( SNO, SNAME ) VALUES ( '', '学生3');
- INSERT INTO S ( SNO, SNAME ) VALUES ( '', '学生4');
- commit;
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '', '', '');
- commit;
- ------------------------------------------------------------------------
- 答案:
- 问题1.找出没选过“黎明”老师的所有学生姓名。
- 第一步:求黎明老师教的所有课的课号
- select distinct cno from c where cteacher='黎明'
- 第二步:选了黎明老师的所有学生的编号
- select sno from sc where cno in (
- 第一步的结果
- )
- 第三步:没有选黎明老师的所有学生的姓名
- select sname from s where sno not in (
- 第二步的结果
- )
- 即:
- select sname from s where sno not in (
- select sno from sc where cno in (
- select distinct cno from c where cteacher='黎明'
- )
- )
- ----------------------------------------------------------------------------
- 问题2:列出2门以上(含2门)不及格学生姓名及平均成绩。
- 第一步:2门以上不及格的学生的学号
- select sno from sc where scgrade < 60 group by sno having count(*) >= 2
- 第二步:每个学生平均分
- select sno, avg(scgrade) as avg_grade from sc group by sno
- 第三步:第一步中得到的学号对应的学生姓名以及平均分
- select s.sname ,avg_grade from s
- join
- 第一步的结果
- on s.sno = t.sno
- join
- 第二步的结果
- on s.sno = t1.sno
- 即:
- select s.sname ,avg_grade from s
- join
- (select sno, count(*) from sc where scgrade < 60 group by sno having count(*) >= 2)t
- on s.sno = t.sno
- join
- (select sno, avg(scgrade) as avg_grade from sc group by sno )t1
- on s.sno = t1.sno
- 错误的写法:
- 错误在于:求的是所有不及格的课程的平均分,而不是所有课程(包括及格的)的平均分
- 执行顺序:
- 首先会执行Where语句,将不符合选择条件的记录过滤掉,
- 然后再将过滤后的数据按照group by子句中的字段进行分组,
- 接着使用having子句过滤掉不符合条件的分组,
- 然后再将剩下的数据排序显示。
- select sname, avg_scgrade from s join
- (select sno, avg(scgrade) avg_scgrade from sc where scgrade < 60 group by sno having count(*) >= 2) t
- on (s.sno = t.sno);
- ----------------------------------------------------------------------------
- 问题3:即学过1号课程又学过2号课所有学生的姓名。
- 第一步:学过1号课程的学号
- select sno from sc where cno = 1
- 第二步:学过2号课程的学号
- select sno from sc where cno = 2
- 第三步:即学过1号课程又学过2号课的学号
- select sno from sc where cno =1 and sno in (select sno from sc where cno = 2)
- 第四步:得到姓名
- select sname from s where sno in (
- select sno from sc where cno = 1 and sno in (select sno from sc where cno = 2)
- )
- 或者:
- select sname from s where
- sno in (select sno from sc where cno = 1)
- and
- sno in (select sno from sc where cno = 2)
- --DML语句
- --DML语句用于添加、删除和修改表中的数据,
- --包含三条最常用的语句,即Insert、Update和Delete。
- --Insert语句插入数据
- --方式一:指定字段列表
- insert into emp (empno, ename, job, deptno)
- values (9998, 'TEST', 'CLERK', 20);
- select * from emp;
- --显式的插入一个空值,可以用NULL值来表示,
- insert into emp (empno, ename, job, sal , deptno)
- values (9997, 'TEST2', 'CLERK', null, 20);
- --省略字段列表
- insert into emp
- values (9999, 'TEST3', 'CLERK', '', NULL, 8000, NULL, 30);
- --应用子查询
- --可以先查看一下,当前有几个表
- select table_name from user_tables
- --创建一个表
- create table emp7 as select * from emp;
- --查询一下
- select * from emp7
- --再插入一些结果
- insert into emp7 (select * from emp5)
- --再查询一下,应该28条记录才对
- select * from emp5
- --------------------------------------------------------------------------------------
- --Update语句更新数据
- update emp
- set sal = sal * 1.1;
- --修改表中部分的值
- --将部门号为10的所有员工的薪水都上涨10%
- update emp
- set sal = sal * 1.1
- where deptno = 10;
- --更新多个字段
- update emp5
- set sal=sal*1.1,ename='aaa'
- --应用子查询
- --给所有经理涨工资
- update emp7 set sal=sal*1.1
- where empno in(
- select distinct mgr from emp7 where mgr is not null
- )
- ----------------------------------------------------------------------------------
- --Delete语句删除数据
- --不指定where条件的时候,Delete语句将删除表中全部的数据
- select * from emp7;
- Delete from emp7;
- --删除表中部分数据
- Delete from emp2
- Where deptno = 20;
- --恢复旧有的数据
- --(扣钱、吐钱应该作为一组动作同时完成)
- --要么同时完成,要么同时不完成的动作就称为一个Transaction
- --大多数数据库系统都支持Transaction,在Oracle中,一个Transaction起始于一条DML语句,结束于以下的几种情况:
- --1. 用户显式执行Commit语句提交操作或Rollback语句回退。
- --2. 当执行DDL语句或DCL语句时事务自动提交。
- --3. 用户正常断开连接时,Transaction自动提交。
- --4. 系统崩溃或断电时事务自动回退。
- delete from emp where empno = 9998;
- select * from emp;
- commit;
- rollback;
- NUMBER[(precision [, scale])]
- NUMBER(p, s)
- 其中p,s都是可选的:
- p代表精度,默认为38
- s代表小数位数,取值范围-84~127,
- 默认取值要看是否指定了p,
- 如果指定了p,默认s为0,
- 如果没有指定p,默认取最大值。
- 其他的数值类型都是number的衍生,底层都是number,比如integer/int完全映射到number(38)
- 默认应该是
- number(38,127)
- 范围: 1 <= p <=38, -84 <= s <= 127
- 保存数据范围:-1.0e-130 <= number value < 1.0e+126
- 保存在机器内部的范围: 1 ~ 22 bytes
- 有效位:从左边第一个不为0的数算起的位数。
- s的情况:
- s > 0
- 精确到小数点右边s位,并四舍五入。然后检验有效位是否 <= p。
- s < 0
- 精确到小数点左边s位,并四舍五入。然后检验有效位是否 <= p + |s|。
- s = 0
- 此时NUMBER表示整数。
- eg:
- Actual Data Specified As Stored As
- ----------------------------------------
- 123.89 NUMBER 123.89
- 123.89 NUMBER(3) 124
- 123.89 NUMBER(6,2) 123.89
- 123.89 NUMBER(6,1) 123.9
- 123.89 NUMBER(4,2) exceeds precision (有效位为5, 5 > 4)
- 123.89 NUMBER(6,-2) 100
- .01234 NUMBER(4,5) .01234 (有效位为4)
- .00012 NUMBER(4,5) .00012
- .000127 NUMBER(4,5) .00013
- .0000012 NUMBER(2,7) .0000012
- .00000123 NUMBER(2,7) .0000012
- 1.2e-4 NUMBER(2,5) 0.00012
- 1.2e-5 NUMBER(2,5) 0.00001
- 123.2564 NUMBER 123.2564
- 1234.9876 NUMBER(6,2) 1234.99
- 12345.12345 NUMBER(6,2) Error (有效位为5+2 > 6)
- 1234.9876 NUMBER(6) 1235 (s没有表示s=0)
- 12345.345 NUMBER(5,-2) 12300
- 1234567 NUMBER(5,-2) 1234600
- 12345678 NUMBER(5,-2) Error (有效位为8 > 7)
- 123456789 NUMBER(5,-4) 123460000
- 1234567890 NUMBER(5,-4) Error (有效位为10 > 9)
- 12345.58 NUMBER(*, 1) 12345.6
- 0.1 NUMBER(4,5) Error (0.10000, 有效位为5 > 4)
- 0.01234567 NUMBER(4,5) 0.01235
- 0.09999 NUMBER(4,5) 0.09999
- --delete from test;
- --drop table test;
- --create table test(
- -- n NUMBER
- --);
- --insert into test (n) values(123.89);
- --select * from test
- --第三章 数据库常用对象
- 字段类型 中文说明 限制条件 其它说明
- CHAR 固定长度字符串 最大长度2000 bytes
- --VARCHAR2 可变长度的字符串 最大长度4000 bytes 可做索引的最大长度749
- NCHAR 根据字符集而定的固定长度字符串 最大长度2000 bytes
- NVARCHAR2 根据字符集而定的可变长度字符串 最大长度4000 bytes
- --DATE 日期(日-月-年) DD-MM-YY(HH-MI-SS) 经过严格测试,无千虫问题
- LONG 超长字符串 最大长度2G(231-1) 足够存储大部头著作
- RAW 固定长度的二进制数据 最大长度2000 bytes 可存放多媒体图象声音等
- LONG RAW 可变长度的二进制数据 最大长度2G 同上
- BLOB 二进制数据 最大长度4G
- --CLOB 字符数据 最大长度4G
- NCLOB 根据字符集而定的字符数据 最大长度4G
- BFILE 存放在数据库外的二进制数据 最大长度4G
- ROWID 数据表中记录的唯一行号 10 bytes ********.****.****格式,*为0或1
- NROWID 二进制数据表中记录的唯一行号 最大长度4000 bytes
- --NUMBER(P,S) 数字类型 P为整数位,S为小数位
- DECIMAL(P,S) 数字类型 P为整数位,S为小数位
- INTEGER 整数类型 小的整数
- FLOAT 浮点数类型 NUMBER(38),双精度
- REAL 实数类型 NUMBER(63),精度更高
- -------------------------------------------------------------------------------------------------------
- Category Datatypes
- Character CHAR, NCHAR, VARCHAR2, NVARCHAR2
- Number NUMBER
- Long and raw LONG, LONG RAW, RAW
- Date and time DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE,TIMESTAMP WITH LOCAL TIME ZONE, INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND
- Large object CLOB, NCLOB, BCLOB, BFILE
- Row ID ROWID, UROWID
- ------------------------------------------------------------------------------------------------------------
- --Varchar2(n) 变长字符串,存储空间等于实际空间的数据大小,最大为4K
- --Char(n) 定长字符串,存储空间大小固定
- --Number(p,s) 整数或小数
- ----ps参数的含义
- --Date 年、月、日、时、分、秒
- --Long 变长字符串,最大字节数达到2GB
- --Oracle还提供了二进制和字节大对象,即BLOB、CLOB等类型,常用于二进制数据的保存,例如图片、音频、视频等等,
- --BLOB
- --CLOB
- ---------------------------------------------------------------------------------------------------------------
- --varchar & varchar2 & nvarchar & nvarchar2区别
- 1,varchar早就建议不使用了,应该用VARCHAR2。nvarchar估计也不使用的,也应该是使用nvarchar2。
- 2,VARCHAR2(size),可变长度的字符串,其最大长度为 size 个字节。
- size 的最大值是 4000,而最小值是 1。您必须指定一个 VARCHAR2 的 size。
- 3,NVARCHAR2(size),可变长度的字符串,依据所选的国家字符集,其最大长度为 size 个字符或字节。
- size 的最大值取决于存储每个字符所需要的字节数,其上限为 4000 个字节。
- 您必须为 NVARCHAR2 指定一个 size。
- 4,VARCHAR2与NVARCHAR2的不同之处在于它们存放信息占用的空间不同。
- VARCHAR2存放的英文字符只占一个字节,而nvarchar2依据所选的字符集,大多为两个。
- 5,当你的数据库字符集不是unicode,比如ZHS16GBK,
- 但又想在个别字段存储诸如中文冷僻字的unicode字符时,
- 就可以选择nvarchar2,但必须9i版本以上的.
- 6,nvachar定义的是字符数,varchar定义的是字节数
- 所以nvachar(10)放入varchar(10)就会出现此错误,因为varchar(10)只能放10个字节的数据
- select lengthb('錒') from dual;
- -------------------------------------------------------------------------------------------------------------------
- 3.1.1创建表
- --建立一张用来存储学生信息的表,
- drop table stu;
- select * from stu;
- rollback;
- create table stu(
- id number(6),
- name varchar2(20),
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50)
- );
- --在创建表的时候,我们还可以使用子查询来参考现有的一张表
- create table emp2
- as
- select * from emp;
- --在子查询中使用任何查询的语法
- create table emp_dept
- as
- select ename, dname from emp join dept using (deptno);
- --创建表时指定约束条件
- --1. NOT NULL 非空
- --2. UNIQUE KEY 唯一
- --3. PRIMARY KEY 主键
- --4. FOREIGN KEY 外键
- --5. CHECK 自定义检查约束
- --非空约束
- 要求姓名不能为空
- create table stu(
- id number(6),
- name varchar2(20) not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50)
- );
- --可以给这个约束起一个名字:
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50)
- );
- --唯一性约束
- --email字段不应该有重复值
- --unique约束只是代表该字段的值不能重复,但空值是允许的
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50) unique
- );
- --可以给unique约束起一个名字:
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50) constraint stu_email_uni unique
- );
- --还可以将约束加在字段定义完毕后
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50),
- constraint stu_email_uni unique(email)
- );
- --也可以在表级约束中用一个约束条件同时约束多个字段,
- --比如我们要求email和名字的组合值不能重复
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50),
- constraint stu_email_uni unique(name, email)
- );
- --主键约束
- --主键可以用来唯一的标识一条记录,
- --主键相当于非空约束和唯一约束的组合,
- --在一张表中只允许有一个主键,
- --这个主键可以是一个或者多个子段的组合
- create table stu(
- id number(6) primary key,
- name varchar2(20) constraint stu_name_nn not null,
- …
- email varchar2(50),
- constraint stu_email_uni unique(name, email)
- );
- --主键可以定义在多个子段上,此时用这些字段的组合来标识唯一的一条记录,
- --语法上只能够采用表级约束
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- …
- email varchar2(50),
- constraint stu_email_uni unique(name, email),
- constraint stu_id_name_pk primary key (id, name)
- );
- --外键约束
- --外键约束建立于一张表的两个字段或两张表的两个字段上,
- --用于保证两个字段的关系,即:
- ----子表外键字段的值必须在参照字段的取值中存在,
- ----并且,如果字段的值被别的字段参照时,记录不允许被删除。
- --外键约束被参考的字段必须是主键!
- --违反完整约束条件
- insert into emp (empno, ename, job, deptno)
- values (9997, 'TEST', 'CLERK', 80);
- --违反完整约束条件
- delete from dept where deptno = 10;
- select * from dept;
- --建立另外一张表class,用来表示班级的信息,
- create table class(
- id number(4) primary key,
- name varchar2(20) not null
- );
- --在创建stu表时加入外键约束:
- --drop table stu;
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4) references class(id),
- email varchar2(50) constraint stu_email_uni unique
- );
- --也可以采用表级约束语法:
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50) constraint stu_email_uni unique,
- constraint stu_class_fk foreign key (class) references class(id)
- );
- --违反完整约束条件
- insert into stu
- values (1, 'test', 0, 22, to_date('2005-03-02' , 'YYYY-MM-DD'), 1, 1, 'test@test.com')
- --想插入stu表中任何的class的值,必须在class表中id字段找到,因此,我们首先执行下面的语句:
- insert into class values (1, 'Class1');
- --当stu表中已经有记录参照了class表中id为1的记录时,违反完整约束条件
- delete from class where id = 1;
- --Check约束
- --Check约束用于检验字段的值是否符合某个条件表达式,
- --要求插入stu表中年龄字段的值不能为负数
- create table stu(
- id number(6),
- name varchar2(20) constraint stu_name_nn not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50) constraint stu_email_uni unique,
- constraint stu_class_fk foreign key (class)references class(id),
- constraint stu_age_min check (age > 0)
- );
- --在Check约束中,条件表达式可以使用and、or、not等逻辑操作符。
- create table stu(
- id number(6) primary key,
- name varchar2(20) not null,
- sex number(1),
- age number(3),
- sdate date,
- grade number(2) default 1,
- class number(4),
- email varchar2(50) unique,
- constraint stu_class_fk foreign key (class)references class(id),
- constraint stu_age_min check (age > 0)
- );
- --------------------------------------------------------------------------------------
- --修改表结构或其约束条件-->即alter table语句,
- --增加字段-----给stu表增加一个家庭住址的字段
- alter table stu add (addr varchar2(100));
- --删除字段-----例如要讲我们刚才新增的addr字段进行删除,
- alter table stu drop (addr);
- --修改字段-----例如我们要修改新增的addr字段的精度
- --注意如果原来该字段中没有任何数据,那么可以将字段修改为任何类型,否则,所修改的类型必须能够容纳原有的数据。
- alter table stu modify (addr varchar2(150));
- --删除或增加约束条件
- --删除stu表中的外键约束stu_class_fk,可以这样写:
- alter table stu
- drop constraint stu_class_fk;
- --加入新的约束:
- alter table stu
- add constraint stu_class_fk foreign key (class) references class(id);
- --注意-----非空约束不能够使用类似的语法,只能够通过修改字段来同时修改约束,例如:
- --将name字段上的非空约束去除:
- alter table stu modify (name varchar2(20) null);
- --在name字段上添加非空约束:
- alter table stu modify (name varchar2(20) not null);
- --当无法确定一个约束的名字的时候,可以向系统表中寻找,有关系统表的操作,请参考附录《数据库常用DBA操作》,也可以将原来的表删除,然后建立新的表。
- --select * from user_objects
- --删除表
- Drop table stu;
- --索引是为了加快对数据的搜索速度而设立的,
- --对stu表中的email字段建立索引
- create index idx_stu_email on stu(email);
- --对两个字段的组合建立索引,
- create index idx_stu_email_class on stu(email, class);
- --我们想删除刚刚建立的索引,可以这样写:
- drop index inx_stu_email_class;
- --视图
- --不用视图-->非常复杂的查询语句(求平均薪水的等级最低的部门的部门名称):
- select dname, grade from
- (select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t,
- salgrade s
- where
- t.avg_sal between s.losal and s.hisal )
- t1,
- dept
- where t1.deptno = dept.deptno
- and
- t1.grade =
- (select min(grade) from
- (select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t,
- salgrade s
- where
- t.avg_sal between s.losal and s.hisal )
- );
- --建立视图
- create view v$_temp as
- (select deptno, avg_sal, grade from
- (select deptno, avg(sal) avg_sal from emp group by deptno) t,
- salgrade s
- where
- t.avg_sal between s.losal and s.hisal );
- --上面的查询就可以简化为:
- select dname from dept, v$_temp where
- v$_temp.deptno = dept.deptno
- and grade = (select min(grade) from v$_temp);
- --适当的利用视图,可以使我们的查询变得简单,
- --但是如果视图建立的太多的话,会给我们系统的维护带来麻烦,
- ----比如如果表的结构了,与这张表有关的任何视图必须跟着修改,
- --删除一张视图的时候,
- drop view v$_temp;
- --序列----->序列是oracle专有的对象,它用来产生一个自动递增的数列,
- create table article(
- id number,
- title varchar2(1024),
- content long
- );
- ---创建序列
- create sequence seq_article_id start with 1 increment by 1;
- ---使用序列
- ----select * from article
- insert into article
- values (seq_article_id.nextval, 'TEST', 'test content');
- --删除序列
- drop sequence seq_article_id;
- --数据库设计
- --BBS需求
- --1,可以登陆,可以退出
- --2,用户可以注册
- --3,所有人可以发帖,可以回帖
- --4,划分不同的板块
- --5,每个板块有一个或多个版主,一个人可以是多个板块的版主
- --select * from user;
- create table tbl_user(
- us_id number(6) primary key,
- us_username varchar2(20),
- us_password varchar2(20),
- us_rdate date
- );
- create table tbl_board(
- bd_id number(6) primary key,
- bd_name varchar2(200),
- bd_masterid varchar2(200)
- );
- create table tbl_topic(
- tp_id number(6) primary key,
- tp_title varchar2(200),
- tp_content varchar2(4000),
- tp_us_id number(6) references tbl_user(us_id),
- tp_bd_id number(6) references tbl_board(bd_id),
- tp_pid number(6),
- tp_pdate date,
- tp_rootid number(6)
- );
- --树状结构的设计
- 1:id - pid
- 2:id - pid - isleaf - level - childcount
- 递归效率增加
- 插入、删除、修改效率降低
- 支持平板形式支持的不好
- 3:id - pid - isleaf - level - childcount - rootId
- 平板形式好实现
- 4:id pid rootid 代表字符串(代表数字)
- 最多每个节点能有99个小孩
- 最多有3层
- 01 00 00 第一层第一个 01 00 00
- 01 01 00 第一个回复 01 01 00
- 01 02 00 01 01 01
- 01 02 01 01 02 00
- 01 01 01 01 02 01
- --权限设计
- 1: 资源Resource
- 帖子,用户信息,板块信息
- 2: 权限privilege
- 发帖,删贴,回复帖,查询贴,添加用户,删除用户,查询用户,修改用户密码,修改用户信息,......
- 2: 角色role,可以赋予多个权限
- 一系列权限的组合
- 3: 用户对应一到多个权限
- 1:用户登陆
- 2:验证属于什么角色
- 3:检查该角色是不是具备操作权限
- --简化的权限设计:用户表,角色表
- --思考那些人会使用该系统?
- --要站在使用者的角度去分析
- create table tbl_role(
- rl_id number(6) primary key,
- rl_name varchar2(20),
- rl_code date
- );
- create table tbl_user(
- us_id number(6) primary key,
- us_username varchar2(20),
- us_password varchar2(20),
- us_rdate date,
- us_rl_id number(6) references tbl_role(rl_id),
- );
- declare - 可选
- 声明各种变量或游标的地方。
- begin - 必要
- 开始执行语句。
- --单行注释语句用两个连在一起的'-'表示。
- /*多行注释语句,
- 可以换行*/
- exception - 可选
- 出错后的处理。
- end; - 必要(请注意end后面的分号)
- 结束。
- -----------------------------------------------------------------------------
- --最简单的语句块
- begin
- dbms_output.put_line('HelloWorld!');
- end;
- set serveroutput on;
- -------------------------------------------------------------------------------
- --简单的PL/SQL语句块
- declare
- v_name varchar2(20);
- begin
- v_name := 'myname';
- dbms_output.put_line(v_name);
- end;
- ---------------------------------------------------------------------------
- --语句块的组成
- declare
- v_num number := 0;
- begin
- v_num := 2/v_num;
- dbms_output.put_line(v_num);
- exception
- when others then
- dbms_output.put_line('error');
- end;
- --在变量声明时需要遵守一些基本的规则:
- 1. 变量名不能够使用保留字,如from 、select等
- 2. 第一个字符必须是字母
- 3. 变量名最多包含30个字符
- 4. 不要与数据库的表或者列同名
- 5. 每一行只能声明一个变量
- --PL/SQL中的变量类型主要有以下几种:
- 1. binary_integer:整数,主要用来计数而不是用来表示字段类型
- 2. number:数字类型
- 3. char:定长字符串
- 4. varchar2:变长字符串
- 5. date:日期
- 6. long:长字符串,最长2GB
- 7. boolean:布尔类型,可以取值为true、false和null值
- --变量声明
- declare
- v_temp number(1):=5;
- v_count binary_integer := 0;
- v_sal number(7,2) := 4000.00;
- v_date date := sysdate;
- v_pi constant number(3,2) := 3.14; --相当于java里面的final
- v_valid boolean := false;
- v_name varchar2(20) not null := 'MyName';
- begin
- dbms_output.put_line('v_temp value:' || v_name);
- end;
- --变量声明,使用%type属性
- declare
- v_empno number(4);
- v_empno2 emp.empno%type; --好处,表的定义变了,这里跟着变
- v_empno3 v_empno2%type;
- begin
- dbms_output.put_line('Test');
- end;
- --简单变量赋值
- declare
- v_name varchar2(20);
- v_sal number(7,2);
- v_sal2 number(7,2);
- v_valid boolean := false;
- v_date date;
- begin
- v_name := 'MyName';
- v_sal := 23.77;
- v_sal2 := 23.77;
- v_valid := (v_sal = v_sal2);
- v_date := to_date('1999-08-12 12:23:38', 'YYYY-MM-DD HH24:MI:SS');
- --dbms_output.put_line(v_sal == v_sal2);
- end;
- --复合变量
- --Table变量类型
- --相当于java里面的数组
- declare
- --声明了一个数组类型,约定俗成以type_开头
- --下标的类型是binary_integer类型
- type type_table_emp_empno is table of emp.empno%type index by binary_integer;
- v_empnos type_table_emp_empno;
- begin
- v_empnos(0) := 7369;
- v_empnos(2) := 7839;
- v_empnos(200) := 9999; --下标可以取负值
- dbms_output.put_line(v_empnos(200));
- end;
- --Record变量类型
- --相当于java里面的类
- declare
- type type_record_dept is record
- (
- deptno dept.deptno%type,
- dname dept.dname%type,
- loc dept.loc%type
- );
- v_temp type_record_dept;
- begin
- v_temp.deptno := 50;
- v_temp.dname := 'aaaa';
- v_temp.loc := 'bj';
- dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname);
- end;
- --使用%rowtype声明record变量
- --表结构变了,这段程序不用变
- declare
- v_temp dept%rowtype;
- begin
- v_temp.deptno := 50;
- v_temp.dname := 'aaaa';
- v_temp.loc := 'bj';
- dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname);
- end;
- --SQL语句的运用
- --select必须返回一条记录并且只能返回一条记录
- --select必须和into一起用
- declare
- v_ename emp.ename%type;
- v_sal emp.sal%type;
- begin
- select ename,sal into v_ename,v_sal from emp where empno = 7369;
- dbms_output.put_line(v_ename || ' ' || v_sal);
- end;
- --ORA-01403: 未找到数据
- declare
- v_ename emp.ename%type;
- v_sal emp.sal%type;
- begin
- select ename,sal into v_ename,v_sal from emp where empno = 9999;
- dbms_output.put_line(v_ename || ' ' || v_sal);
- end;
- --实际返回的行数超出请求的行数
- declare
- v_ename emp.ename%type;
- v_sal emp.sal%type;
- begin
- select ename,sal into v_ename,v_sal from emp where deptno = 30;
- dbms_output.put_line(v_ename || ' ' || v_sal);
- end;
- --v_emp可以存贮一条记录
- declare
- v_emp emp%rowtype;
- begin
- select * into v_emp from emp where empno = 7369;
- dbms_output.put_line(v_emp.ename);
- end;
- --insert
- declare
- v_deptno dept.deptno%type := 50;
- v_dname dept.dname%type := 'aaaa';
- v_loc dept.loc%type := 'bj';
- begin
- insert into dept2 values (v_deptno, v_dname, v_loc);
- commit;
- end;
- select * from dept2;
- --sql%rowcount
- declare
- v_deptno emp2.deptno%type := 30;
- v_count number;
- begin
- --update emp2 set sal = sal/2 where deptno = v_deptno;
- --delete from emp2 where deptno = 10;
- --select deptno into v_deptno from emp2 where empno = 7369 ;
- select count(*) into v_count from emp2;
- dbms_output.put_line(sql%rowcount || '条记录被影响');
- --commit;
- end;
- rollback;
- --PL/SQL使用DDL语句
- --必须写execute immediate......
- begin
- execute immediate 'create table T (nnn varchar2(20) default ''aaa'')';
- end;
- drop table T;
- -------------------------------------------------------------------------------------------------------------------
- --if语句
- --取出7369的薪水,如果<1200,则输出'low',如果<2000则输出'middle',否则'high'
- --注意elsif的写法
- --注意else后面没有then
- --注意end if后面有一个分号
- declare
- v_sal emp.sal%type;
- begin
- select sal into v_sal from emp
- where empno = 7369;
- if (v_sal < 1200) then
- dbms_output.put_line('low');
- elsif(v_sal < 2000) then
- dbms_output.put_line('middle');
- else
- dbms_output.put_line('high');
- end if;
- end;
- --IF
- --FI
- --循环
- --第一种
- declare
- i binary_integer := 1;
- begin
- loop
- dbms_output.put_line(i);
- i := i + 1;
- exit when ( i >= 11);
- end loop;
- end;
- --第二种
- declare
- j binary_integer := 1;
- begin
- while j < 11 loop
- dbms_output.put_line(j);
- j := j + 1;
- end loop;
- end;
- --第三种
- begin
- for k in 1..10 loop
- dbms_output.put_line(k);
- end loop;
- for k in reverse 1..10 loop
- dbms_output.put_line(k);
- end loop;
- end;
- ---------------------------------------------------------------------
- --错误处理1
- --这条select,返回多条记录,会产生异常
- declare
- v_temp number(4);
- begin
- select empno into v_temp from emp where deptno = 10;
- exception
- when too_many_rows then
- dbms_output.put_line('太多记录了');
- when others then
- dbms_output.put_line('error');
- end;
- --错误处理2
- declare
- v_temp number(4);
- begin
- select empno into v_temp from emp where empno = 2222;
- exception
- when no_data_found then
- dbms_output.put_line('没数据');
- end;
- --------------------------------------------------------------------------------------------------------------------
- --游标 (重点)
- --open c 的时候,才执行select语句
- declare
- cursor c is
- select * from emp;
- v_emp c%rowtype;
- begin
- open c;
- fetch c into v_emp;
- dbms_output.put_line(v_emp.ename);
- close c;
- end;
- --最常用的游标属性有以下四个:
- --1. %isopen,boolean类型变量,用来代表游标是否打开。
- --2. %notfound,boolean类型变量,如果最近的fetch语句没有返回一条记录,取true。
- --3. %found,boolean类型变量,如果最近的fetch语句取到了记录,取true。
- --4. %rowcount,number类型变量,用来代表目前fetch到的记录的总行数。
- declare
- cursor c is
- select * from emp;
- v_emp c%rowtype;
- begin
- open c;
- loop
- fetch c into v_emp;
- exit when (c%notfound);
- dbms_output.put_line(v_emp.ename);--如果这行挪到上边,最后一行打印两遍
- end loop;
- close c;
- end;
- --while
- declare
- cursor c is
- select * from emp;
- v_emp c%rowtype;
- begin
- open c;
- fetch c into v_emp;
- while (c%found) loop
- dbms_output.put_line(v_emp.ename);
- fetch c into v_emp;--如果这行挪到上边,最后一行打印两遍
- end loop;
- close c;
- end;
- --for.自动打开,自动关闭
- --最简单的,不容易出错
- declare
- cursor c is
- select * from emp;
- begin
- for v_emp in c loop
- dbms_output.put_line(v_emp.ename);
- end loop;
- end;
- --带参数的游标
- --声明两个行参
- --v_temp c%rowtype;--不需要声明
- declare
- cursor c(v_deptno emp.deptno%type, v_job emp.job%type)
- is
- select ename, sal from emp where deptno = v_deptno and job = v_job;
- --v_temp c%rowtype;
- begin
- --open c(30, 'CLERK');
- for v_temp in c(30, 'CLERK') loop
- dbms_output.put_line(v_temp.ename);
- end loop;
- end;
- --可更新的游标
- --用的不多
- --注意:for update
- --注意游标的用法:where current of c,
- --判断两个值是不是相等,用一个等号
- declare
- cursor c
- is
- select * from emp2 for update;
- --v_temp c%rowtype;
- begin
- for v_temp in c loop
- if(v_temp.sal < 2000) then
- update emp2 set sal = sal * 2 where current of c;
- elsif (v_temp.sal = 5000) then
- delete from emp2 where current of c;
- end if;
- end loop;
- commit;
- end;
- ----------------------------------------------------------------------------------------------------------------------
- --存储过程
- --带名字的plsql程序块
- create or replace procedure p
- is
- cursor c is
- select * from emp2 for update;
- begin
- for v_emp in c loop
- if (v_emp.deptno = 10) then
- update emp2 set sal = sal + 10 where current of c;
- elsif (v_emp.deptno = 20) then
- update emp2 set sal = sal + 20 where current of c;
- else
- update emp2
sql 使用汇总(PQSQL)的更多相关文章
- SQL小汇总
SQL小汇总 1.对每个时段的数据进行统计2.查询时间条件(to_date)3.插入序列号和系统时间4.查询当天.7天内.30天内5.查询前后x小时.分钟.天.月.6.保留小数点后4位7.查询字段A中 ...
- SQL语句汇总(终篇)—— 表联接与联接查询
上一篇博文说到相关子查询效率低下,那我们怎么能将不同表的信息一起查询出来呢?这就需要用到表联接. 和之前的UNION组合查询不同,UNION是将不同的表组合起来,也就是纵向联接,说白了就是竖着拼起来. ...
- SQL语句汇总(一)——数据库与表的操作以及创建约束
首先,非常感谢大家对上篇博文的支持,真是让本菜受宠若惊,同时对拖了这么久才出了此篇表示抱歉. 前言:此文旨在汇总从建立数据库到联接查询等绝大部分SQL语句.SQL语句虽不能说很多,但稍有时间不写就容易 ...
- 初级SQL开发汇总指南
汇总部分内容来自网络(作者 :zhtbs),比较基础的东西,能够了解比较基础的一些东西. Select语句概要 数据库中数据的提取(查询)使用select 语法,主要有以下几点作用 l 提取的数据 ...
- SQL语句汇总(终篇)—— 表联接与联接查询
既然是最后一篇那就不能只列出些干枯的标准语句,更何况表联接也是SQL中较难的部分,所以此次搭配题目来详细阐述表联接. 上一篇博文说到相关子查询效率低下,那我们怎么能将不同表的信息一起查询出来呢?这就需 ...
- SQL语句汇总(一)——数据库与表的操作以及创建约束
首先,非常感谢大家对上篇博文的支持,真是让本菜受宠若惊,同时对拖了这么久才出了此篇表示抱歉. 前言:此文旨在汇总从建立数据库到联接查询等绝大部分SQL语句.SQL语句虽不能说很多,但稍有时间不写就容易 ...
- SQL练习题汇总(Sqlserver和Mysql版本)
所需表及数据执行脚本: CREATE TABLE STUDENT (SNO ) NOT NULL, SNAME ) NOT NULL, SSEX ) NOT NULL, SBIRTHDAY DATET ...
- MS SQL 分类汇总参数 grouping(**)=1 rollup cubt
转:http://www.111cn.net/database/mssqlserver/43368.htm 本文章介绍了关于sql多级分类汇总实现方法及数据结构,有碰到问题的同学可参考一下. 据库结构 ...
- 基本Sql语句汇总
关于Sql语句的学习,选择的DBMS为SQL Server,Sql语句随着工作中的应用不断补充,不具备系统性,为个人笔记汇总,网上有很多优秀的资源,故不对每一处应用做过多细致的说明,后期会对部分篇幅较 ...
随机推荐
- 「DP」区间dp
区间dp? 状态设计为描述一段区间的dp. eg:f[i][j]表示从 i 到 j 这个区间上的最优值.
- CopyOnWrite 策略
CopyOnWrite 是用于解决并发读写的一种策略,在Write的时候对共享变量进行Copy,在副本上进行更新,再把更新好的副本原子性地替换原来的共享变量.写入时复制是一种优化策略,多个调用者同时访 ...
- EF Core的安装、EF Core与数据库结合
一.新建一个.net core的MVC项目 新建好项目后,不能像以前一样直接在新建项中添加ef, 需要用命令在添加ef的依赖 二.EF Cor ...
- 201621123016《Java程序设计》第1周学习总结
1. 本周学习总结 本周的学习内容:java的发展历史,java程序设计环境,java简单语法. java与c++一样是一门面向对象的程序设计语言(相比于c++它是一门更彻底的面向对象的程序设计语言) ...
- swift4.0 方法监听Selector写法总结
import UIKit class MainViewController: UITabBarController { //MARK:属性 懒加载 lazy var composeBtn = UIBu ...
- HDU2896【AC自动机-模板】
思路: 因为不同病毒特征码不会相同. AC自动机,然后对于每一个输出即可. 注意:以上字符串中字符都是ASCII码可见字符(不包括回车);G++ MLE. //#include <bits/st ...
- Android DPAD not enabled in AVD
问题描述:打开Android的仿真器,右侧的按键部分对于上下左右键出现以下现象后果是,这些按键都没法使用,由于我是测试一个小游戏,俄罗斯方块,朋友,要是少了上下左右键,让我情何以堪,而且我试过使用键盘 ...
- mysql 5.6 安装x64版本
从mysql下载的 32bit的 msi installer 后 , 安装的时候没有发现选择x64的地方, 最后安装完毕后发现server是32bit的,只能删除server( installer ...
- hdu1536(sg函数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1536 题意:首先输入K 表示一个集合的大小 之后输入集合 表示对于这对石子只能去这个集合中的元素的个 ...
- c#file类读写
private void button4_Click(object sender, EventArgs e) { FileStream fs = File.OpenRead(textBox1.Text ...