第一章:sql数据操作和查询

– 1.语句命令组成:

 1. 数据定义语言(ddl),包括create(创建)命令、alter(修改)命令、drop(删除)命令等。     -- 主要针对对象的结构2. 数据操纵语言(dml),包括insert(插入)命令、update(更新)命令、delete(删除)命令等。  -- 主要针对表3. 数据查询语言(dql),包括基本查询语句、order by子句、group by子句等。4. 事务控制语言(tcl),包括commit(提交)命令、rollback(回滚)命令。5. 数据控制语言(dcl),grant(授权)命令、revoke(撤销)命令。

– 2.查询结构

   select *|列名|表达式 from 表名 where 条件 group by 列名 having 条件 order by 列名 [asc/desc]  -- * 表示所有的列名称; asc 升序(默认),desc 降序

– 3.查询顺序

   select     字段或表达式(多个字段用逗号隔开)                                       -- 5from       表(视图或者数据集)                                                     -- 1where      字段的限定(多个限定用or或者and隔开,后面不能跟聚合函数)                 -- 2group by   字段或表达式(多个字段用逗号隔开)                                       -- 3having     表达式(前面必须有group by,多个表达式用or或者and隔开)                    -- 4order by   字段或表达式(多个字段用逗号隔开,如col1 asc, col2 desc或者1 asc,2 desc) -- 6

– 虚拟表

select 10/2 from dual;
select 1 as 数字1, '1' as 字符1 from dual;-- select 中有*时候,并且还有其它字段或表达式,必需在*号前加表名.或表别名.
select sysdate as 当前日期,t.* from student_info t;  -- 列别名可以加as , 表的别名不能加as

– 4.聚合函数

聚合函数:聚合函数同时可以对多行数据进行操作,并返回一个结果。
聚合函数与group by 使用(字段需要分组,聚合函数必须要跟group by 联用)
注意:select 中除了聚合函数包裹的内容,其它字段必须包含于group by 后面的字段,select 只是选取聚合后的字段和值avg         平均值
sum      求和
min、max 最小值、最大值
count    统计个数-- 计算员工表的总体平均工资、总工资、总人数、工龄最大和最小的入职日期
select avg(sal) as 平均工资,sum(sal) as 总工资,count(empno) as 总人数,min(hiredate) as 最早入职日期,max(hiredate) as 最晚入职日期from emp;-- 每个部门的平均工资、总工资、总人数、工龄最大和最小的入职日期
select deptno,avg(sal) as 平均工资,sum(sal) as 总工资,count(empno) as 总人数,min(hiredate) as 最早入职日期,max(hiredate) as 最晚入职日期from empgroup by deptno; -- 按照部门编号和工作类型分组统计人数
select deptno,job,count(empno)from empgroup by deptno,job;-- count对列和对*的区别(count对列时,有空值的列不会计数)

select count(*), --15
count(1), --15
count(1000), --15
count(comm), --4 – 不计算空值
count(job), --15
count(distinct job) – 6 – 去重
from emp;

– 5.操作符

算术运算,关系运算,和逻辑运算(1)算术运算: +、-、*、/select e.*, (nvl(e.sal,0)+nvl(e.comm,0))*12 as 年薪 from emp e;(2)关系运算: =、!=、<>、>、>=、<、<=select * from emp where empno=7369;(3)逻辑运算: not>and>orselect (case when 1=1 or 1=3 and 1=2then 1else 2 end) as flagfrom dual;  -- 1

– 6.null操作(’’,null)

在查询条件中null值用is null作条件,非null值用 is not null做条件
空值的一些特性:
1、空值跟任何值进行算术运算,得到的结果都为空值
2、空值跟任何值进行关系运算,得到的结果都为不成立
3、空值不参与任何聚合运算
4、排序的时候,空值永远是最大的
-- 查询奖金为空
select * from emp where comm is null;
-- 1
select e.*, comm+100, sal + comm from emp e;
-- 2
select * from emp where comm<>0;
-- 3
select count(comm) from emp;
-- 4
select * from emp order by comm asc;

– 7.去重(distinct, group by, rowid)

-- 查看部门编号(去重)
 select distinct deptno from emp;select deptno from emp group by deptno;
-- distinct 只能出现在最前,不能一个字段去重一个字段不去重
select distinct job, deptno from emp;
select job, deptno from emp group by job, deptno;
-- 错误1
select job,distinct deptnofrom emp;
-- 错误2
select distinct job,distinct deptnofrom emp;

– 8.in 操作

查询出工作职责是'salesman'或者'president'或者'analyst'的员工信息。
     select ename,job from emp where job = 'salesman' or job = 'president' or job = 'analyst';select ename,job from emp where job in ('salesman','president','analyst');select ename,job from emp where job = any('salesman','president','analyst'); -- 不建议这种写法

– 9.between…and…(包含边界从小到大顺序)

查询列值包含在指定区间内的行,包含边界。
查询工资大于等于1500且小于等于2000的员工信息。
select *from empwhere sal >=1500 and sal <=2000;select *from empwhere sal between 1500 and 2000;查询工资在1500到2000之间的员工信息
select *from empwhere sal >1500 and sal <2000;-- 查询不到值
select *from empwhere sal between 2000 and 1500;

– 10.like模糊查询(对字符串)

字符匹配操作可以使用通配符'%'和'_':%:代表任意个字符。_:代表任意一个字符。
 select * from student_info where sname like '李_';select * from student_info where sname like '李_%';select * from student_info where sname like '李__';

– 11.集合运算

交集:intersect              -- 两者共有部分
并集(去重):  union
并集(不去重):union all
补集:minus                  -- 前者有后者无
当使用集合操作的时候,要注意:
1.查询所返回的列数以及列的类型必须匹配,列名可以不同。
2.只有union all不会去重。其他三个都需要排序后去重,性能比较差例题:
1.求员工表和部门表中的共有的部门编号(去重)
select deptnofrom emp
intersect
select deptnofrom dept;2.求员工表或者部门表中所包含的部门编号(不去重)
select deptnofrom empunion all
select deptnofrom dept;3.求员工表或者部门表中所包含的部门编号(去重)
select deptnofrom empunion
select deptnofrom dept;4.求部门表中不在员工表中的部门编号
select deptnofrom deptminus
select deptnofrom emp;
--
select deptno from emp
minus
select deptnofrom dept;

– 12.子查询

    子查询在select、update、delete语句内部可以出现select语句。1.单行子查询:不向外部返回结果,或者只返回一行结果。2.多行子查询:向外部返回零行、一行或者多行结果。-- 单行查询select * from emp where empno=7369;-- 多行查询select * from emp where deptno=10;-- 查询工资和7369相同的员工信息select * from emp where sal = (select sal from emp where empno=7369);     -- 单行结果"=",并且字段要对应-- 查询工资和10号部门员工工资相同的其它部门的员工信息select * from emp where sal in (select sal from emp where deptno = 10) and deptno <> 10;   -- 单行结果"in",并且字段要对应select * from emp where sal = any(select sal from emp where deptno = 10) and deptno <> 10; -- 单行结果"in",并且字段要对应-- 查询emp表中每个部门的最低工资的员工信息(尝试练习)select e.*from emp e, (select deptno, min(sal) as min_sal from emp group by deptno) a                           -- 子查询作为临时表关联where e.deptno = a.deptnoand e.sal = a.min_sal;select * from emp where (deptno,sal) in (select deptno, min(sal) as min_sal from emp group by deptno);  -- 可以多列对应-- 查询员工名称及其直接上级的名称select e1.empno 员工编号,e1.ename 员工名称,e1.mgr 上级员工编号,(select e.ename from emp e where e.empno = e1.mgr) as 上级员工名称 -- 子查询作为查询内容from emp e1;-- 更新所有员工工资和7369工资相同update emp set sal = (select sal from emp where empno=7369);-- 删除和7369相同工资的员工数据delete from emp where sal = (select sal from emp where empno=7369);

– 13.连接查询(重点)

包括内联接(inner join 1种)和外联接(outer join 3种)
(1)内连接(inner join):inner可省略内连接写法1(标准写法)select from 表名1join 表名2on 表名1.字段1=表名2.字段1and 表名1.字段2=表名2.字段2;内连接写法2(oracle写法)selectfrom 表名1,表名2where 表名1.字段1=表名2.字段1and 表名1.字段2=表名2.字段2;-- 查询员工信息及其部门信息select * from dept e join emp d              on e.deptno = d.deptno;-- oracleselect *from emp e, dept dwhere e.deptno=d.deptno;(2)左外连接(left outer join): outer可省略left join 跟表的前后顺序有关左外连接写法1(标准写法)selectfrom 表名1                     -- 主表    left join 表名2                -- 从表on 表名1.字段1=表名2.字段1and 表名1.字段2=表名2.字段2;左外连接写法2(oracle写法)selectfrom 表名1,表名2where 表名1.字段=表名2.字段(+);-- 查询部门名称为'sales'部门的信息及其对应的员工信息select *from dept d         left join emp e    on d.deptno=e.deptno;where d.dname='sales';   注意:  select *from dept d          left join emp e        on d.deptno=e.deptnoand d.dname='sales'; -- oracle  select *from dept d, emp ewhere d.deptno=e.deptno(+)and d.dname='sales'; (3)右外连接(right outer join): outer可省略
(4)全外连接(full outer join): outer可省略-- full joinselect e.*,d.*from emp efull join dept don e.deptno=d.deptno;-- 错的select e.*,d.*from emp e, dept dwhere e.deptno(+)=d.deptno(+);

第二章: 表操作和常用函数

创建表方式:
(1)语法结构:直接创建表create table 表名(列名1 数据类型 [,列名2 数据类型]...);数据类型:1.数字型   number        -- 默认最大为38位长度整数number(10)    -- 最大长度为10的整数number(8,2)   -- 整数最大长度为6位,小数长度为2位2.字符型   char          -- 默认1位长度的字符char(10)      -- 最大长度为10的字符,输入值不满10位,后面补空格varchar2(10)  -- 最大长度为10的字符,输入值不满10位,后面不会填充3.日期型   date          -- 后面不要加括号(可以到时分秒)timestamp-- 普通创建     create table t_course (cno number(10) default 0,  -- 给默认值cname varchar2(20),cdate date );(2)语法结构:根据结果集创建表create table 表名 as select 语句;        -- 间接创建create table t_emp_cp as select * from emp;            -- 拷贝表结构和数据create table t_emp_cp1 as select * from emp where 1=2; -- 拷贝表结构(3)表结构更改1.字段名称更改alter table t_course rename column cno to cno1;2.字段类型更改alter table t_course modify cno1 number(20);3.增加字段alter table t_course add cctv varchar2(10);4.删除字段alter table t_course drop column cctv;5.表名更改alter table t_course rename to t_course1216;6.删除表drop table t_course1216;(4)表数据更改-- insert intoinsert into t_course(cno,cname,cdate) values (1,'语文',sysdate);insert into t_course values (2,'数学',date'2019-11-15');insert into t_course(cname,cdate) values ('英语',to_date('2019-11-15','yyyy-mm-dd'));-- updateupdate t_course set cno=3 where cno=0;update t_course set cname='政治',cdate=date'2019-11-16' where cno=3;-- deletedelete from t_course where cno=3;  -- 逐行清除某些条件下的数据-- truncatetruncate table t_course;           -- 直接清空整张表-- 4.oracle单行函数
常用的单行函数有:

 数字函数:对数字进行计算,返回一个数字。
 日期函数:对日期和时间进行处理。
字符函数:对字符串操作。

(1)数字函数
abs(x) x绝对值 select abs(-2) from dual; – 2
mod(x,y) x除以y的余数 select mod(7,3) from dual; – 1
power(x,y) x的y次幂 select power(2,3) from dual; – 8
round(x[,y]) x在第y位四舍五入(默认四舍五入到整数) select round(2.989),round(2.989,2),round(5.989,-1) from dual; – 3, 2.99, 10
trunc(x[,y]) x在第y位截断(默认截断到整数) select trunc(2.989),trunc(2.989,2),trunc(5.989,-1) from dual; – 2, 2.98, 0
ceil(x) 向上取整 select ceil(2.13), ceil(2.00),ceil(-2.13) from dual; – 3, 2, -2
floor(x) 向下取整 select floor(2.89),floor(3.00),floor(-2.89) from dual; – 2, 3,-3

(2)日期函数
add_months(d,n),在某一个日期d上,加上指定的月数n,返回计算后的新日期。d表示日期,n表示要加的月数(n可以为负值)
select add_months(sysdate, 1),
add_months(date’2019-08-30’, -6),
add_months(date’2020-08-30’, -6)
from dual;

last_day(d),返回指定日期当月的最后一天
select last_day(sysdate),last_day(date'2019-08-30') from dual;-- trunc配合日期使用
trunc(d[,fmt])和round(d[,fmt])对日期处理:
trunc(d[,fmt]):
fmt: 'ddd'      截取到当月的当天(默认格式)
fmt: 'dd'       截取到当月的当天
fmt: 'd'        截取到当周的第一天
fmt: 'mm'       截取到当月的第一天
fmt: 'q'        截取到当季度的第一天
fmt: 'y'        截取到当年的第一天
select sysdate,trunc(sysdate),trunc(sysdate,'dd'),trunc(sysdate,'ddd'),trunc(sysdate,'d'),    -- 周日为本周第一天trunc(sysdate,'mm'),   -- 可以写成'month'trunc(sysdate,'q'),    trunc(sysdate,'y')     -- 可以写成'year'
from dual;

(3)字符函数
ascii(x) 返回字符x的ascii码。
concat(x,y) 连接字符串x和y。(|| 也可以连接字符串)
length(x) 返回x的长度。
lengthb(x) 返回x的字节长度
lower(x) x转换为小写。
upper(x) x转换为大写。
replace(x,old,new) 替换字符 – 在x中查找old,并替换为new。
-------------------
ltrim(x[,trim_str]) 左边截去字符 – 从x左边开始截去其中的trim_str字符串,直到不是为止,缺省则默认截去的为空格。
rtrim(x[,trim_str]) 右边截去字符 – 从x右边开始截去其中的trim_str字符串,直到不是为止,缺省则默认截去的为空格。
trim([trim_str from] x)
两边截去字符 – 从x两边开始截去其中的trim_str字符串,直到不是为止,缺省则默认截去的为空格。
instr(x, str[,start] [,n]) 定位字符位置 – 在x中查找str,可以指定从start位开始,第n次出现,省去的参数默认为1。
substr(x,start[,length]) 截取某段字符 – 在x中从start位开始,截取length个字符,缺省length,默认到结尾。

-- 示例
select ascii('a') from dual;   -- 65
--
select '0722' || 'bi' || '大数据' from dual;
select concat(concat('0722','bi'),'大数据') from dual;
select concat(concat('0722','bi'), (select '大数据' from dual)) from dual;
--
select lower('ab2'), upper('ab2'), replace('a2b3a','a','520') from dual;
select length('a ub好'), lengthb('中国平安'), lengthb('abcd') from dual;
--
select translate('a你好djl','ad','34') from dual;
select translate('a你好djl','adj','34') from dual;------------------
select ltrim(' a 1 '), rtrim(' a 1 '), trim(' a 1 ')from dual;  -- 默认截去空格select ltrim(' a 1 ', 'a'), rtrim('a 1', 'a')from dual;  -- 截去'a'(可以截去单个或多个字符)select trim('a' from 'a 1 ') from dual;  -- 只能截去单个字符
select trim('a1' from 'a 1 ') from dual; -- 报错--
select instr('0722bi大数据bi520', 'bi') from dual;       -- 从'0722bi大数据'的第1个字符开始查找'bi'第1次出现的位置(5)
select instr('0722bi大数据bi520', 'bi',6) from dual;     -- 从'0722bi大数据'的第6个字符开始查找'bi'第1次出现的位置(10)
select instr('0722bi大数据bi520', 'bi',5, 2) from dual;  -- 从'0722bi大数据'的第5个字符开始查找'bi'第2次出现的位置(10)
select instr('0722bi大数据bi520', 'bi',6, 2) from dual;  -- 从'0722bi大数据'的第6个字符开始查找'bi'第2次出现的位置(0)--
select substr('ra badf', 2) from dual;    -- 从第2个字符截取到最后一个字符
select substr('ra badf', 2, 3) from dual; -- 从第2个字符截取3个字符-- 5.转换函数
(1)to_char(d|n[,fmt])select 12, to_char(12),to_char(date'2019-07-08','yyyymmdd') from dual;-- fmt 格式select to_char(date'2019-08-30','yyyy'),   -- '2019'to_char(date'2019-08-30','yyyymm'), -- '201908'to_char(date'2019-08-30','ww'),     -- '35'  第35周to_char(date'2019-08-30','iw'),     -- '35'  第35周(自然周)to_char(date'2019-08-30','q'),      -- '3'   第3季度to_char(date'2019-08-30','mm'),     -- '08'to_char(date'2019-08-30','dd'),     -- '30'to_char(date'2019-08-30','d')       -- '6'   当周的第几天(星期天为第一天)from dual;-- 数字格式显示(后面格式长度要大于前面的值,如果不加fm或在前面填充空格)select to_char(243677865674,'fm999,999,999,999,990.00') from dual;(2)to_number(x[,fmt])x 里面必须全部为数字,如果有空格必须在最前或最后select to_number('1 2'),   -- 不行to_number(' 12'),   -- 可以 12to_number('12 '),   -- 可以 12to_number(' 12 '),  -- 可以 12to_number('12a')    -- 不行from dual;-- 日期不能直接转数字select to_number(date'2019-08-22') from dual;  -- 错误select to_number(to_date('20190822','yyyymmdd')) from dual;  -- 错误select to_number(to_char(date'2019-08-22','yyyymmdd')) from dual;(3)to_date(x [,fmt])select to_date('2019-07-08','yyyy-mm-dd'),to_date(20190708,'yyyy-mm-dd')from dual;注意:字符或数值中的年月日必须是日期范围内的值select to_date('2019-13-08','yyyy-mm-dd'),  -- 月份不对to_date(20190732,'yyyy-mm-dd')       -- 天数不对from dual;-- 转换格式前后对应      select to_date('2019-07-08','yyyymmdd'), -- 错误to_date(20190708,'yyyy-mm-dd')    -- 可以from dual; -- 6.空值转换函数
nvl (列,默认值)         如果列值为null,则使用默认值表示
nvl2(列,返回值1,返回值2)如果列值不为null,返回结果1;如果列值为null,返回结果2
--
select nvl(null,0),     -- 空转0nvl(null,100),   -- 空转100nvl('', 99),     -- 空字符转99nvl(10, 100),    -- 非空不会转nvl('ad',77)     -- 非空不会转from dual;
--
select nvl2(null, 0, 1),       -- 空转1nvl2('', 99, 2),        -- 空字符转2nvl2(10, 3, 100),       -- 非空转3nvl2('ad', 'ad', 7)     -- 非空转'ad'from dual;-- 7.条件转换函数(从前往后判断,满足前面条件,执行对应操作后退出)
decode(列|值,判断值1,返回值1,判断值2,返回值2,...,默认值)  -- 默认值可以给可以不给,不给的话,默认为空
case when 条件1 then 返回值1 [when 条件2 then 返回值2 ...] else 默认值 end
区别:decode    只能对单个字段进行等值判断case when 可以对多个字段进行任意条件判断
-- decode对值
select decode(12,         -- 原始值1, 2, 12, 10),    -- 10decode(12, 1, 2, 13, 10),    -- 空decode(12, 1, 2, 13, 10, 7),        -- 给定默认值7decode(12, 1, 2, 12, 10,     -- 找到后就返回值,然后退出,不会向下找12, 88,7)         -- 给定默认值7from dual;
-- decode对列(对emp表中的奖金为空的转换为100,不为空的转换为88)
select comm,decode(comm, null, 100, 88)from emp;练习:将部门名称进行如下更改并展示部门信息
accounting   会计部
research     研究部
sales        销售部
operations   操作部
select d.deptno,decode(dname,'accounting','会计部','research','研究部','sales','销售部','operations','操作部') as 部门,d.locfrom dept d;-- case when(对emp表中的奖金为空的转换为100,不为空的转换为88)
select comm,(case when comm is null then 100else 88end) as comm_1from emp;
-- 部门转换
select dept.*,(casewhen dname = 'accounting' then '会计部'when dname = 'research' then '研究部'when dname = 'sales' then '销售部'else '操作部'end) as 部门from dept;-- 8.exists 函数
exists(查询结果集):查询结果集有记录则成立,否则不成立
not exists(查询结果集):与exists相反
列出有员工的部门信息
select distinct d.dnamefrom dept djoin emp eon d.deptno=e.deptno;select d.*from dept dwhere deptno in (select deptno from emp);-- exists
select d.dnamefrom dept dwhere exists (select 1 from emp e where e.deptno=d.deptno);
-- 空值和无结果集的区别
select d.dnamefrom dept dwhere exists (select null from dual);-- 9.伪列
rowid  插入数据的时候生成,记录的是该行的物理地址(用作去重)
rownum 查询数据的时候生成,返回的是序号(用作分页)
select e.*, e.rowid, rownum  -- rownum是变化的值,不能指定到某个表from emp e;
select e.rowid,d.rowid,rownum, e.*,d.*from emp ejoin dept don e.deptno=d.deptno;
-- rownum 查询只能是小于或小于等于某个值(不能直接等于或者大于或者不是从1开始的某个区间段)
select e.*,rowid, rownumfrom emp ewhere rownum<=10;
抽取排在第7到第10行的数据
-- 1.补集
select e.*, rownumfrom emp ewhere rownum <= 10
minus
select e.*, rownumfrom emp ewhere rownum <= 6;
-- 2.子查询
select t.*from (select e.*, rownum as rn   -- 一定要有别名from emp ewhere rownum <= 10) twhere t.rn>=7;-- rowid
删除重复数据,相同数据只保留一条
delete from 表名 别名where rowid not in (select min(rowid) from 表名 别名 group by 列名);
-- 从员工表找出所有部门编号(字段值进行分组找该字段每一组的一个值)
select distinct deptnofrom emp;
select deptnofrom empgroup by deptno;
-- 每个部门的员工数据只保留一条(字段值进行分组保留每一组的一条完整信息)
delete from empwhere rowid not in (select min(rowid) from emp group by deptno);-- 10.临时表
创建oracle临时表,可以有两种类型的临时表:
会话级临时表(1.其它会话查询不到数据 2.本会话关掉后也查询不到数据)
事务级临时表(1.当进行事务提交或者事务回滚的时候,临时表中的数据将自行被截断 2.其它会话查询不到数据 3.本会话关掉后也查询不到数据)
1)会话级临时表
create global temporary table table_name

(col1 type1,col2 type2…) on commit preserve rows;

2)事务级临时表
create global temporary table table_name
(col1 type1,col2 type2...) on commit delete rows;举例:会话(每一个打开的窗口)
create global temporary table student_1
(stu_id number(5),class_id  number(5),stu_name varchar2(8),stu_memo varchar2(200)) on commit preserve rows ;
insert into student_1 values(1,2,'a','随便');
commit;
select * from student_1;举例:事务
create global temporary table t_pay_customer
(id number(5),
pay_mon varchar2(8)
) on commit delete rows;create global temporary table t_pay_merchant
(id number(5),
get_mon varchar2(8)
) on commit delete rows;insert into t_pay_customer values(1,100);
select * from t_pay_customer;
commit;
insert into t_pay_merchant values(1,100);-- 11.表的约束
按照约束用途分类:
1.primary key:主键约束 (非空、唯一)          -- 身份证号
2.foreign key:外键约束 (受外部表主键的约束)
3.check:      检查约束 (只能为空或约束的值)  -- 性别
4.unique:     唯一约束 (不重复、可多行为空)
5.not null:   非空约束 (不能为空)-- 建表时候给定约束(系统给定约束名称)
create table t_student_1 (
sno varchar2(18) primary key,                    -- 主键
cno varchar2(60) references t_course_1(cno),     -- 外键
score number(4,1) not null,
sex varchar2(200) check(sex='男' or sex='女'),
tel number(11) unique
);(1)primary key (主键只有一个, 但是可以对多个字段组合建立一个主键)
create table t_china_id (
id_no varchar2(18),
id_name varchar2(60),
birth_day date,
address varchar2(200),
tel number(11),
constraint pr_id_no primary key(id_no)
);
insert into t_china_id(id_no) values('1');
insert into t_china_id(id_no) values('1'); -- 重复值报错
insert into t_china_id(id_no) values('');  -- 空值报错
--
create table t_china_id_1 (
id_no varchar2(18),
id_name varchar2(60),
birth_day date,
address varchar2(200),
tel number(11),
constraint pr_id_name primary key(id_no,id_name)
);
insert into t_china_id_1(id_no) values('1');  -- 主键字段id_name为空报错
insert into t_china_id_1(id_no,id_name) values('1','a');
insert into t_china_id_1(id_no,id_name) values('1','b');

(2)foreign key (外部表要先建立主键,外键约束的字段值只能包含在外部表主键值中)
– 父项表
create table dept_1
(deptno number(2,0),
dname varchar2(14),
loc varchar2(13),
constraint pk_deptno_1 primary key (deptno)
);
– 子项表
create table emp_1(
empno number(4,0),
ename varchar2(10),
deptno number(2,0),
constraint pk_empno_1 primary key (empno),
constraint fk_deptno_1 foreign key (deptno) references dept_1(deptno)
);

insert into emp_1(empno,ename,deptno) values (1,'a',null);  -- 可以插入数据
insert into emp_1(empno,ename,deptno) values (2,'b',10);    -- 报错,外部表主键没有10的值
insert into dept_1(deptno,dname,loc) values (10,'aa','bb');
insert into emp_1(empno,ename,deptno) values (2,'b',10);    -- 可以插入数据
delete from dept_1 where deptno=10;                         -- 报错,字表已经引用外部表10号部门的值

(3)check
create table t_china_id_2 (
id_no varchar2(18) primary key,
id_name varchar2(60),
sex varchar2(4),
tel number(11),
constraint ck_sex check(sex=‘男’ or sex=‘女’)
);
insert into t_china_id_2(id_no,sex) values(‘1’,’’); – 可以为空
insert into t_china_id_2(id_no,sex) values(‘2’,‘未知’); – 不能为检查约束外的值
insert into t_china_id_2(id_no,sex) values(‘3’,‘男’);

(3)unique
create table t_china_id_3 (
id_no varchar2(18) primary key,
id_name varchar2(60),
sex varchar2(4),
tel number(11),
constraint uq_tel unique(tel)
);
insert into t_china_id_3(id_no,tel) values(‘1’,null); – 可以为空
insert into t_china_id_3(id_no,tel) values(‘2’,null); – 可以为空
insert into t_china_id_3(id_no,tel) values(‘3’,1);
insert into t_china_id_3(id_no,tel) values(‘4’,1); – 重复值报错

(4)not null

(5)约束组合使用(主键不能和唯一约束组合)
create table t_china_id_4 (
id_no varchar2(18) primary key check(length(id_no)=18),
id_name varchar2(60)
);
insert into t_china_id_4(id_no,id_name) values(‘1’,‘张三’); – 主键中的检查约束不满足18位, 报错
insert into t_china_id_4(id_no,id_name) values(‘123456789876543210’,‘张三’);

-- alter table命令添加约束
alter table 表名 add constraint 约束名 primary key(列名1[,列名2...])
alter table 主表名 add constraint 约束名 foreign key(列名1[,列名2...]) references 从表名(列名1[,列名2...])
alter table 表名 add constraint 约束名 check(条件)
alter table 表名 add constraint 约束名 unique(列名)
alter table 表名 modify 列名 not null
alter table 表名 drop constraint 约束名-- 有数据不满足约束的时候,不能创建约束
create table t_test_1 (
sno varchar2(10),
sname varchar2(20)
);
insert into t_test_1(sno, sname) values ('1','张三');
insert into t_test_1(sno, sname) values ('1','李四');
alter table t_test_1 add constraint pk_t_test_1_sno primary key (sno);   -- 报错-- 11.分析函数
它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值
语法格式:分析函数语法(<> 内的内容可以选择性省略)
function_name(<参数>,…) over (<partition by 表达式,…> <order by 表达式 <asc desc>> )
(1)、函数为聚合函数(avg,sum,count)情况下:
-- 按照每个部门的工资从低到高排序,计算每个部门的累计工资
select e.*,sum(sal) over (partition by deptno order by sal)from emp e;select e.*,sum(sal) over (partition by deptno order by sal,empno)from emp e;(2)、函数为排序函数(row_number(),rank(),dense_rank())情况下:①row_number: row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。 ②rank: rank函数返回一个唯一的值,当碰到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。③dense_rank: dense_rank函数返回一个唯一的值,当碰到相同数据时,此时所有相同数据的排名都是一样的。 同时会在最后一条相同记录和下一条不同记录的排名之间不空出排名。-- 按照员工部门分组, 给出工资从低到高的排名(排名不并列)
select e.*,row_number() over (partition by deptno order by sal)from emp e;

(3)、函数为位移函数(lead(列,参数), lag(列,参数)
select e.*,
lag(e.sal,1) over(order by e.sal) as 工资下移一位,
lead(e.sal,1) over(order by e.sal) as 工资上移一位
from emp e;

-- 12.行列转换

(1)行转列
有一张表s,记录了某公司每个季度的销售额,如下
y q amt
2015 1 100
2015 2 110
2015 3 130
2015 4 100
2016 1 200
2016 2 150
2016 3 100
2016 4 300

y      q1   q2   q3   q4
2015   100  110  130  100
2016   200  150  100  300

with t as (select deptno as 部门, count(empno) as 人数 from emp group by deptno)
select
max(decode(部门,10,人数)) as “10号部门”,
max(decode(部门,20,人数)) as “20号部门”,
max(decode(部门,30,人数)) as “30号部门”,
max(decode(部门,50,人数)) as “50号部门”
from t;

select y,max(case when q=1 then amt end) as q1,max(case when q=2 then amt end) as q2,max(case when q=3 then amt end) as q3,max(case when q=4 then amt end) as q4from t_y_q_amt tgroup by y;(2)列转行
/*
-- 将原表拆分4个季度的值,给上季度的标识,然后合并
y      q1      q_flag
2015   100     1
2016   200     1y      q2      q_flag
2015   110     2
2016   150     2y      q3      q_flag
2015   130     3
2016   100     3y      q4      q_flag
2015   100     4
2016   300     4
*/select y, 1 as q, q1 as amtfrom t_y_q_amt_1 t1
union all
select y, 2 as q, q2 as amtfrom t_y_q_amt_1 t1
union all
select y, 3 as q, q3 as amtfrom t_y_q_amt_1 t1
union all
select y, 4 as q, q4 as amtfrom t_y_q_amt_1 t1;

第4章 表空间、数据库对象
1.表空间
(1)系统表空间 system
(2)临时表空间 temp
(3)用户表空间 users
(4)undo表空间 undotbs1
(5)样例表空间 example
(6)系统副本空间 sysaux

2.同义词

 私有同义词:拥有create synonym权限的用户(包括非管理员用户)即可创建私有同义词,创建的私有同义词只能由当前用户使用。
 公有同义词:系统管理员可以创建公有同义词,公有同义词可以被所有用户访问。
创建同义词
create [or replace] [public] synonym [schema.]synonym_name
for [schema.]object_name

-- sys 用户
create or replace public synonym emp_copy for scott.emp;-- scott用户
select * from  emp_copy;3.序列
序列(sequence)是用来生成连续的整数数据的对象。
创建序列
create sequence sequence_name
[start with num]             -- 从某一个整数开始,升序默认值是1,降序默认值是-1
[increment by increment]     -- 增长数
[maxvalue num|nomaxvalue]    -- 最大值
[minvalue num|nominvalue]    -- 最小值
[cycle|nocycle]              -- 表示如果升序达到最大值后,从最小值重新开始;如果是降序序列,达到最小值后,从最大值重新开始
[cache num|nocache]          -- 预先在内存中生成序列号/不预先在内存中生成序列号
-- 最简单创建
create sequence s_1;序列使用
--访问下一个值(初始创建后要先定义)
select s_1.nextval from dual;
--访问当前值
select s_1.currval from dual; -- 生成序列号
create sequence s_2
start with 2
minvalue 1
maxvalue 10
increment by 2
cycle
cache 2序列修改和删除
--序列修改
alter sequence s_1
maxvalue 10000
minvalue -300
--删除序列
drop sequence s_1; 4.视图
视图(view)实际上是一张或者多张表上的预定义查询,这些表称为基表。
从视图中查询信息与从表中查询信息的方法完全相同。只需要简单的select…from即可。
创建视图
create [or replace] [{force|noforce}] view view_name
as
select查询
[with read only] 视图
--创建视图
create or replace view v_emp_dept
as
select e.empno, e.ename, e.job, e.hiredate, e.deptno, d.dnamefrom emp ejoin dept don e.deptno = d.deptno
with read only-- 更改基础表
delete from emp where empno<>7369--通过视图查询
select * from v_emp_dept;5、索引
前提:表数据量比较大的时候,查询比较慢
1.如果表中的某些字段经常被查询或者表之间的关联,以及作为查询的条件出现时,就应该考虑为该列创建索引。
2.有一条基本的准则是:当任何单个查询要检索的行少于或者等于整个表行数的10%时,索引就非常有用。
(1)索引种类
唯一索引
1、何时创建:当某列任意两行的值都不相同
2、当建立primary key(主键)或者unique constraint(唯一约束)时,唯一索引将被自动建立组合索引
1、何时创建:当两个或多个列经常一起出现在where条件中时,则在这些列上同时创建
2、组合索引中列的顺序是任意的,也无需相邻。但是建议将最频繁访问的列放在列表的最前面基于函数的索引
1、何时创建:在where条件语句中包含函数或者表达式时
2、函数包括:算数表达式、pl/sql函数、程序包函数、sql函数、用户自定义函数。/*
位图索引
反向键索引
键压缩索引
索引组织表(iot)
分区索引
*/创建索引
create [unique] index index_name on table_name(column_name[,column_name…])
-- 唯一索引
create unique index u_inx_emp_bak_empno on emp_bak(empno);
-- 组合索引(字段顺序有关)
create index inx_emp_bak_deptno_job on emp_bak(deptno,job);
-- 基于函数的索引
create index inx_emp_bak_ename on emp_bak(substr(ename,-1,1));索引失效
1.隐士转换
select * from emp_bak where empno = '7934';
-- 改 select * from emp_bak where empno = 7934;
2.字段引用函数
select * from emp_bak where to_char(empno) = '7934';
3.null 值判断
select * from emp_bak where empno is not null;
-- 改select * from emp_bak where empno>0 or empno<=0;
4.索引列进行运算
select * from emp_bak where empno + 10 = 7944;
-- 改select * from emp_bak where empno = 7944 -10;
select * from emp_bak where empno <> 7944;
-- 改select * from emp_bak where empno > 7944union allselect * from emp_bak where empno < 7944;
5.like首字母未知(末尾字母知道)
select * from emp_bak where ename like '%s';
-- 改select * from emp_bak where substr(ename,-1,1) ='s';
6.组合索引(字段顺序有关)
select * from emp_bak where deptno=10;
select * from emp_bak where deptno=10 and job='salesman';
select * from emp_bak where job='salesman';               -- 索引失效6.表分区
前提:表数据量比较大的时候,查询比较慢
优点:1.提高查询效率 2.增强可用性 3.维护方便(只对某些有问题分区数据维护,不用对整张表维护)
缺点:2.分区表需要维护(维护创建的分区)
表分区的几种类型及操作方法
1.范围分区:range
2.列表分区:list
3.散列(哈希)分区:hash
4.组合分区范围分区:
按入职日期进行范围分区
create table myemp
(empno  number(4)  primary key,ename varchar2(10),hiredate date,deptno number(7)
)
partition  by  range (hiredate)
(partition  part1 values  less  than (to_date('1981-1-1','yyyy/mm/dd')), --①partition  part2 values  less  than (to_date('1982-1-1','yyyy/mm/dd')),partition  part3 values  less  than (to_date('1983-1-1','yyyy/mm/dd')), partition  part4 values  less  than (to_date('1988-1-1','yyyy/mm/dd')), partition  part5 values  less  than (maxvalue)                          --默认最大
);-- select * from user_tab_partitions where table_name='myemp'; 查看分区表情况insert into myemp(empno,ename,hiredate,deptno)values(1,'张三',date'1980-1-1',10);insert into myemp(empno,ename,hiredate,deptno)values(2,'李四',date'1981-10-02',20);       insert into myemp(empno,ename,hiredate,deptno)values(3,'王五',date'1982-11-03',30);         insert into myemp(empno,ename,hiredate,deptno)values(4,'李蕾',date'1983-07-08',40);  insert into myemp(empno,ename,hiredate,deptno)values(5,'李华',date'1987-09-09',40);       insert into myemp(empno,ename,hiredate,deptno)values(6,'赵四',date'1989-11-03',50);        -- 查看分区数据
select * from myemp partition(part5);列表分区:
该分区的特点是某列的值比较少并且不会经常变动,基于这样的特点我们可以采用列表分区。
按deptno进行list分区
create table myemp2
(empno  number(4)  primary key,ename varchar2(10),hiredate date,deptno number(7)
)
partition by list (deptno)
(partition myemp_deptno_10  values (10) ,partition myemp_deptno_20  values (20) ,partition myemp_deptno_30  values (30) , partition myemp_deptno_40  values (40)
);-- select * from user_tab_partitions where table_name='myemp2'; 查看分区表情况insert into myemp2(empno,ename,hiredate,deptno)values(1,'张三',date'1980-1-1',10);insert into myemp2(empno,ename,hiredate,deptno)values(2,'李四',date'1981-10-02',20);       insert into myemp2(empno,ename,hiredate,deptno)values(3,'王五',date'1982-11-03',30);         insert into myemp2(empno,ename,hiredate,deptno)values(4,'李蕾',date'1983-07-08',40);  insert into myemp2(empno,ename,hiredate,deptno)values(5,'李华',date'1987-09-09',40);       insert into myemp2(empno,ename,hiredate,deptno)values(6,'赵四',date'1989-11-03',50);  -- 没给分区数据无法插入散列分区/hash 分区:组合分区:
这种分区是基于两种分区的组合,分区之中的分区被称为子分区。
按入职日期进行范围分区,再按deptno进行list子分区
create table myemp4
(empno  number(4)  primary key,ename varchar2(10),hiredate date,deptno number(7,2)
)
partition by range(hiredate) subpartition by list(deptno)
(partition p1 values less than(to_date('1981-01-01','yyyy-mm-dd'))(subpartition p1a values (10),subpartition p1b values (20),subpartition p1c values (30),subpartition p1d values (40)),partition p2 values less than (to_date('1982-01-01','yyyy-mm-dd'))(subpartition p2a values (10),subpartition p2b values (20),subpartition p2c values (30),subpartition p2d values (40)),partition p3 values less than (to_date('1983-01-01','yyyy-mm-dd'))(subpartition p3a values (10),subpartition p3b values (20),subpartition p3c values (30),subpartition p3d values (40)),partition p4 values less than (to_date('1988-01-01','yyyy-mm-dd'))(subpartition p4a values (10),subpartition p4b values (20),subpartition p4c values (30),subpartition p4d values (40)),partition p5 values less  than (maxvalue)(subpartition p5a values (10) ,subpartition p5b values (20),subpartition p5c values (30),subpartition p5d values (40))
);
-- select * from user_tab_partitions where table_name='myemp4'; 查看分区表情况1)查看分区数据(列表分区为例)
select * from myemp2 partition(myemp_deptno_40);
1)添加分区(原有的分区表没有给定默认分区的前提)
alter table myemp2 add partition myemp_deptno_50 values (50);
2)删除分区
alter table myemp2 drop partition myemp_deptno_50;
注意:如果删除的分区是表中唯一的分区,那么此分区将不能被删除,要想删除此分区,必须删除表。
3)重命名表分区
以下代码将p21更改为p2
alter table myemp2 rename partition myemp_deptno_50 to myemp_deptno_60; 总结:
1.非分区表, 不能直接改为分区表
2.创建了分区表, 给了默认分区, 不能添加其它分区
3.建完的分区表, 数据插入只能是当前分区所能包含的数据7.增量更新数据语法格式:merge(不是所有数据库都通用)merge into 目标表using (增量)on (匹配字段)when matched then update set   --update和set之间不需要加表名when not matched then insert values--insert和values之间不需要加into 表名create table dept_bak as select * from dept where deptno in (10,20);select * from dept_bak for update;  -- 修改loc的值merge into dept_bak dusing (select deptno,dname,loc from dept) ton (d.deptno=t.deptno)when matched then update set-- d.deptno=t.deptno,  一定不能更新关联上的字段d.dname=t.dname,d.loc=t.locwhen not matched then insert (d.deptno,d.dname,d.loc)values (t.deptno,t.dname,t.loc);select * from dept;select * from dept_bak;merge的灵活应用:若数据量大时,merge删除比delete好。merge into emp eusing (select * from emp where deptno = 10) son (s.empno = e.empno)when matched thenupdate set e.comm = e.comm delete where 1 = 1;   --set随便改,后面接delete8.insert all-- 多条插入create table t1(product_id number, product_name varchar2(80),p_month number);insert into t1 values(111, '苹果',1);insert into t1 values(222, '橘子',1);insert into t1 values(333, '香蕉',1);commit;create table t2 as select * from t1 where 1=2;insert allinto t2 values (product_id, product_name,p_month)into t2 values (product_id, product_name,p_month+1)into t2 values (product_id, product_name,p_month+2)into t2 values (product_id, product_name,p_month+3) select product_id, product_name, p_monthfrom t1;commit;select * from t2 order by product_id, product_name, p_month;-- 多表插入(分表--大表按照类别插入数据到小表)create table apple_orders as select * from t1 where 1=2;create table orange_orders as select * from t1 where 1=2;create table banana_orders as select * from t1 where 1=2;insert allwhen product_id = 111 theninto apple_orderswhen product_id = 222 theninto orange_orderselseinto banana_ordersselect product_id, product_name, p_month from t1;commit;select * from apple_orders;select * from orange_orders;select * from banana_orders;

第5章 pl/sql程序设计
1.pl/sql介绍
2.pl/sql基础
语法结构:pl/sql块的语法
[declare – 声明部分
–declaration statements]① – 声明变量、常量、游标等(声明的内容可以不在执行部分使用)
begin – 执行部分
–executable statements ② – 对于执行部分不能去定义变量等(使用的变量、常量、游标等必须在声明的内容中)
[exception – 异常处理
–exception statements] ③
end; – 分号不能省略

    注意: 每一个命令语句结束后面必须加分号特殊符号::= 赋值     v_cnt := 6;  对变量赋值为6.. 连续值   1..6         表示1到6的整数** 求幂     3**2         3的2次方为9-- 1begindbms_output.put_line('0701bi课程!');end;-- 2declarev_sql varchar2(100);beginv_sql :='0701bi课程!';dbms_output.put_line(v_sql);end;-- 3declarev_1 number;v_2 number;beginv_1 := 10;v_2 := 0;dbms_output.put_line(v_1/v_2);exception when zero_divide thendbms_output.put_line('分母为0');end;2.1声明与赋值声明变量必须指明变量的数据类型,也可以声明变量时对变量初始化,变量声明必须在声明部分。变量名 数据类型[ :=初始值]代码演示:声明变量declaresname varchar2(20) :='jerry';  sno number := 520; cname varchar2(10);begincname := 'bi';dbms_output.put_line(sname||sno||cname);   --  默认是以字符串打印,字符串连接的方式连接多个变量end;2.2 声明常量常量在声明时赋予初值,并且在运行时不允许重新赋值。使用 constant 关键字声明常量。declarepi constant number := 3.14;r    number default 3;area number; beginpi := 3;                    -- 报错,常量不可重新赋值-- r  :=4;                  -- 变量默认值可以更改area := pi * r * r;        dbms_output.put_line(area); end;2.3 隐式游标赋值对变量赋值还可以使用select…into 语句从数据库中查询数据对变量进行赋值。但是查询的结果只能是一行记录,不能是零行或者多行记录。例题1:打印出emp中员工编号为7369的姓名和工资。  declarev_ename varchar2(20);v_sal number(10,2);beginselect ename,salinto v_ename,v_sal          -- 隐式游标赋值from emp where empno=7369;dbms_output.put_line('员工名称:'||v_ename||' 员工工资:'||v_sal);    -- 不能直接打印表,只能是单行字段拼接后的字符串形式打印end;注意:使用select…into语句对变量赋值,要求查询的结果必须是一行,不能是多行或者没有记录。2.4 声明属性数据类型%type:   引用数据库中的某列的数据类型或某个变量的数据类型。%rowtype:引用数据库中的一行(所有字段)作为数据类型。例题1:打印出emp中员工编号为7369的姓名和工资。-- typedeclare v_ename emp.ename%type;v_sal   emp.sal%type;beginselect ename,salinto v_ename,v_salfrom empwhere empno=7369;dbms_output.put_line(v_ename||'--'||v_sal);end;   -- rowtypedeclare v_emp emp%rowtype;                  -- emp的表头一致:字段名和类型beginselect ename,salinto v_emp.ename,v_emp.sal        -- 注意插入变量表对应的字段中from empwhere empno=7369;dbms_output.put_line(v_emp.ename||'--'||v_emp.sal);  -- 打印也只能是字段拼接end;-- 不建议如下写法declare v_emp emp%rowtype;beginselect *into v_empfrom empwhere empno=7369;dbms_output.put_line(v_emp.ename||'--'||v_emp.sal);end;3.条件控制3.1 if 语句-- if-thenif 条件 then--条件结构体end if;declare v_num1 number:= 10;v_num2 number:= 30;beginif v_num1>=v_num2 thendbms_output.put_line(v_num1 ||'>=' ||v_num2);end if;end;-- if-then-elseif 条件 then--条件成立结构体else--条件不成立结构体end if;declare v_num1 number:= 10;v_num2 number:= 30;beginif v_num1>=v_num2 thendbms_output.put_line(v_num1 ||'>=' ||v_num2);elsedbms_output.put_line(v_num1 ||'<' ||v_num2); end if;end;-- if-then-elsifif 条件1 then--条件1成立结构体elsif 条件2 then--条件2成立结构体else--以上条件都不成立结构体end if;beginif  1=2 then dbms_output.put_line('1=2');     -- 每个 then 面的语句结束都要加分号 elsif 1=3 then dbms_output.put_line('1=3');elsif 1=4 then dbms_output.put_line('1=4');  else                               dbms_output.put_line('1=1');  end if;                             -- if 语句结束用 end ifend;3.2 case 语句casewhen 表达式1 then 语句序列1;when 表达式2 then 语句序列2;when 表达式3 then 语句序列3;……else 语句序列n;end case;begincasewhen 1 = 2 thendbms_output.put_line('1=2');      -- 每个 then 面的语句结束都要加分号when 1 = 3 thendbms_output.put_line('1=3');when 1 = 4 thendbms_output.put_line('1=4');else                                -- 可以没有此分支但是以上语句中必须有一个条件为真,如果有此分支一定不要加条件判断dbms_output.put_line('1=1');end case;                             -- case 语句结束用 end caseend;4.循环控制    pl/sql提供了丰富的循环结构来重复执行一些列语句。oracle提供的循环类型有:1.无条件循环loop-end loop语句2.while循环语句3.for循环语句在上面的三类循环中exit用来强制结束循环。-- loop循环loop--循环体end loop;语法格式:1.循环体在loop和end loop之间,在每个loop循环体中,首先执行循环体中的语句序列,执行完后再重新开始执行。2.在loop循环中可以使用exit或者[exit when 条件]的形式终止循环。否则该循环就是死循环。例题1:打印1到100数字(换行) declare v_num number :=0;beginloopv_num := v_num + 1;           -- 自增dbms_output.put_line(v_num);   exit when v_num>=100;         -- 退出条件end loop;end;-- while循环(先判断条件,条件成立再执行循环体)while 条件 loop--循环体end loop;declarev_num number :=1;beginwhile v_num<=100 loopdbms_output.put_line(v_num);v_num := v_num + 1;           -- 自增end loop;end;-- for循环for 循环变量 in [reverse] 循环下限..循环上限 loop--循环体end loop;for循环需要预先确定的循环次数,可通过给循环变量指定下限和上限来确定循环运行的次数,然后循环变量在每次循环中递增(或者递减)beginfor v_num in 1..100 loop        --  可以不声明变量,数字只能从小到大dbms_output.put_line(v_num);end loop;end;5.游标游标的类型有两种:隐式游标和显示游标。pl/sql会为所有的sql数据操作声明一个隐式的游标,包括只返回一条记录的查询操作。显示游标四个步骤:1.声明2.打开游标3.逐行获取数据4.关闭游标语法结构:声明游标cursor 游标名[(参数1 数据类型[,参数2 数据类型...])]is select 语句;  --游标的声明语法结构:执行游标open 游标名[(实际参数1[,实际参数2...])];  --打开游标fetch 游标名 into 变量名1[,变量名2...];或fetch 游标名 into 记录变量;  --提取数据close 游标名;  --关闭游标(千万别忘了!)游标属性:%found、%notfound%found:用于判断游标是否从结果集中提取数据。如果提取到数据,则返回值为true,否则返回值为false。%notfound:该属性与%found相反,如果提取到数据则返回值为false;如果没有,则返回值为trun。declarecursor c_emp isselect ename,sal from emp where deptno=10;v_emp c_emp%rowtype;beginopen c_emp;loop fetch c_emp into v_emp;exit when c_emp%notfound;dbms_output.put_line(v_emp.ename||'--'||v_emp.sal);end loop;close c_emp;end;     --for循环declarecursor c_emp isselect ename,salfrom empwhere deptno=10; beginfor v_emp in c_emp loopdbms_output.put_line('姓名: ' || v_emp.ename || '工资: ' || v_emp.sal);end loop;end;    -- 游标参数例题1:打印某个部门的员工姓名和工资declarecursor c_emp(p_deptno emp.deptno%type) is   -- 游标参数select ename,salfrom emp where deptno=p_deptno;beginfor v_emp in c_emp(&部门号) loop    -- 键盘输入变量值(键盘输入值时,字符型要加单引号)/打开游标的时候传入dbms_output.put_line('姓名: ' || v_emp.ename || '工资: ' || v_emp.sal);end loop;end;7.pl/sql 中的dml和ddl语言-- dmlcreate table emp_01 as select * from emp;begindelete from emp_01 where deptno=10;update emp_01 set sal=8888 where deptno=20;insert into emp_01(empno,deptno) values(1111,40);commit;end;select * from emp_01;-- ddlbegin-- create table emp_02 as select * from emp;  -- ddl不能直接在pl/sql块中使用-- truncate table emp_01;   -- alter table emp_01 add ct date;drop table emp_01;end;8.动态sql   在pl/sql程序开发中,可以使用dml语句和事务控制语句,但是还有很多语句(比如ddl语句)不能直接在pl/sql中执行。这些语句可以使用动态sql来实现。语法格式:动态sqlexecute immediate 动态语句字符串[into 变量列表][using 参数列表]-- beginexecute immediate 'create table yyy as select * from emp';    -- 字符串语句最后不要加分号;end;或者declarev_sql varchar2(100) :='create table yyy as select * from emp';  beginexecute immediate v_sql;end;-- 用参数传入declarev_empno  emp.empno%type := &输入员工编号;v_deptno emp.deptno%type := &输入部门编号;v_sal    emp.sal%type;beginexecute immediate 'select sal from emp where empno = :1 and deptno= :2'    -- :1和:2为参数名,用后面using的值替换into v_sal                 -- 查询的结果写入变量using v_empno, v_deptno;    -- 替换动态sql中的参数:1和:2dbms_output.put_line(v_sal);end;-- 关于 dbms_output.put 和 dbms_output.put_linebegindbms_output.put('0710');    -- 不换行(后面必须有dbms_output.put_line,才能打印)dbms_output.put_line('bi');dbms_output.put_line('hahaha');end;-- begindbms_output.put('0710');dbms_output.put('bi'); dbms_output.put_line('');end;-- 双重循环beginfor x in 1..3 loopfor y in 4..6 loopdbms_output.put_line(x||'*'||y||'='||x*y); end loop;end loop;end;  9.创建存储过程语法格式:创建存储过程create [or replace] procedure 过程名(参数1 [in|out|in out] 数据类型,参数2 [in|out|in out] 数据类型……)is|aspl/sql过程体;三种参数:传入(in或省去),传出(out),传入或传出(in out)注意: 1.数据类型不要带长度也不用括号 varchar2/number/date2.如果存储过程不带参数,过程名后不用括号,is|as 后可以直接跟声明内容,不要declare3.为in的参数,不能在过程中被赋值,只能作为调用传入值4.省去参数类型则默认为in传入5.in out 参数必需在声明时候赋初值,调用中用变量名语法格式:调用存储过程begin过程名[(参数)];end;-- 1.不带参数     例题1:打印emp表中所有雇员的姓名,工作和薪水。create or replace procedure sp_emp_deptno_1iscursor c_emp_deptno isselect ename, job, sal from emp;  beginfor v_emp_deptno in c_emp_deptno loopdbms_output.put_line('姓名:' || v_emp_deptno.ename ||'工作:' || v_emp_deptno.job || '工资:' || v_emp_deptno.sal);end loop;end;-- 调用beginsp_emp_deptno_1;end;-- 2.只带传入参数例题2:接收一个部门号,显示该部门的所有雇员的姓名,工作和薪水。create or replace procedure sp_emp_info (p_deptno in emp.deptno%type)is-- 游标cursor c_emp isselect ename,job,sal from emp where deptno=p_deptno;beginfor v_emp in c_emp loopdbms_output.put_line('部门:'||p_deptno||' 姓名:'|| v_emp.ename ||' 工作:' || v_emp.job || ' 薪水:' || v_emp.sal);end loop;end;-- 调用beginsp_emp_info(10);-- sp_emp_info(&部门编号);end;或者    declarev_deptno emp.deptno%type :=10;beginsp_emp_info (v_deptno);end;或者 beginsp_emp_info(p_deptno => 10);  -- 参数定向调用(多个参数可以改变顺序)end;-- 3.带传入和传出参数例题3:查询某个部门中的某个职位员工的姓名、工资、入职日期。(只考虑单行情况)create or replace procedure sp_myemp(p_deptno    in  number,p_hiredate  out date,p_sal       out number,p_job_ename in out varchar2)is                                   beginselect e.ename, e.sal, e.hiredateinto p_job_ename, p_sal, p_hiredate from emp ewhere e.deptno = p_deptnoand e.job = p_job_ename;dbms_output.put_line(p_job_ename || ' ' || p_sal || ' ' || p_hiredate);exception   -- 异常处理开始when too_many_rows thendbms_output.put_line('select into 返回多行值!');when no_data_found thendbms_output.put_line('select into 没有返回值!');end;--调用存储过程declarev_hiredate date;                                -- out 参数v_sal number;                                   -- out 参数v_job_ename varchar2(100) :='manager';          -- in out 参数此处先声明并赋值beginsp_myemp(10, v_hiredate, v_sal, v_job_ename);   -- 存储过程参数要对应(个数和类型)end;11.自定义函数语法格式:创建函数create [or replace] function 函数名(参数1 数据类型,参数2,[in|out|in out] 数据类型……)return 返回的数据类型   -- 不带数据类型长度is|aspl/sql函数体;           -- 里面必须要有一个return子句-- 不带参数情况create or replace function fun_testreturn number    -- 函数的返回类型isbeginreturn 100;end;select fun_test from dual;-- 传入两个参数,返回最大值create or replace function fun_max (p_num1 in number, p_num2 in number)return number    -- 函数的返回类型isbeginif p_num1>p_num2 then return p_num1;  else return p_num2; end if;end;调用:select fun_max(12,20) from dual;select fun_max(12,20) from emp;  -- 每行返回一个值或者begindbms_output.put_line(fun_max(12,20));end;或者declarev_num number;beginv_num := fun_max(12,20);dbms_output.put_line(v_num);end;12.创建包包就是把相关的存储过程、函数、变量、常量和游标等pl/sql程序组合在一起,并赋予一定的管理功能的程序块。一个程序包由两部分组成:包定义和包体。其中包定义部分声明包内数据类型、变量、常量、游标、子程序和函数等元素,这些元素为包的共有元素。包主体则定义了包定义部分的具体实现。注意:包声明的对象不一定要在包体中去使用,但是包体中的对象一定要在包声明中定义并保持一致。语法格式:创建包头create [or replace] package 包名is|as变量、常量及数据类型定义;游标定义头部;函数、过程的定义和参数列表以及返回类型;end [包名];语法格式:创建包体create [or replace] package body 包名is|asprocedure 过程名(参数)is|asbegin过程体;end [过程名];function 函数名(参数) return 类型is|asbegin函数体;end [函数名];end;例题1:创建一个包, 包中含有存储过程和函数create or replace package pk_mypackageisa number;                                  -- 声明变量(声明的对象不一定要在包体中使用)procedure my_sp(p_empno in number);        -- 声明存储过程function my_fun(p_num1 in number , p_num2 in number) return number; -- 声明函数end;create or replace package body pk_mypackageis-- 通过员工号找员工姓名和工资存储过程procedure my_sp(p_empno in number)    -- 和包中的声明要对应(并且一定要先声明)isv_ename emp.ename%type;v_sal   emp.sal%type;beginselect ename, sal into v_ename, v_sal from emp where empno=p_empno;dbms_output.put_line('姓名:'|| v_ename ||'工资:'|| v_sal);exception when no_data_found thendbms_output.put_line('select into语句中没有返回任何记录!'); when too_many_rows then dbms_output.put_line('select into语句中返回多于1条记录!');end;-- 比较大小函数function my_fun(p_num1 in number , p_num2 in number)return numberisbegin if p_num1>p_num2 then return p_num1;else return p_num2; end if;end;end;-- 用户下面的表select * from user_tables;-- 用户下面的过程体select * from user_procedures where object_type ='package'  ;select * from user_procedures where object_type ='function' ;select * from user_procedures where object_type ='procedure';-- 调用存储过程beginpk_mypackage.my_sp(&员工编号);end;-- 调用函数select pk_mypackage.my_fun(10,20) from dual;13.异常处理  语法格式:异常处理begin--可执行部分exception   -- 异常处理开始when 异常名1 then--对应异常处理;when 异常名2 then--对应异常处理;……when others then--其他异常处理;end;------- declarev_enmae emp.ename%type; beginselect enameinto v_enmaefrom empwhere deptno=10;   -- 'dfad' 其它错误dbms_output.put_line('返回单行值');       exception   -- 异常处理开始when too_many_rows thendbms_output.put_line('select into 返回多行值!');when no_data_found thendbms_output.put_line('select into 没有返回值!');when others thendbms_output.put_line('其它错误!');end;13.触发器简介触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行。触发器可以分为: 语句级触发器和行级触发器。具体举例:1、 在一个表中定义的语句级的触发器,当这个表被删除时,程序就会自动执行触发器里面定义的操作过程。这个就是删除表的操作就是触发器执行的条件了。2、 在一个表中定义了行级的触发器,那当这个表中一行数据发生变化的时候,比如删除了一行记录,那触发器也会被自动执行了。--触发器语法语法:create [or replace] trigger trigger_name{before | after} trigger_eventon table_name[for each row][when trigger_condition]trigger_body语法解释:trigger_name:触发器名称before | after : 指定触发器是在触发事件发生之前触发或者发生之后触发trigger_event:触发事件,在dml触发器中主要为insert、update、delete等table_name:表名,表示发生触发器作用的对象for each row:指定创建的是行级触发器,若没有该子句则创建的是语句级触发器when trigger_condition:添加的触发条件trigger_body:触发体,是标准的pl/sql语句块例题1:create table student_123   --创建student表(id_no     number(19),    --id_nostu_no    varchar2(20),  --学号stu_name  varchar2(32),  --姓名stu_age   number,        --年龄stu_major varchar2(32)   --专业);create table stu_log_123     --创建stu_log表,用于记录对student表的操作日志(log_id     number,         --日志idlog_action varchar2(100),  --操作名称log_date   date,           --操作时间log_message   varchar2(32) --日志信息);行级触发器(after触发器)创建触发器:将对student_123表的操作都记录到stu_log_123表中(of 用于指定一个或多个字段,指定字段被更新时才会触发触发器)create or replace trigger modify_stu_123after insert or delete or update of stu_name  -- 字段on student_123                                -- 表for each row  -- 行级触发begin if inserting theninsert into stu_log_123 values(1,'insert',sysdate,:new.stu_name);elsif deleting theninsert into stu_log_123 values(2,'delete',sysdate,:old.stu_name);elsif updating theninsert into stu_log_123 values(3,'update_old',sysdate,:old.stu_name);insert into stu_log_123  values(4,'update_new',sysdate,:new.stu_name);end if;end;insert into student_123 values(1,'no2','李四',21,'数学系');  --插入一条数据delete student_123 where stu_name='张三';                    --删除一条数据update student_123 set stu_age=19 where stu_name='李四';     --修改李四的年龄update student_123 set stu_name='王二' where stu_name='李四';--修改李四的名称select * from student_123;select * from stu_log_123;语句级触发器(before触发器):用来控制对表的修改create or replace trigger modify_stu_123_tablebefore insert or update or delete on student_123beginif deleting thenraise_application_error(-20001,'该表不允许删除数据');elsif updating thenraise_application_error(-20002,'该表不允许修改数据');elsif inserting thenraise_application_error(-20003,'该表不允许插入数据');end if;end;delete from student_123;drop table student_123;14.dbms_job该过程用于建立一个新的作业,当建立作业的时候,需要通过设置相应的参数来告诉oracle要执行的内容,要执行的时间,要执行任务的间隔。如下格式:dbms_job.submit(job out binary_interger,                          -- 用于指定作业编号what in varchar2,                                 -- 用于指定作业要执行的操作next_date in date default sysdate,                -- 用于指定该操作的下一次运行的日期interval in varchar2 default 'null',              -- 用于指定该操作的时间间隔no_parse in boolean default false,                -- 用于指定是否需要解析与作业相关的过程instance in binary_integer default any_instance,  -- 用于指定哪个例程可以运行作业?force in boolean default false                    -- 用于指定是否强制运行与作业相关的例程);-- 举例create table testjob(id number constraint testjob_id_pk primary key,name varchar2(30),ct_dt date);--如果序列存在就删除,然后创建一个序列create sequence testjob_id_seq;--创建一个序列,每一次向表中插入一条数据,并且表中的id字段值使用序列指定create or replace procedure insert_job isbegininsert into testjobvalues(testjob_id_seq.nextval, 'test' || testjob_id_seq.currval,sysdate);commit;end;declarejobno binary_integer;begin--提交,操作的时间间隔设置为1分钟dbms_job.submit(jobno,'insert_job();',sysdate,'sysdate+1/(24*60*6)');--打印序列号dbms_output.put_line('jobno='||jobno);--运行dbms_job.run(jobno);end;-- 删除begindbms_job.remove(jobno);  -- jobno为具体数字end; plsql-->>oraclenavicat for mysql-->>mysqlpgadmin4-->>postgresqlmysql:int/double  char/varchar  date/timestapmysql----oraclelimit 10----rownum <=10mysql和oracle的可能不同的地方,记得回去查询:常规查询语句,子查询,分组聚合,表关联,建表语句,`id` bigint(20) not null auto_increment comment '主键',primary key (`id`),myisam和innodb 简单总结https://blog.csdn.net/sjmz30071360/article/details/80822085  https://www.cnblogs.com/yjd_hycf_space/p/7772722.html   https://www.cnblogs.com/muchen/p/5310732.html

alias ll=‘ls -l’
pwd – 查看当前路径
ls -l – 查看当前目录下的所有文件和文件夹
mkdir 文件夹名 – 创建文件夹
touch 文件名 – 创建文件夹
vi 文件名 – 编辑文件 (先输入i,编辑完后按esc,再按shift+zz)
cat 文件名
more 文件名
rz – 上传文件
sz 文件名 – 下载文件
cd 文件夹名 – 进入某个文件夹目录
cd … 返回上一级目录
rm 文件名 – 删除文件

https://www.cnblogs.com/charisna/p/4673866.html
范式建模,维度建模(3种模型),实体建模

执行计划:

database link:
create public database link db_orcl
connect to scott identified by “123456” – 数字密码"123456"
using ‘192.168.0.222:1521/orcl’; – 需要连接的数据ip/端口/数据库名
– 查询
select * from emp@db_orcl;
– 删除
drop public database link db_orcl; – 删除database link
select * from emp@db_orcl;

HiveQL的基础操作全集相关推荐

  1. python基础教程视频(全13集)-Python基础视频教程全集

    原标题:Python基础视频教程全集 Python编程语言的定位是"优雅"."明确"."简单",所以对于Python初学者来说,学起来没有那 ...

  2. python基础教程视频-Python基础视频教程全集

    原标题:Python基础视频教程全集 Python编程语言的定位是"优雅"."明确"."简单",所以对于Python初学者来说,学起来没有那 ...

  3. 01、Cadence使用记录之新建工程与基础操作(原理图绘制:OrCAD Capture CIS)

    01.Cadence使用记录之新建工程与基础操作(原理图绘制:OrCAD Capture CIS) 硕士学电磁场去了,写点博客记录下学习过程. 参考的教程是B站的视频:allegro软件入门视频教程全 ...

  4. python教程视频大全_Python基础视频教程全集

    原标题:Python基础视频教程全集 Python编程语言的定位是"优雅"."明确"."简单",所以对于Python初学者来说,学起来没有那 ...

  5. 提交表单自动刷新_Web自动化测试:元素的基础操作和浏览器基础操作

    上一节,我们了解了如何定位元素,其实也有涉及对于元素的操作,这一节我们就详细的介绍一下对于元素的操作和对于浏览器的一些操作 一.对于元素的基础操作: clear():清除输入框内的文本 send_ke ...

  6. 【opencv】(1) 基础操作:图像视频读取、图像截取、颜色通道

    主要内容有:图像及视频的读取和保存.图像显示.转换灰度图.图像截取.颜色通道提取和组合 那我们开始吧. 1. 图像操作 首先我们导入opencv库,彩色图像一般都是由RGB(红绿蓝)三颜色通道构成,灰 ...

  7. JavaのFile类基础操作之问题

    在上一章节,介绍了File类的基础操作,比如文件的创建,文件的删除等等.这一章节,将介绍在File类基础操作中遇到的问题. 1.路径分割符问题 在实际的软件开发与运行过程中,往往都会在Windows环 ...

  8. 计算机应用基础统考操作,全国统考计算机应用基础操作题

    全国统考计算机应用基础操作题 (16页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.9 积分 .1.打开考生文件夹下的文件Word6.doc,完成 ...

  9. Docker 之 Docker基础操作

    第1章 Docker基础操作 1.1 常用的命令 0) 安装Docker 环境 yum -y install docker 1)   指定 IP,DNS 网络位启动Docker容器 a)  docke ...

最新文章

  1. 微信可能会颠覆快递的运营模式
  2. 如何在Github打造你的爆款开源项目
  3. tensorflow中sess.run第一个参数衣服不能随便穿
  4. 《Head First设计模式》第七章-适配器模式、外观模式
  5. 12.13记录//QQDemo示例程序源代码
  6. laravel-admin 在列表页添加自定义按钮
  7. 将字符串转换为全角或半角
  8. 设计模式第四篇-工厂模式
  9. mybatis中获取当前时间_mybatis 在xml文件中获取当前时间的sql
  10. 网站微信扫码登录回调不跳转问题
  11. ORAN C平面 Section Type 1
  12. mac命令行更新gradle
  13. 人工智能全局概览:通用智能的当前困境和未来可能
  14. 【C/C++】【面经】2022 网易互娱面经( 游戏客户端方向 )(更新:一面;二面;)
  15. 应届生想做产品经理该怎么走?
  16. WinRAR压缩软件去除广告
  17. RecyclerView之利用ItemDecoration实现万能分割线
  18. 字节跳动 Go RPC 框架 KiteX 性能优化实践
  19. java文件打包jar文件_把java文件打包成.jar (jar命令详解)
  20. C语言视频教程-谭浩强版-小甲鱼主讲—P13

热门文章

  1. 锤子android 7,锤子新机坚果Pro配置放出:骁龙626处理器、Android 7.1.1系统
  2. 注意力CBMA到底在网络中做了什么事
  3. 医学影像开源数据集汇总
  4. Linux LVM全面实践
  5. 我看朴灵评注阮一峰的《JavaScript 运行机制详解:再谈Event Loop》
  6. Tikhonov正则化方法在测绘领域的综述
  7. Quoted-printable1(BUCTF在线评测)
  8. hazelcast java_Hazelcast
  9. yii 高级版后台清理前台的缓存
  10. css-图片闪烁效果