1.字符串指定列宽:column 列名 format a号;
例如:column ENAME format a10;
2.数字指定列宽:column 列名 format 9999;
说明:一个9代表一个数字。
1 2的缩写格式:
col 列名 for 指令;
=====================================================================
例如我添加的内容如下:
-- 指定行宽
set linesize 150
-- 指定每页显示条数
set pagesize 100
-- 指定oracle默认显示时间
alter session set nls_date_format=‘yyyy-MM-dd‘;
=====================================================================
//取消重复行关键字:(distinct)
select distinct 重复字段 from 表名;
注意:如果查询多列,distinct作用于多列,多列有重复才算重复。
//拼接字符串 --查询格式:ENAME的工资是:SAL
select ename || ‘的工资是:‘ || sal from emp;
//拼接字符串((oncat)函数
select concat(‘我叫 ‘,‘小童鞋_成er‘) from dual;
拼接多个:select concat(concat(‘我叫 ‘,‘小童鞋_成er‘),‘ 啊!‘) from dual;
//oracle的虚表,oracle查询必须指定form关键字
select ‘Hello ‘ || ‘World‘ from dual;
dual是一个虚拟表:
比如 得到当前时间:select sysdate from dual;
计算数值: select 3 + 2 from dual;
//关于(like)查询特殊字符用法:
ID NAME
-- ----------
1 dd%
2 %xx
1、我们进行查询,select * from 表名 where 字段 like ‘%%‘; 那么就是查询所有了。
//定义转移字符:select * from 表名 where 字段 like ‘\%%‘ escape ‘\‘; --把\%转义,escpae指定哪个是转义符。
比如:select * from 表名 where 字段 like ‘x%%‘ escape ‘x‘; //把x转义
2、查询第三个字母为I的:
select * from 表名 where 字段 like ‘__I‘;
//查询~到~范围(between)
比如查询工资1500~6000之间的。
select * from 表名 where (工资字段 between 1500 and 6000);
//查询id为1 2 3 4的用户 (in查询)
第一种写法:select * from 表名 where ID字段 = 1 or ID字段 = 2 or ID字段 = 3 or ID字段 = 4;
批处理写法:select * from 表名 where ID字段 in(1,2,3,4);
注意:
select * from 表名 where 字段 in(xx,xx,null); //没有影响
select * from 表名 where 字段 not in(xx,xx,null); //如果not in 含有null,则不返回任何结果。
//查询Oracle指定的格式(v$nls_parameters)
select * from v$nls_parameters; //只能查看,不能修改
//修改当前会话的格式 默认时间格式:DD-MON-YY
alter session set nls_date_format=‘yyyy-MM-dd‘; //只对当前会话有效
//排序 (order by)
升序:
select * from 表名 order by 要排序字段 asc; //asc默认也可不写,从高到底
降序:
select * from 表名 order by 要排序字段 desc; //降序,从低到高
NULL值排序始终在下面:
select * from 表名 order by 含有NULL字段 desc nulls last;
NULL值排序始终在上面:
select * from 表名 order by 含有NULL字段 desc nulls first;
select * from 表名 order by nvl(含有NULL字段,-1) asc;
根据字段位置排序:
select id,name from xx order by 2 desc; //2是name的位置
//分组
分组函数:
max(字段); //最大值
min(字段); //最小值
avg(字段); //平均值
count(字段); //总条数
sum(字段); //总和
分组方法(group by):
select max(sal),deptno from emp group by deptno; //查询每个部门工资最高的人,如果group by中没有这个字段,就不能显示这个字段
对两个字段进行排序:
select max(sal),deptno,job from emp group by deptno,job; //根据“部门(deptno)”和“工作(job)”进行排序。
对分组条件进行筛选(group by 字段 having 条件),同时进行排序(order by):
select deptno,count(*) from emp group by deptno having count(*)>4 order by deptno desc;
注意:
group by 和 having 都不可以使用“别名”;
order by 可以使用“别名”;
某些情况下,优先使用where,而不使用having。
例子,查询“部门”,“部门人数”,取消10号部门信息:
效率高:select deptno,count(*) from emp where deptno <> 10 group by deptno;
效率低:select deptno,count(*) from emp group by deptno having deptno <> 10;
//字符函数
LOWER(String) //将字段转换为“小写”;
select LOWER(‘ABC‘) from dual; -- 结果:abc
UPPER(String) //将字段转换为“大写”;
select LOWER(‘abc‘) from dual; -- 结果:ABC
INITCAP(String) //每个单词首字母转为“大写”;\
select INITCAP(‘hello word.day‘) from dual; -- 结果:Hello Word.Day
-- 首写字母为大写
select initcap(ename) from emp;
//拼接字符串
CONCAT(‘a‘,‘b‘); //跟||一样
//截取函数:
SUBSTR(String,index,index) //要截取的字符串,从第几个开始,此位置往后截取几个 (从1下标开始)
select SUBSTR(‘abc‘,1,2) from dual; -- 结果:ab
USBSTR(String,index) //如果不指定,就从1位置,截取到字符串结束
select SUBSTR(‘abc‘,2) from dual; -- 结果:bc
//字段长度
LENGTH(String) //返回字段长度
select LENGTH(‘abc‘) from dual; -- 结果:3
//查找字符串位置
INSTR(String,String) //返回字符串位置下标
select INSTR(‘abcdefg‘,‘c‘) from dual; -- 结果:3
//补齐函数LPAD(String,indexOf,char)和RPAD(String,indexOf,char)
LPAD:
select lpad(‘abc‘,5,‘*‘) from dual; -- 结果:**abc
RPAD:
select rpad(‘abc‘,5,‘*‘) from dual; -- 结果:abc**
//可以匿名,比如:
select ename as 姓名,substr(ename,1,1)|| replace(rpad(‘ ‘,length(ename)-1,‘*‘),‘ ‘,‘‘) ||substr(ename,length(ename)) as 匿名 from emp where ename = ‘SCOTT‘;
姓名 匿名
---------------
SCOTT S***T
//去掉前后空格TRIM(‘ ‘ from String)
TRIM(String) //去掉前后空格
TRIM(‘a‘ from ‘abc‘) //去掉a,注意:只能为前、后替换
//替换函数replace(String,String,String)
select * from replace(‘abc‘,‘a‘,‘1‘) from dual; -- 结果:1bc
//判断,类似switch case case
CASE 字段
WHEN xx -- 如果是 xx值
THEN xx -- 替换成 xx值
ELSE --否则
xx --返回 xx值
END
------------------------------------------------
CASE 字段
WHEN xx -- 如果是 xx值
THEN xx -- 替换成 xx值
WHEN xx -- 如果是 xx值
THEN xx -- 替换成 xx值
ELSE --否则
xx --返回 xx值
END
//判读,类似if else
case
when xx=xx
then Yes -- 是
else No -- 不是
end
------------------------------------------------
//判断(oracle独有) decode函数
select
decode(ename,‘是SCOTT‘,‘Yes‘,‘不是SCOTT‘,‘No‘,‘都不是‘)
from emp
where ename = upper(‘scott‘);
//集合操作
union :取并集,比如:A集合有1 3,B集合有1 4;并集结果:1 3 4
select * from emp where ename in(‘SCOTT‘,‘CLARK‘) union select * from emp where ename in(‘SMITH‘,‘ALLEN‘,‘SCOTT‘);
union all :取合集,比如:A集合有1 3,B集合有 1 4;合集结果:1 1 3 4
select * from emp where ename in(‘SCOTT‘,‘CLARK‘) union all select * from emp where ename in(‘SMITH‘,‘ALLEN‘,‘SCOTT‘);
intersect :取交集,比如:A集合有1 3,B集合有1 4;交集结果:1
select * from emp where ename in(‘SCOTT‘,‘CLARK‘) intersect select * from emp where ename in(‘SMITH‘,‘ALLEN‘,‘SCOTT‘);
minus :取差集,比如:A集合有1 3 ,B集合有1 4;差集结果:3
例如:select ename from emp where ename in(‘SCOTT‘,‘ALLEN‘) minus select ename from emp where ename in(‘SCOTT‘,‘ALLEN‘,‘SMITH‘);
结果:“无结果”
例如:select ename from emp where ename in(‘SCOTT‘,‘ALLEN‘,‘SMITH‘) minus select ename from emp where ename in(‘SCOTT‘,‘ALLEN‘);
结果:SMITH
总结:以“第一个”集合为中心,取两结果的相差
//左连接、右连接
-- 左连接:
/*Oracle专用:*/ select d.deptno as "部门编号",d.dname as "部门名称",count(e.deptno) as "总人数" from emp e,dept d where d.deptno=e.deptno(+) group by d.deptno,d.dname order by count(e.deptno);
/*通用:*/ SELECT d.deptno AS "部门编号",d.dname AS "部门名称",COUNT(e.deptno) AS "部门总人数" FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno GROUP BY d.deptno,d.dname ORDER BY 部门总人数
-- 右连接:
/*Oracle专用:*/ select d.deptno as "部门编号",d.dname as "部门名称",count(e.deptno) as "总人数" from emp e,dept d where d.deptno=e.deptno(+) group by d.deptno,d.dname order by count(e.deptno);
/*通用:*/ SELECT d.deptno AS "部门编号",d.dname AS "部门名称",COUNT(e.deptno) AS "部门总人数" FROM emp e RIGHT JOIN dept d ON e.deptno=d.deptno GROUP BY d.deptno,d.dname ORDER BY 部门总人数
//单表“自连接”
/*方法1:*/ select a.ename,b.ename from emp a, emp b where a.mgr=b.empno;
/*内链接通用:*/ SELECT a.ename,b.ename FROM emp a INNER JOIN emp b ON a.mgr=b.empno; //inner 可以省略不写
//满外连接
/*mysql不能用:*/ SELECT e.ename,e.deptno,d.dname,d.deptno FROM emp e FULL JOIN dept d ON e.deptno = d.deptno;
//返回笛卡尔集
SELECT e.ename,e.deptno,d.dname,d.deptno FROM emp e CROSS JOIN dept d;
==============================================Oracle分页==============================================================
//第一页
select * from (select rownum rn,a.* from (select * from emp) a where rownum <=10) where rn >=1;
//第二页
select * from (select rownum rn,a.* from (select * from emp) a where rownum <=20) where rn >=11;
create view my_view
as
select empno,ename,deptno from emp where deptno = 10
union
select 0,‘0‘,0 from emp where 1=0
;
=========================================================================================
//替换现有视图
create or replace view 旧视图名称
as
....
;
//只允许选择条件插入视图
create view 视图名称
as
select empno,ename,sal,deptno from emp where deptno = 10
with check option -- 只能插入 deptno=10 的
;
/*
where deptno in(10,20)
with check option -- 只能插入 10 和 20 的数据
*/
============================存储程序(控制台)=====================================
//显示存储过程脚本输出
set serveroutput on;
------------------------------------------------------------------------------
//存储过程实例
declare
-- 变量
//定义一个变量
变量名 number(3);
//定义一个变量,并赋默认值
变量名 varchar2(20):= NULL;
//定义一个,使用“表.列”类型
变量名 表名.列名%type;
//定义一个容器,相当于List,使用表全部字段
变量名 表名%rowtype;
begin
-- sql语句
//赋值一个变量
select ename into 变量名 from emp where empno=7839;
//赋值两个或多个变量
select ename,sal into 变量名,变量名 from emp where empno=7839;
//赋值容器,表全部字段
select * into 变量名 from emp where empno=7839;
/*
for 循环
*/
set serveroutput on;
declare
begin
for i in 1..5
loop
dbms_output.put_line(i);
end loop;
end;
/*
loop 循环
*/
set serveroutput on;
declare
vnum number(2):=1;
begin
loop //定义loop
exit when vnum > 10; //当满足这个添加退出循环
dbms_output.put_line(vnum);
vnum := vnum + 1;
end loop; //结束loop
end;
/*
while 循环
*/
set serveroutput on;
declare
vnum number(2):=1;
begin
while vnum <= 10 //此处不要分号
loop
dbms_output.put_line(vnum);
vnum:=vnum+1;
end loop;
end;
============================光标(游标)=====================================
//小例子
set serveroutput on;
declare
-- 1、定义光标(所有员工的集合)
cursor c_emp is select ename,job from emp;
-- 7、定义变量,存放ename 和 job
vename emp.ename%type;
vjob emp.job%type;
begin
-- 2、打开光标
open c_emp;
-- 4、循环集合(光标)
loop
-- 6、获取数据
fetch c_emp into vename,vjob;
-- 8、判断集合循环(光标)完退出循环
exit when c_emp%notfound;
//最后输出
//dbms_output.put_line(vename||‘的工作是:‘||vjob);
/* -- 修改语法
if vename = ‘SCOTT‘
then
update emp set ename=‘修改后的名字‘ where ename=vename;
commit;
end if;
*/
-- 5、关闭循环
end loop;
-- 3、关闭光标
close c_emp;
end;
//预定义除数为0异常
set serveroutput on;
declare
vnum number(1):=2;
begin
vnum := vnum/0;
raise ZERO_DIVIDE; -- oracle 预定义异常:除数为0异常
dbms_output.put_line(‘发生异常不走这里!‘);
exception
-- 发生异常处理
when ZERO_DIVIDE then dbms_output.put_line(‘自定义除0异常!‘);
end;
/*自定义异常*/
set serveroutput on;
declare
vnum number(1):=1;
my_exception exception;
begin
if vnum is null
then dbms_output.put_line(‘空啦!‘);
elsif vnum is not null
-- then dbms_output.put_line(‘不为空啦!‘);
then
raise my_exception; -- 抛出异常
end if;
exception
when my_exception then dbms_output.put_line(‘发生异常啦,兄弟!‘);
end;
//返回其他异常
exception
when others
then xxxx;
============================存储过程=====================================
//创建存储过程过程
create procedure 存储过程名字
as
//变量
vnum number:=3;
begin
dbms_output.put_line(vnum);
end;
//修改为 create or replace procedure 存储过程名字
//带参数的存储过程 注意:如果传入的是varchar2类型,这样:vename varchar2 不能 varchar2(10)
create or replace
-- 员工序号,涨多少工资
procedure addSal(vempno in number,vmoney in number)
as
vename emp.ename%type;
vsal emp.sal%type;
begin
update stu set sal=sal+vmoney where empno = vempno;
commit;
select ename,sal into vename,vsal from stu where empno=vempno;
dbms_output.put_line(‘姓名:‘ || vename || ‘ 涨了 ‘ || vmoney || ‘ 工资!‘);
dbms_output.put_line(‘月工资为:‘ || vsal);
end;
/*
执行方式一、
set serveroutput on;
execute 存储过程名字();
*/
/*
执行方式二、
set serveroutput on;
begin
存储过程名字();
end;
/
*/
//查看用户存储过程
select * from user_procedures;
//删除存储过程
drop procedure 存储过程名字;
============================存储函数(带有返回值)=====================================
//创建存储函数
create or replace function My_Function(vempno number)
return varchar2 //存储函数返回值类型
as
vename stu.ENAME%type;
begin
select ename into vename from stu where empno=vempno;
return vename; //返回
end;
/*执行存储函数*/
select My_Function(参数) from dual; //也可用于插入字段
//存储过程跟存储函数,都可以使用out输出变量
create or replace
-- out 输出变量:会生成注释输入,取消掉注释,测试输出
function My_Function(vempno number,vsal out number, vcomm out varchar2)
return varchar2
as
-- 输出不了,没有指定out
vename stu.ENAME%type;
begin
select ename,sal,comm into vename,vsal,vcomm from stu where empno=vempno;
-- 只能手动打印
dbms_output.put_line(vename);
return NULL;
end;
//存储过程使用out参数
create or replace
procedure My_Procedure(name in varchar2,vename out varchar2)
as
vsal stu.sal%type;
begin
select ename,sal into vename,vsal from stu where ename=name;
end;
============================Oracle回收站(ORACLE 10G之后特性) 普通用户,管理员没有回收站(慎重删除)=====================================
//查看回收站
select * from user_recyclebin;
//从回收站中撤回删除的表
flashback table 表名 to before drop; //表名是ORIGINAL_NAME字段
//从回收站撤回删除表时重命名
flashback table 表名 to before drop rename to 新表名;
//根据回收站名字闪回表
flashback table "BIN$XX文字" to before drop;
//清空回收站指定表
purge table 回收站表名; //也就是ORIGINAL_NAME
//清空回收站
purge recyclebin;
==========================(for update 和 for update wait)区别============================
/**
* for update 操作没有提交时,如有另一线程操作,会进行等待...
* for update nowait 操作没有提交时,另一线程操作时,会弹出:ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源
**/
==========================JDBC调用“存储过程”和“存储函数”============================
//JDBC调用存储函数
create or replace
procedure My_Procedure(p_empno in number,r_ename out varchar2,r_sal out number)
as
begin
select ename,sal into r_ename,r_sal from emp where empno=p_empno;
end;
-----------------------------------------------------------------------------------------------------------------------------
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");
//第一个问号是in 参数,后两个是out
CallableStatement call = conn.prepareCall("{call My_Procedure(?,?,?)}");
// 赋值?为7839
call.setObject(1, 7839);
// 指定返回值类型
call.registerOutParameter(2, OracleTypes.VARCHAR);
// 指定返回值类型
call.registerOutParameter(3, OracleTypes.NUMBER);
// 执行查询
call.executeQuery();
//打印返回参数,从?号开始索引
System.out.println(call.getString(2));
//打印返回参数,从?号开始索引
System.out.println(call.getString(3));
//关闭
call.close();
conn.close();
//JDBC调用存储函数
create or replace
function My_Function(p_empno in number)
return varchar2
as
v_ename emp.ename%type;
begin
select ename into v_ename from emp where empno=p_empno;
return v_ename;
end;
//创建一个触发器,不是8点到18点工作日,不能插入数据
create or replace trigger My_Trigger
before -- 指定插入数据之前
insert -- 指定操作触发器DML
on
stu -- 表名
declare
-- 变量
begin
if not (to_number(to_char(sysdate,‘hh24‘)) between 8 and 18)
-- 错误代码必须在-20000~-20999之间(包含,否则提示:“错误号参数超出范围”)
then raise_application_error(-20000,‘现在是非工作时间,不能插入数据!‘);
end if;
end;
//创建一个行级触发器,涨工资不能越涨越少
create or replace trigger My_Trigger2
after -- 插入之后
update
on
stu
for each row -- 行触发器
declare
-- 变量
begin
-- :new 新值 < :old 旧值
if :new.sal < :old.sal
then raise_application_error(-20000,‘工资不能越涨越少呀!‘);
end if;
end;