Oracle数据库-学习笔记
P2
步骤:
1.win + R打开dos窗口
2.输入:"sqlplus scott/tiger" 连接数据库
"show user":显示当前用户
conn 账户/口令:连接别的用户
select username,account_status from dba_users:查看用户状态
还可以指定用户名:select username,account_status from dba_users where username = 'SCOTT';
删除用户时,若级联删除不允许,可以先停止相关会话,然后再删除:
select * from v$session:查看sid号
alter system kill session '136,258';
再删除就可以了
column 列名 noprint; :不打印指定列名的列
注释:--
1."select *from 表名;" :查询语句
如:
"select *from tab; " :该语句可以查看系统中有哪些表
"select *from emp;" :当前用户自带一张表,emp表为员工表
"select *from dept;"
"set linesize xxx" :调整列宽度为xxx
"host cls" :清屏
dual:单行单列的自带表 如 select * from dual;
2."desc 表名;" :查看表的结构
如:
"desc emp;" :左为字段名,右为字段类型
"desc dept;"
emp和dept两张表通过 外键 和 主键 建立关联关系,如DEPTNO部门编号
方案:用户
scott:scott用户
select *from 表名;
也可以select empno,ename,job from emp; 这样查询部分信息
起别名:
select
empno as "编号",
ename "姓名",
job 月薪 注意:“job 月 薪”这种情况不可以,因为没有引号,计算机无法分辨具体别名有哪些
from emp;
三种都可以
如果在起别名时,遇到一些特殊符号,如:空格 等,需要用双引号括起来。例如以下:
job "月 薪" 或 job "from" 等等
若在查询操作输入语句时不小心输入错误:如将from输入成了form,可以按照以下方法修改:
输入:"c /form/from" 后直接回车,显示修改后的语句,如下:
"1* select * from emp",若修改符合想法,则输入 "/" 后回车,即可得到想要的操作,不必重复输入一大串
还可以输入 "ed" 后回车,进入文件修改后换行以 "/" 结尾,关闭文件后预览是否修改成功,成功则输入 "/" 输出
即,可以通过 c 或 ed 修改错误语句
列的计算:
对列进行加减乘除之后会自动出现一列。
基本概念:
实体:相当于java中的类
记录:相当于java中的对象,一行数据
字段:相当于java中的属性,列
表:同一个实体中,所有的记录、字段组合起来就是一张表
desc查询表的结构后:1.NUMBER(x):代表有x位数字;
NUMBER(x,y):代表有x位数字,其中有y位小数
2.VARCHAR2(x):代表长度为x的字符串,类似于java中的String类型
3.DATE:如雇佣时间,和java.sql.Date类似
4.BLOB:二进制
5.CLOB:大文本
SQL:
select 控制列
where 控制行
(where紧跟着select)
如:select empno,job,sal from emp where empno>=7500 and empno<=7900;
字符串/字符、日期:用单引号引起
大小写问题:
a.命令/关键字:不敏感(不区分)
b.数据:敏感(区分)
运算符:
操作运算符:+ - * / %
关系运算符:>、 >=、 <、 <=、 =、 !=或<>都是不等于
如果是null,必须用 is 、或 is not 。 如:select * from emp where comm is null;
逻辑运算符: or and not
或 且 非
如:select * from emp where not(mgr=7698 and job='CLERK');
where执行顺序:右->左
null:
判断 null 要用 is/is not (不能用=/!=)
null的计算:
任何数字 和null计算,结果都为null
需要对null进行处理:null->0
方法:1. nvl:相当于if
nvl(comm,0) 意思为如果comm为null,就将comm值置为0
如:select ename, nvl(comm,0) from emp;
2.nvl2:相当于if...else
nvl2(comm,x,0) 意思为如果comm值为null,就将comm值置为0,否则将comm值置为x
即if(comm==null) return 0;
else return x;
3.distinct:对查询出的结果集去重
如:select distinct deptno from emp
连接符: java中:"hello"+"world"->"helloworld"
oracle:concat 或 ||
如:1.select concat('hello','world') from dual;
2.select 'hello'||'world' from dual;
dual:oracle提供的学习时使用的临时表:单行单列
修改oracle默认的日期格式 通过查询 select * from v$nls_parameters;
默认格式:DD-MON-RR
修改:alter session set NLS_DATE_FORMAT = 'yyyy-mm-dd';
修改日期显示格式:例如:to_char(hire_date,'yyyy-mm-dd') = '1999-06-07'
范围查询:数字/日期(日期带引号)
between 小 and 大;
>= 小 and <=大
如:select * from emp where sal between 1500 and 3000;
select * from emp where hiredate between '20-2月 -81' and '08-9月 -81';
关键字in,表示在哪个范围里(只能取括号内的几个值)
select last_name,department_id,salary
from employees
--where department_id=90 or department_id=80 or department_id=70
where department_id in (90,80,70)
模糊查询:
like
配合通配符使用:_ :一个字符
% :任意个字符
若使用到转义字符,则需用escape声明:如:...where XXX like '%\_%' escape '\';
如:姓名中包含L的员工信息:select * from emp where ename like '%L%';
员工编号第二位为4的员工信息:select * from emp where empno like '_4%';
姓名长度>6的员工信息:select * from emp where ename like '______%'; (6个_)
修改内容:例如:
update employees
set last_name = 'XXXXXX'
where last_name = 'XXXXX'
排序:order by XXX desc/asc ,XXXX desc/asc..
(desc默认由大到小,asc默认由小到大)
如果仅写order by XXXX:也是默认由小到大
select last_name,department_id,commission_pct,salary
from employees
where department_id = 80
order by salary asc
单行函数:
1.字符函数:
大小写控制函数
LOWER(str)、
UPPER(str)、
INITCAP(str)(多个单词首字母大写),
字符控制函数
CONCAT(str,str)、
SUBSTR(str,index,length)、
LENGTH(str)、
INSTR(str,ch)(str中是否存在ch,返回下标,下标从0开始)、
LPAD(str,length,ch) | RPAD(str,length,ch)(分别为左右对齐,用length长度表示str,若str长度比length小,则分别在左右以ch补位)、
TRIM(ch FROM str)(删除str中首尾处的ch)、
REPLACE(str,chOld,chNew)(用chNew替代str中所有的chOld)
2.数字函数:
ROUND(num,index):四舍五入
TRUNC(num,index):截断
MOD(num,mod):求余
3.日期函数:
SYSDATE:返回日期和时间
MONTHS_BETWEEN(大,小):两个日期相差的月份数
ADD_MONTHS(date,addnum):向指定日期date中加上若干(addnum)月份
NEXT_DAY(date,str):指定日期date的下一个星期几(str)对应的日期(准确的说是从当前来看最近的星期几是多会儿)
LAST_DAY(date):本月的最后一天
ROUND(date,str):日期date按照str指定处四舍五入
TRUNC(date,str):日期date按照str指定处截断
extract (
{ year | month | day | hour | minute | second }
| { timezone_hour | timezone_minute }
| { timezone_region | timezone_abbr }
from { date_value | interval_value } )
4.转换函数:
隐式数据类型转换(Oracle自动完成下列类型转换):
VARCHAR2(字符串) or CHAR --> NUMBER、DATE
NUMBER、DATE --> VARCHAR2
显式数据类型转换:
TO_CHAR(要转化的数据,转换格式)
TO_DATE(要转化的数据,转换格式) yyyy表示年,mm表示月,dd表示天
TO_NUMBER(要转化的数据,转换格式)
注:将date型转化成char型数据时,如果要穿插一些字符时(如年、月、日等字符),需要用双引号引起
将number类型数据转换成char型数据时,格式占位符使用9表示时,最前面若位数不够不会补位;若占位符使用0表示时,若前面位数不够会使用0补位。.表示小数点,,表示千位符
当想要表示工资等数据时,若在格式中第一位用$表示美元符,若用L则表示当地货币符号
计算天数:
如:select to_date('08/06/2015','mm/dd/yyyy')-to_date('07/01/2015','mm/dd/yyyy') from dual;
计算月数:
months_between(date1,date2)可以查看两个日期间有多少个月
计算年数:(月数除以12)
select trunc(months_between(to_date('08/06/2015','mm/dd/yyyy'),to_date('08/06/2013','mm/dd/yyyy'))/12) from dual;
5.通用函数:
这些函数适用于任何数据类型,同时也适用于空值。
NVL(expr1,expr2)可以将空值转化成其他类型值。当expr1为空时,用expr2代替,否则用原值。如求员工年薪时,奖金率有可能为空
NVL2(expr1,expr2,expr3)当expr1不为null时,返回expr2;当expr1为null时,返回expr3。
NULLIF(expr1,expr2)相等返回NULL,不等返回expr1
COALES CE(expr1,expr2,......,exprn)如果第一个表达式为空,则返回下一个表达式,对其他的参数进行COALESCE
条件表达式:IF-THEN-ELSE
1.CASE:
CASE expr when xxxx then xxxx
when xxxx then xxxx
else xxxx end
2.DECODE:
decode(expr,xxxx(条件),xxxx(结果1),
xxxx(条件),xxxx(结果2),
(省略else) xxxx (省略end))
给查询结果加序号:
row_number() over (partition by col1 order by col2)
表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。
嵌套函数:
单行函数可以嵌套;
嵌套函数的执行顺序是由内到外
多表查询:
例:select last_name,e.department_id,department_name
from employees e,departments d
where e.department_id=d.department_id
注:若多表查询不设置条件的话会导致笛卡尔积(左面的每一个匹配右面的每一个,数量为乘积)
内连接(等值、非等值):只会显示左右都匹配的信息。
外连接(左、右):左外连接可以显示左面在右面没有匹配到的东西,在右面条件后加(+)
右外连接与左相反。
例:select last_name,e.department_id,department_name
from employees e,departments d
where e.department_id(+)=d.department_id
注:一个谓词只能连接一个外部连接的表。
一般情况下,要连接n个表需要用到n-1个条件。
cross join:也会发生笛卡尔积错误:
select last_name,e.department_id,department_name
from employees e cross join departments d
natural join:自然地将两表连接,并且将两边中所有相等的列(条件)都连接在一起。
select last_name,e.department_id,department_name
from employees e natural join departments d
from...join...using(...):通过using查询关联表中的指定列。(前提是关联的表中指定列的列名、数据类型都一样)
from...join...on......:与where相似。
若要再关联表,添加条件,则直接在之前语句后添加join...on...即可。
左外连接:from...left outer join...on......
右外连接:from...right outer join...on......
满外连接:from...full outer join...on......
例:select last_name,d.department_id,department_name--,city
from employees e full outer join departments d
on e.department_id=d.department_id
--join locations l
--on d.location_id=l.location_id
自连接:通过表自己的信息查询表自己的信息(自己连自己)。
如:查询某员工的老板是谁
组函数:
常用: AVG()
COUNT(expr):返回expr不为空的记录总数。
MAX()
MIN()
STDDEV():标准差
SUM()
AVG和SUM中只能存放NUMBER类型的数据。而MAX、MIN什么类型都可以存。
组合使用:COUNT(NVL(...,...))
COUNT(Distinct expr)
分组:group by:在select列表中所有未包含在组函数中的列都应该包含在group by子句中。相反,包含在group by子句中的列不必包含在select列表中。
否则,会出现非法使用组函数的概念。
非法使用组函数:
1.不能在where子句中使用组函数。
2.可以在having子句中使用组函数。
若想多层分组的话,在group by后直接写多个条件即可
例:select department_id,round(avg(salary),2)
from employees
group by department_id
若加过滤条件(where),where要跟from挨着。
组函数可以嵌套:如求平均工资的最大值:MAX(AVG(salary))
组函数处理多行返回一行、不计算空值、where子句不可以使用组函数进行过滤(用having替代)。
例题:查询1995-1998年每年雇佣的人数:
select count(*) "total",
count(decode(to_char(hire_date,'yyyy'),'1995',1,null)) "1995",
count(decode(to_char(hire_date,'yyyy'),'1996',1,null)) "1996",
count(decode(to_char(hire_date,'yyyy'),'1997',1,null)) "1997",
count(decode(to_char(hire_date,'yyyy'),'1998',1,null)) "1998"
from employees
where to_char(hire_date,'yyyy') in ('1995','1996','1997','1998')
子查询:
例:谁的工资比Abel的高?
select last_name,salary
from employees
where salary>(select salary
from employees
where last_name='Abel')
子查询要包含在括号内,通常写在比较条件的右侧。
子查询(内查询)在主查询之前一次执行完成;子查询的结果被主查询(外查询)使用。
单行操作对应单行子查询,多行操作对应多行子查询。
单行子查询的比较操作符:>、<、>=、<=、<>
多行子查询的比较操作符:in(等于列表中的任意一个)、any(和子查询返回的某一个值比较)、all(和子查询返回的所有值比较)
空值操作不会报错,只是显示为空。
例:查询平均工资最低的部门信息及其最低平均工资
select d.*,(select avg(salary) from employees where department_id=d.department_id)
from departments d
where department_id=(
select department_id
from employees
having avg(salary)=(
select min(avg(salary))
from employees
group by department_id
)
group by department_id
)
DDL用于定义数据库的结构,比如创建、修改或删除数据库对象,包括如下SQL语句:
CREATE TABLE:创建数据库表
ALTER TABLE:更改表结构、添加、删除、修改列长度
DROP TABLE:删除表
CREATE INDEX:在表上建立索引
DROP INDEX:删除索引
DDL操作直接提交保存,不可回滚。
select * from user_tables; 查询用户自己创建的表。或者还可以在My Objects的Tables中查看。
select * from user_catalog; 查询用户自己的数据库对象。
创建并管理表:
命名规则:
1.必须以字母开头
2.必须在1-30个字符之间
3.必须只能包含A-Z,a-z,0-9,_,$和#
4.必须不能和用户定义的其他对象重名
5.必须不能是Oracle的保留字
例:
建表:
方式1(白手起家):
create table emp1(
id number(10),
name varchar2(20),
salary number(10,2),
hire_date date
)
方式2:
create table emp2
as
select employee_id id,last_name name,hire_date,salary
from employees
还可以加过滤条件,如where 1=2,则新建表为空表,若不加过滤条件,则新表中存在的数据与指定表相同
修改表结构:
添加列:alter table emp1
add(email varchar2(20)) 新建列email
修改列:alter table emp1
modify(id number(15)) 修改已有列id
如果要修改的列不为空的话,是改不了的。
增加默认值:alter table emp1
modify(salary number(20,2) default 2000)
只对添加默认值之后的表的值产生影响。
删除列:alter table emp1
drop column email
重命名列:alter table emp1
rename column salary to sal
删除表:(删除数据同时删除表)
drop table emp3;
清空表:(清空数据)
truncate table emp3;
重命名表:rename oldName to newName
了解:在某表中将某列设置成不可用,之后删除:
alter table XXX
set unused column XXXX
alter table XXX
drop unused columns
comment on table 表 / column 字段 is:为表或字段添加注释
查询注释:
表级:select comments from user_tab_comments
where table_name='E_WANG';
字段:select comments from user_col_comments
where table_name='E_WANG'
注意:此处的条件中的表名一定要大写!
数据处理:
DML(数据操纵语言)可以实现向表中插入数据、修改现存数据、删除现存数据。
事务是由完成若干项工作的DML语句组成的。
向表中插入数据:
insert into 表名 values(...)或 insert into 表名 select ...from...
如: insert into emp1
values(1001,'zhangsan',sysdate,10000)
其中,日期可以由to_date函数插入。如果插入的对象有部分值不确定,可以用null填补。
若添加的顺序、值的个数与表的结构不同,则可以在表明名后指定添加哪些数据即可。
如:
insert into emp1(last_name,employee_id,hire_date)
values('wangwu',1003,to_date('2002-10-3','yyyy-mm-dd'))
还可以直接从其他表中拷贝数据,如:
insert into emp1(employee_id,hire_date,last_name,salary)
select employee_id,hire_date,last_name,salary
from employees
where department_id=80
创建脚本:
insert into emp1(employee_id,last_name,salary,hire_date)
values(&id,'&name',&salary,'&hire_date')
修改数据:
update 表名 set 列名 = 值 (where ...)
如: update emp1
set salary = 8000
where last_name='Johnson'
如果省略where的话,表中数据都将被更改。
例:将114号员工的job_id和salary修改的和205号员工一样。
update employee_01
set job_id=(
select job_id
from employee_01
where employee_id=205
),
salary=(
select salary
from employee_01
where employee_id=205
)
where employee_id=114
commit:提交。相当于word中的保存。
rollback:回滚。返回修改之前。commit后的数据不能再回滚。
删除表中数据:
delete from 表名
where ...
例:删除employee_01表中部门名称中含”Public“字符的部门id
delete from employee_01
where department_id = (
select department_id
from departments
where department_name like '%Public%'
)
注:修改和删除表中的信息时,会发生完整性错误。
如有连接关系的两个表,如果修改或删除了一个表中的内容,另一个表无法判断应该怎么办。
commit、rollback、savepoint。
当对表中数据进行操作后,如果rollback回滚,可以回到最后一次commit时的数据。
如果在操作过程中使用savepoint保存点,则可以在rollback时候指定返回的保存点或回滚到最后一次commit的地方。
返回保存点:rollback to savepoint XXX;
在对表中数据进行操作时,如果没有commit的话,其他用户无法操作该表;只有当前操作的用户commit以后,其他用户才能进行操作。
如scott用户正在操作表中的数据,而此时system用户要查看scott用户修改后的数据(select * from scott.employees for update;),只有当scott用户执行commit提交改变后,才可以访问。
当scott用户和system用户都commit后,表才被释放。
约束:constraint
约束是表级的强制规定。
有以下五种:
NOT NULL:非空约束(只能定义在列上)
UNIQUE:唯一。只能插入不同数据。都是空值时不违反约束(多个空值是可以的)。
PRIMARY KEY:主键。自然非空,值唯一。
FOREIGN KEY:外键。
references:可以与其他表的主键相联系:通过references 要联系的表(要联系的列)
on delete cascade(级联删除):当父表中的列被删除时,子表中相对应的列也被删除。
on delete set null(级联置空):子表中相应的列置空。
上面两个直接在constraint语句最后加就行。
CHECK:检查条件。如:check(salary>1500...)
建表时添加约束:
如:create table emp1(
id number(10) constraint emp1_id_nn not null,
name varchar2(20) not null,
salary number(10,2)
)
添加约束的语法:
使用ALTER TABLE语句:
添加或删除约束,但是不能修改约束
有效化(enable)或无效化(disable)约束
添加NOT NULL约束要使用MODIFY语句。
添加别的约束还是用add constraint
如:alter table emp3
modify(salary number(10,2) not null)
删除约束:
如:alter table emp3
drop constraint emp3_email_uk
查询约束:
select constraint_name,constraint_type,
search_condition
from user_constraints
where table_name='EMPLOYEES'
查询约束定义的列:
select constraint_name,column_name
from user_cons_columns
where table_name = 'EMPLOYEES';
视图:
视图是一种虚表。
视图建立在已有表的基础上,视图赖以建立的这些表称为基表
向视图提供数据内容的语句为select语句,可以将视图理解为存储起来的select语句
视图是向用户提供基表数据的另一种表现形式
使用视图的好处:
控制数据访问;简化查询;避免重复访问相同的数据
创建一个视图:
如:create view empview
as
select employee_id,last_name,salary
from employees
where department_id=80
修改视图:create or replace ...
如:create or replace view empview
as
select employee_id,last_name,salary,department_name
from employees e,departments d
where d.department_id=80
and e.department_id=d.department_id
只能查看,不能修改:with read only(直接加在创建视图语句的最后)
删除视图:drop view 视图名;
如:drop view empview2;
显示视图的结构:desc 视图名;
简单视图:没有用到分组函数;
复杂视图:用到了分组函数
在简单视图中执行DML操作:
当视图定义中包含以下元素之一时不能使用delete:
组函数
group by 子句
distinct 关键字
rownum 伪列
rowid:物理存在的序号
当视图定义中包含以下元素之一时不能使用update:
group by 子句
distinct 关键字
rownum 伪列 (只能从1开始)
列的定义为表达式
Top-N 分析查询一个列中最大或最小的n个值
最大或最小的值的集合是Top-N分析所关心的。
注意:对rownum只能使用 < 或 <= ,而用=,>,>=都将不能返回任何数据
如:select rn,employee_id,last_name,salary
from (
select rownum rn,employee_id,last_name,salary
from (
select employee_id,last_name,salary
from employees
order by salary desc
)
)
where rn>40 and rn<=50
rownum是一个伪列,在上例中,它与查询产生的表的主键(employee_id)有所关联,只有去除关联才能进行Top-N操作,
而把排好序的表作为新表进行查询就可以去掉rownum与原employee_id的关联,而与新的表产生关联
对oracle分页必须使用rownum“伪列”
序列:
序列:可供多个用户用来产生唯一数值的数据库对象
自动提供唯一的数值
共享对象
*主要用于提供主键值
将序列值装入内存可以提高访问效率
定义序列:
create sequence 序列名
[increment by n] --每次增长的数值
[start with n] --从哪个值开始
[{maxvalue n | nomaxvalue}]
[{minvalue n | nominvalue}]
[{cycle | nocycle}] --是否需要循环
[{cache n | nocache}]; --是否缓存登录
如:create sequence empseq
increment by 10
start with 10
maxvalue 100
cycle
nocache
创建了序列empseq
练习:可以运用序列给表的主键(如id)在添加时依次赋值
如创建新表emp01(employee_id id,last_name name,salary)以及序列empseq后,
添加数据可以运用empseq的nextval方法给id赋值:
如:insert into emp01
values(empseq.nextval,'zhaoliu',3500)
修改序列:
如:alter sequence empseq
increment by 1
nocycle
将序列值装入内存可提高访问效率;
序列在下列情况下出现裂缝:
回滚
系统异常
多个表同时使用同一序列
如果不将序列的值装入内存(nocache),可使用表 USER_SEQUENCES 查看序列当前的有效值。
如:select sequence_name,min_value,max_value,
increment_by,last_number
from user_sequences
删除序列:drop sequence 序列名
如:drop sequence empseq
在建表时可以在右括号后添加segment creation immediate,作用是一创建完表立即分配段空间,避免插入第一条记录时,序列对象跳过第一个值。
或者使用命令 alter system set deferred_segment_creation = flase;取消使用‘延迟段’技术。
索引:
创建索引:create index emp01_id_ix
on emp01(id)
删除索引:drop index 索引名
什么时候创建索引:
列中数据值分布范围很广
列经常在where子句或连接条件中出现
表经常被访问而且数据量很大,访问的数据大概占数据总量的2%到4%
同义词:synonym
创建(私有)同义词:create synonym XXX for XXX
删除同义词:drop synonym XXX
创建公有同义词:create public synonym XXX for XXX
替换同义词:create or replace synonym XXX for XXX
查看数据字典中的同义词信息可以使用dba权限查看数据字典中的dba_synonyms视图:
如:select * from dba_synonyms where owner = 'LIUF';
创建用户:create user XXX(用户名) identified by XXX(密码)
如:create user atguigu01
identified by atguigu
授予创建会话的权限:grant create session to XXX;
授予创建表的权限:grant create table to XXX;
分配表空间:alter user XXX quota unlimited(或相应空间限制,如5m) on 表空间(users);
以上操作需要由dba账户操作,普通账户无法更改
普通账户可以:
修改密码:alter user XXX identified by XXX(密码);
角色:
创建角色:
create role 角色名;
为角色赋予权限:
grant XXX XXX to 角色;
将角色赋予用户:
grant 角色 to 用户1,用户2...
对象(如表、视图等)
对象的拥有者可以自己决定把对象的部分操作权限赋予给哪些用户,也可以通过系统用户分配
grant 权限
on 对象
to 用户1,用户2...(或public)
with grant option:该用户也拥有分配权限的权力
当to后面跟的不是一个个用户名,而是public关键字,表示将关于该对象的该权限赋予所有用户
收回对象权限:revoke
使用with grant option子句所分配的权限同样被收回
revoke 权限
on 对象
from 用户...
Set操作符:
union(并集去重)/union All(并集不去重)
intersect(交集)
minus(差集)
如: select employee_id,department_id
from employees01
union
select employee_id,department_id
from employees02
当操作中上面的表的列数和下面的表的列数不相等时,会出现:“ORA-01789: 查询块具有不正确的结果列数”错误。
当操作中上面表的列的顺序和下面表的列的顺序不同时,会出现:“ORA-01790: 表达式必须具有与对应表达式相同的数据类型”错误。
可以给上面的表的操作的列起别名,该名会运用到结果中;但给下面的表起别名则不会生效
order by子句:只能在语句的最后出现
可以使用第一个查询中的列名,别名或相对位置。
如:select employee_id emp_id,department_id dept_id
from employees01
union
select employee_id,department_id
from employees02
order by 1 desc
当两张表中的列名和表达式在数量和数据类型上不对应,则需要在不对应的地方添加对应的空值
高级子查询:
1.多列子查询
如:
select employee_id,manager_id,department_id
from employees e1
where (manager_id,department_id) in (
select manager_id,department_id
from employees
where employee_id in(141,174)
)
and employee_id not in (141,174)
2.在from子句中使用子查询
select last_name,e1.department_id,salary,e2.avg_sal
from employees e1,(select department_id,avg(salary) avg_sal from employees e2 group by department_id) e2
where e1.department_id=e2.department_id
3.单列子查询表达式
select employee_id,last_name,
(case department_id when(select department_id from departments where location_id=1800) then 'Canada'
else 'USA' end) location
from employees
还可以在order by子句使用
4.相关子查询
主查询与子查询联系较大
select employee_id,last_name
from employees e
where 2<=(
select count(*)
from job_history
where employee_id=e.employee_id
)
5.exists操作符
6.not exists
1、plsql语句格式:
sqldeveloper 或plsqldeveloper中
[declare
--声明部分(变量,复杂的数据类型)
]
begin
sql语句
[exception
--异常处理]
end;
符号:
:= 赋值操作符
|| 连接操作符
-- 单行注释符
/* */ 多行注释符
<< >> 标签
.. 范围操作符
<>或!= 不等于
声明常量时,需要在数据类型前加 constant
属性数据类型:
%type :列类型,引用变量和数据库列的数据类型
%rowtype :行类型,提供表示表中一行的记录类型
异常:
自定义异常:声明数据类型为exception类型的数据
在要使用的地方 raise 该exception(注册异常)
在异常处理部分when 异常 then RAISE_APPLICATION_ERROR(错误号,错误信息)
记录类型:(类似于java的类)
语法:
定义中:type 记录名 is record(变量1 变量1类型,变量2 变量2类型,...变量n 变量n类型);
定义后创建该记录类型的对象(变量)
可以直接select .... into 记录对象
输出时可以调用:记录对象.变量
流程控制:
1.条件判断(两种)
方式一:if.....then......elsif.....then......else.....end if;
方式二:case......when.....then.......end;
2.循环结构(三种)
方式一:loop ... exit when ... end loop;
方式二:while ... loop ... end loop;
方式三:for 变量 in ... loop ... end loop;
3.goto、exit
例:
declare
v_i number:=2;
v_j number:=2;
v_flag number:=1;
begin
while v_i<=100 loop
while v_j<=sqrt(v_i) loop
if mod(v_i,v_j) = 0 then v_flag:=0;
end if;
v_j:=v_j+1;
end loop;
if v_flag=1 then dbms_output.put_line(v_i);
end if;
v_j:=2;
v_i:=v_i+1;
v_flag:=1;
end loop;
end;
例如:
1)基本结构和输出语句:
例子1
SQL> begin
2 dbms_output.put_line('Hello World!');
3 end;
4 /
Hello World!
PL/SQL procedure successfully completed
注:要显示输出语句时需要先打开输出功能:set serverout on
2)变量赋值
例1:
SQL> declare
2 out_text1 varchar2(20);
3 out_text2 varchar2(20);
4 begin
5 out_text1:='文本1';
6 out_text2:='文本2';
7 dbms_output.put_line(out_text1);
8 dbms_output.put_line(out_text2);
9 end;
10 /
文本1
文本2
PL/SQL procedure successfully completed
例2:
SQL> declare
2 v_name varchar2(10) default '张三丰';
3 begin
4 dbms_output.put_line(v_name);
5 end;
6 /
张三丰
PL/SQL procedure successfully completed
3)带提示信息的PL/SQL
例:
SQL> declare
2 num1 number;
3 num2 number;
4 res number;
5 begin
6 num1:=&num1;
7 num2:=&num2;
8 res:=num1/num2;
9 dbms_output.put_line(res);
10 exception
11 when others then
12 dbms_output.put_line('发生异常!');
13 end;
14 /
.5
PL/SQL procedure successfully completed
SQL> /
发生异常!
PL/SQL procedure successfully completed
当定义的变量中有字符类型的变量时,要赋值时需要加引号。
例子:
SQL> declare
2 id number(4);
3 name varchar2(10);
4 begin
5 id:=&学号;
6 name:='&姓名';
7 dbms_output.put_line('学号:'||id||',姓名:'||name);
8 end;
9 /
游标:(类似于java中的iterator)
游标属性:
%FOUND – SQL 语句影响了一行或多行时为 TRUE ---找到为true,执行
%NOTFOUND – SQL 语句没有影响任何行时为TRUE --- 与上面相反。
%ROWCOUNT – SQL 语句影响的行数,没有影响任何行,返回0,在执行任何DML语句前,值为NULL
%ISOPEN - 游标是否打开,隐式游标始终为FALSE(隐式游标执行时打开,结束时立即关闭)
注意:
a 游标属性都用于结束循环
b sql%rowcount用于记录修改的条数,就如你在sqlplus下执行delete from之后提示已删除xx行一样, 这个参数必须要在一个修改语句和commit之间放置,否则你就得不到正确的修改行数。
游标使用for循环可以自动开启、关闭游标,并且自动逐条读取信息。
例:
declare
v_name employees.ename%type;
cursor c_emp is select ename from employees;
begin
open c_emp;
loop
fetch c_emp into v_name;
exit when c_emp%NotFound;
dbms_output.put_line('员工姓名:'||v_name);
end loop;
close c_emp;
end;
declare
cursor c_emp is select empno,ename,salary from employees;
v_no employees.empno%type;
v_name employees.ename%type;
v_sal employees.salary%type;
begin
open c_emp;
dbms_output.put_line('------------员工信息------------');
loop
fetch c_emp into v_no,v_name,v_sal;
exit when c_emp%NotFound;
dbms_output.put_line('员工号:'||v_no||'员工姓名:'||v_name||'员工工资:'||v_sal);
end loop;
close c_emp;
end;
declare
cursor c_emp is select * from employees;
r_emp c_emp%ROWTYPE;
begin
open c_emp;
loop
fetch c_emp into r_emp;
exit when c_emp%NotFound;
dbms_output.put_line('工号:'||r_emp.empno||',姓名:'||r_emp.ename||',工资:'||r_emp.salary);
end loop;
close c_emp;
end;
declare
v_dno scott.employees.department_id%type;
cursor c_emp(dno number) is select * from scott.employees where department_id=dno;
r_emp c_emp%rowtype;
begin
v_dno:=&部门编号;
open c_emp(v_dno);
loop
fetch c_emp into r_emp;
exit when c_emp%NotFound;
if c_emp%Found then
dbms_output.put_line('工号:'||r_emp.employee_id||',姓名:'||r_emp.last_name||',工资:'||r_emp.salary);
else
dbms_output.put_line('该部门不存在!');
end if;
end loop;
close c_emp;
end;
异常:
预定义异常:系统自己定义好的异常
非预定义异常:
自己定义异常,然后与标准的oracle错误联系起来:
pragma exception_init(异常名,错误代码);
抛出异常:
raise 异常名;
在exception块进行处理。when 异常 then ... when others then ...
存储过程:(不返回数据)
procedure
格式:create or replace procedure 过程名 [参数] is .......
参数可以指定 in / out / in out
函数:(返回数据)
function
格式:create or replace function 函数名 [参数] return type is ......
参数可以指定 in / out / in out
只需要写类型,不用写位数
触发器:
trigger
在指定事件(insert、update、delete等)默认隐式触发
触发器组成:
触发事件
触发时间:before、after(触发事件和触发器的操作顺序)
触发器本身
触发频率:语句级(statement)、行级(row)
语句级:当某触发事件发生时,该触发器只触发一次
行级:当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
格式:
create [or replace] trigger 触发器名
{before | after}
{insert | delete | update [ of column[ , column ......] ]} on [schema] 表名
[for each row]
[when condition]
触发器体(内容)
当update触发时,可以使用 :new 和 :old 修饰符获取修改前后的数据
查看用户触发器信息:
select * from user_triggers;
启用/禁用触发器:
alter trigger XXX disable;
alter trigger XXX enable;
Oracle触发器 的三个谓语词 inserting\updating\deleting
例:
create or replace trigger delete_my_emp_trigger
before
delete on my_emp
for each row
begin
insert into my_emp_bak
values(:old.employee_id,:old.salary);
end;
create or replace trigger t_emp_bef
before
insert or delete or update on emp2
for each row
begin
if user<>'SCOTT' then
raise_application_error(-20001,'你无权修改emp2表!');
end if;
end;
create or replace trigger t_ope_his
before
insert or delete or update on emp2
for each row
begin
case
when inserting then
insert into ope_his
values(user,sysdate,'inserting');
when deleting then
insert into ope_his
values(user,sysdate,'deleting');
when updating then
insert into ope_his
values(user,sysdate,'updating');
end case;
end;
create table ope_his
(
username varchar2(10),
chg_date date,
operate varchar2(10)
)

浙公网安备 33010602011771号