登录 用户名sys 密码输orcl as sysdba 或者,斜杠前面是用户名,后面是密码,@后面是主机字符串 conn sys/orcl@orcl as sysdba conn scott/tiger@orcl
退出 exit
环境变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
环境变量查看 show 查看当前sqlplus系统变量 showall showuser show error showtiming 环境变量设置 set wrap off 关闭自动换行 set serveroutput on 使用自带输出方法(dbms_output.put_line方法) settimingon 显示查询耗费时间 set autocommit on 自动提交DML set linesize 180 一行最多180字符 set pause on/off 设置 SQL *Plus 输出结果是否滚动显示 off 是默认值,返回结果一次性输出完毕,中间的每一页不会暂停 on 表示输出结果的每一页都暂停,用户按后回车键后继续显示
行编辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
list 列出缓冲区内容 list1 列出第一行 list232,3行 listlast 最后一行 list * 当前行(有一个类似指针的标记)
append [string] 把string的内容追加到当前行后面 input [string] string内容插入到当前行之后作为一个新行 del 删除当前行 del [n] 删除第n行 clear buffer 清空缓冲区 clear screen 清屏 edit 打开记事本作为输入区编辑 @或start c:/1.sql 运行sql脚本 describe/desc [table|function]返回对表或函数的描述、 help xxx 对某个命令的帮助
like例题: 1.创建t_char表 SQL>createtable t_char (a varchar2(30)); 2.向t_char表中插入数据 'abc''a%b''abc%''bc%' 'ab%%c''%abc''ab/c''bcd' 'ab''b_c''ad' 3.查询包含d字符 SQL>select*from t_char where a like'%d%'; bcd ad 4.查询包含通配符% SQL>select*from t_char where a like'%/%%'escape'/'; a%b abc% bc% ab%%c %abc 5.查询包含两个通配符% SQL>select*from t_char where a like'%/%/%%'escape'/'; ab%%c 6.查询以通配符%开始 SQL>select*from t_char where a like'/%%'escape'/'; %abc 7.查询以通配符%结尾 SQL>select*from t_char where a like'%/%'escape'/'; abc% bc% 8.查询包含转义字符 SQL>select*from t_char where a like'%//%'escape'/'; ab/c
where子查询 select ename,emp.deptno,sal from emp,dept where emp.deptno=dept.deptno and dept.loc='NEW YORK';
等价单行嵌套查询 select ename,deptno,sal form emp where deptno=(select deptno from dept where dept.loc='NEW YORK'); 子查询先处理,然后传递给父查询 运算符=,还有大于小于,in(in可以返回多行)
多行嵌套查询 在A,S部门工作的员工 select ename.deptno,sal from emp where deptno in(select deptno form dept where dname in('ACCOUNTING','SALES'));
多列嵌套查询 每个部门最多工资的人 select ename,deptno,sal from emp where (deptno,sal) in (select deptno,max(sal) from emo groupby deptno);
having子查询 差不多的用法 having avg(sal)>(select sal from emp where ename='smart');
from子查询、内联视图 from emp,(select deptno,loc from dept where...) x 主查询的from子句中的子查询称为内联视图。后面标签x是必须的别名
exist相关子查询
1 2 3 4 5 6 7 8
exist引用父查询中的表,称为相关子查询。对父语句处理每一行执行一次。
经典例,选了某个老师所有课,大概这样?记不太清 select * form student x where not exists (select * from course y where cteacher='''' and not exists (select * from sc z where z.sno=x.sno and z.cno=y.cno))
rownum
1 2 3 4 5 6
rownum是系统分配的,从查询返回的行的编号。可以用于限制返回总行数。 【是取数据的时候产生的序号】个人理解,where之后的顺序 where用小于n;大于、等于只能用1;between必须从1开始 select rownum,ename from emp where rownum<5; √ select rownum,ename form emp where rownum=2; × rownum总是从1开始;查出第一行,≠2,不返回;下一条记录取数据还是第一行
查询数据库文件
1 2 3
select * from v$datafile; select * from v$controlfile; select * from v$logfile;
DDL
create
复制表
1 2 3 4 5 6
从一个表生成另一个表 createtable emp1 asselect * from emp where deptno=10; 与emp表有相同列名、相同数据类型,但是没有主键/外键约束 可以通过任何select语句创建
drop packagemyPackage;删除包说明和包主体 drop packagebodymyPackage;只删除包主体
truncate
清空表中所有记录,但保留表结构和相关对象(触发器等)
1
truncatetable emp;
与delete区别:
truncate是ddl(define定义),将高水平线复位,释放表空间
delete是dml(manage操纵),删除数据行,并不释放空间
DML
insert
一次只能insert一行,位置要对应
多行只能通过其他表中的数据添加
1
insertinto emp1 (select*from emp);
update
1
update emp set ... where ...
delete
1
deletefrom emp where...
删除记录不能释放oracle被占用的数据块表空间,只把被删除的数据块标成unused
PL/SQL
运行机制
程序结构
声明部分(declare开头)
变量声明、赋初值
执行部分(begin)
执行代码
异常处理部分(exception)
执行部分是必须的,其他两个部分可选。每个块部分的语句都必须以分号结束。
每个块由begin/declare开始,以end结束。
匿名块,输入/运行;
命名块,用/创建,execute执行,或者在其他块中调用
可以使用任何有效的DQL DML语句,还可以使用commit、rollback等TCL
程序示例
1 2 3 4 5 6 7 8
declare var number:=10; 赋值使用:= begin update emp set comm=sal*i_percent where deptno=10; end; / 输这个,然后换行,执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
命名: createor replace procedureupdate_emp (v_dept in number,v_percent in number default 10)is begin updateemp setcomm=sal*v_percent wheredeptno=v_dept; end; / execute update_emp(10,15);
调用: declare v_dept number; begin select a.deptno into v_dept from emp a where job='PRESIDENT'; update_emp(v_dept); end;
语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
--单行注释 /**/块注释 :=赋值 select col intovar from...where...; 赋值 select * into emorecord form...where...;记录类型赋值 *一个selectinto语句有且仅有一行结果集,如果没有返回/多于一行都会引起异常。
变量声明 Variable_name [CONSTANT] databyte [NOTNULL][:=|DEFAULT expression] constant:常量 not null后面必须加:=赋初值
Insertinto tb1(col1) values(1); Begin Update emp set comm=2000 Where empno=7839; Rollback; End; 匿名语句块中先update,然后rollback。这个rollback不仅撤销了update语句,也撤销了前面的insert语句。 Insert和该语句块属于同一个事务。
【1】 set serveroutput on (使用自带输出方法dbms_output.put_line) createor replaceprocedure Get_EMP_Ename(ename1 out emp.ename%type,job1 in emp.job%type) as begin select ename into ename1 from emp where emp.job=job1; end; / declare ename emp.ename%type; begin Get_emp_ename(ename,'PRESIDENT'); dbms_output.PUT_LINE(ename); end; /
【2】 set serveroutput on createor replaceprocedure Get_EMP_Ename(ename1 out emp.ename%type,job1 in emp.job%type) as begin select ename into ename1 from emp where emp.job=job1; end; /
set serveroutput on createor replacefunction Get_EMP_Ename_func(job1 in emp.job%type) return emp.ename%typeas ename1 emp.ename%type; begin select ename into ename1 from emp where emp.job=job1; return ename1; end; / declare ename emp.ename%type; begin ename:=Get_emp_ename_func('PRESIDENT'); dbms_output.PUT_LINE(ename); end;
其他调用方法 var ename varchar2(10) exec :ename:=Get_emp_ename_func('PRESIDENT'); print ename call get_emp_ename_func('PRESIDENT') into :ename; print ename
cursor cur_name is select...from...where...; open cur_name; 取数据:fetch将游标内数据取出到变量,或游标for循环 close cur_name;
set serveroutput on declare v_name varchar(20); cursor c_emp isselect ename from emp; begin open c_emp; loop fetch c_emp into v_name; --c_emp游标的数据到变量v_name exit when c_emp%notfound; --检查的是之前的fetch有没有取到值 dbms_output.PUT_LINE(TO_CHAR(c_emp%ROWCOUNT)||' '||v_name); end loop; close c_emp; end; / 可改写while循环: Fetch c_emp into v_name; While c_emp%found loop Dbms_output.put_line(); Fetch c_emp into v_name; End loop;
简化了游标操作,自动声明r、打开游标、取数据。 set serveroutput on; declare cursor c_emp isselect ename from emp; begin for r in c_emp loop r隐式声明,类型为c_emp%rowtype dbms_output.PUT_LINE(c_emp%rowcount || ' ' || r.ename); endloop; end; /
如果在使用游标FOR循环时不需要使用任何游标属性,那么直接在游标FOR循环中使用子查询。 begin for r in (select ename from emp) loop dbms_output.PUT_LINE(r.ename); endloop; end; /
declare v_name emp.ename%type; cursor c_emp(v_deptno number) is select ename from emp where deptno=v_deptno; begin open c_emp(10); loop fetch c_emp into v_name; exitwhen c_emp%notfound; dbms_output.put_line(v_name); endloop; close c_emp; end; /
declare cursor c_emp(v_deptno number) is select ename from emp where deptno=v_deptno; begin for r in c_emp(10) loop dbms_output.PUT_LINE(c_emp%rowcount || ' ' || r.ename); endloop; end; /
for update
1 2 3 4 5 6 7 8 9 10 11 12 13 14
处理游标的当前行—修改或删除 set serveroutput on; declare cursor c_emp(v_deptno number) is select ename from emp1 where deptno=v_deptno FORUPDATE; -- for update的作用是游标打开的时候对数据集加锁 begin for r in c_emp(10) loop deletefrom emp1 WHERECURRENTOF c_emp; endloop; end;
update emp1 set sal=sal*1.3WHERECURRENTOF c_emp; 可以 UPDATE语句仅更新在游标声明的FORUPDATE子句处列出的列。如果没有列出任何列,那么所有的列都可以更新。
游标变量
之前例子都是静态游标--游标与sql语句相关联,编译的时候就确定sql语句。
游标变量可以在运行时拥有不同的值。是一种引用类型,跟指针相似。程序运行中可以指向不同的存储位置。
1 2 3 4 5 6 7 8 9 10 11 12 13
createor replaceprocedure proc1(v_deptno number) as TYPE curref ISREFCURSOR; varcur curref; empinfo emp%rowtype; begin open varcur forselect * from emp where deptno=v_deptno; loop fetch varcur into empinfo; exitwhen varcur%notfound; dbms_output.put_line(empinfo.empno||' '||empinfo.ename); endloop; end;
【1】 declare v_empno emp.empno%TYPE; v_sal emp.sal%TYPE; e_toolow exception; errNum integer; errMsg varchar2(600); begin v_empno:=7900; select sal into v_sal from emp where empno=v_empno; if v_sal<1000then raise e_toolow; endif; exception when e_toolow then dbms_output.put_line('工资太低了'); when others then errNum:=SQLCODE; errMsg:=SQLERRM; raise_application_error(-20000,errNum ||' '||errMsg); end;
CREATEOR REPLACE PACKAGE<包名> IS 变量、常量及数据类型定义; 游标定义; 函数、过程定义和参数列表及返回类型; END<包名>; 都是公共的,包之外的程序可以调用。
createor replace package OpOnEmp as procedure Get_EMP_Ename(ename1 out emp.ename%type,job1 in emp.job%type); function Get_EMP_Ename_func(job1 in emp.job%type) return emp.ename%type; end OpOnEmp;
创建包主体部分的语句格式如下: CREATEOR REPLACE PACKAGE BODY<包名> AS 私有变量等结构 游标、函数、过程的具体定义; END<包名>;
createor replace package body OpOnEmp as --增加一个存储过程 procedure Get_EMP_Ename(ename1 out emp.ename%type,job1 in emp.job%type) as begin select ename into ename1 from emp where emp.job=job1; end Get_EMP_ename; --增加一个函数 function Get_EMP_Ename_func(job1 in emp.job%type) return emp.ename%typeas ename1 emp.ename%type; begin select ename into ename1 from emp where emp.job=job1; return ename1; end Get_EMP_Ename_func; end OpOnEmp; //函数体
var a varchar2(30) exec oponemp.get_emp_ename(:a,'PRESIDENT'); print a
1 2 3 4 5 6 7 8 9 10 11
利用包定义全局变量 create or replace package public_var as pinumber:=3.14; end; --调用全局变量 declare area number(4,2); begin area:=public_var.pi*2*2; dbms_output.put_line(area); end;
Createor replacetrigger checksal Beforeinsertorupdateon emp1 Foreachrow When(new.sal<1000) Begin Raise_application_error(-20001, 'The salary is too low.'); End; When子句里面的表达式可以用new和old引用当前行。但这不加冒号。冒号只在触发器体中有效。
CREATEOR REPLACEtrigger op_emp1_log afterINSERTorupdateordeleteON emp1 Declare descstr varchar2(50); begin if inserting then descstr:='Insert'; elsif updating then descstr:='update'; else descstr:='delete'; endif;
insertinto logtb values (user,sysdate,descstr || ' on emp1'); end;
触发器谓词:
Inserting 如果触发语句为insert,则为true
Updating 如果触发语句为update,则为true
Deleting 如果触发语句为delete,则为true
替代触发器
Instead of 触发器只能定义于视图上,触发事件是视图上的DML,主要用于修改一个本来不能修改的视图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
创建视图: createor replaceview stuview as select s.sno,s.sname,math,english from student s,score where s.sno=score.sno;
在数据库事件上发生,包括:服务器的启动与关闭、用户登录/注销,以及服务器错误。 Servererror after 有错就激发 Logon after 用户成功连接数据库激发 Logoff before 用户刚开始注销 Startup after 实例开始时激发 Shutdown before 实例关闭之前激发 //异常关闭,也许不激发
--database级别上: createor replacetrigger logconnect after logon ondatabase begin insertinto scott.logtable values(user,sysdate); end;
--schema级别上: createor replacetrigger logconnect after logon onschema begin insertinto scott.logtable values(user,sysdate); end;
授予对象权限 grant object_privs(column,...) on object_name touser/role/public...with grant option grantinserton tb1 to user1; user1插入table1的权限 grantinsert(id,name) on tb1 to user1; grantexecuteon dbms_output to jeff; grantallon emp1 to yzp;--emp1表上所有的对象权限 grantselecton authors to testuser1 withgrant option
撤销权限 Revokecreatetablefrom testuser2 Revokeselecton authors from testuser1;
使用CREATEROLE语句可以创建一个新的角色,执行该语句的用户必须具有CREATEROLE系统权限。 授予权限.把角色授予给用户 createrole role1; grantselect,update,deleteon scott.emp to role1; grantcreatesessionto role1; createuser yzp identified by yzp; grant role1 to yzp;
默认只有建立角色的用户具有对该角色的管理权限。 可以使用以下语句,把管理角色的能力授予用户。 Grant rolename to username withadminoption 使用WITHADMINOPTION为角色授予的权限不级联取消
删除角色 撤销用户的角色:Revoke role1 from yzp; 删除角色:droprole role1; 在删除角色前不需要撤销角色; 角色删除后,原来拥有该角色的用户就不再拥有该角色了,相应的权限也就没有了