《Oracle数据库SQL和PL_SQL实例教程》文摘

localhost:1521@ORCL test/122333  sys/122333 dba   scott/tiger

connect SCOTT/tiger@ORCL

show all

select * from emp;

set pagesize 100 linesize 120

show user
select user from dual

spool c:\test
记录信息
spool off

describe emp; desc emp;

select table_name from user_tables;

sqlplus sys/122333 as sysdba

create user student identified by student

grant create session to student;

grant select on scott.dept to student;

drop user student cascade;

grant connect to user1;
grant create table to user1;
grant create procedure to user1;
grant unlimited tablespace to user1;

create table emp as select * from scott.emp;

rownum 是每个表的虚列

select ename, sal, sal*(1+20/100) from emp;

select ename as 名称, sal 工资 from emp;

select ename as "Name", sal '工资' from emp;

select ename||job from emp;
select distinct job from emp;

select ename, sal from emp order by sal asc, ename desc;

select empno, sal*months_between(sysdate, hiredate) as total from emp order by total;

select nvl(comm, 0) from emp;

select concat(rpad(ename, 15, '.'), job) as 职务列表 from emp;

select empno, initcap(ename), job from emp where substr(ename, 1,1) = 'W';

select empno, length(ename), ename from emp where instr(ename, 'S', 1, 1) > 0;  --起始位置1,出现次数1

select trim('s' from 'sos') from dual;

select sysdate from dual;

select last_day('08-2月-03') from dual;

select ename, round(sysdate-hiredate) days from emp where deptno = 10;

select to_date('1980-01-01', 'yyyy-mm-dd') from dual;

to_char to_number

select to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS AM DY') from dual;

select decode(2, 1, '1', 3, '2', '11') from dual;

select userenv('isdba'),userenv('instance'),userenv('language'),userenv('lang'),userenv('terminal') from dual;

select ename, sal, dname from emp, dept where emp.deptno(+) = dept.deptno;

select deptno, max(sal) from emp  group by deptno having max(sal) >= 3000;

select deptno, max(avg(sal)) from emp group by deptno; 会出错,因为各部门平均工资的最高值不应该属于某个部门

select empno, ename, sal from emp where (job, deptno) = (select job, deptno from emp where ename = 'SCOTT');

insert into manager select empno, ename, sal from emp where job  = 'CLERK';

update manager set (ename, sal) = (select ename, sal from emp where empno = 7788) where empno = 1000;

注意truncate/drop/delete区别

select empno , ename, job, sal from emp where deptno = 10 for update;

create sequence AAA minvalue 1 maxvalue 999 start with 1 increment by 1 cache 30;

select sequence_name from user_sequences;

drop table 图书4 cascade constraints;

rename 图书 to 图书5;

truncate table 图书5;

comment on table emp is '公司雇员列表';

select object_name from user_objects where object_type = 'TABLE';

alter table 图书 disable constraint sys_C0011485;

alter table 出版社 add 电子邮件 varchar2(30) check(电子邮件 like '%@%');

alter table 图书 set unused column 出版日期;
alter table 图书 drop unused columns;

alter table emp add constraint PK_4 primary key(empno);
alter table emp drop constraint PK_4;

create table 考生(
考号 varchar2(5),
姓名 varchar2(30),
成绩 number(3))
partition by range(成绩)
(partition A values less than (300) tablespace users,
partition B values less than (500) tablespace users,
partition C values less than (MAXValue) tablespace users);

select * from 考生 partition(C);

grant create view to user1;
grant drop any view to user1;

create or replace view 图书作者(书名, 作者, 出版社) as select 图书名称, 作者, 出版社名称 from 图书, 出版社 where 图书.出版社编号 = 出版社.编号;

create or replace view manager as select * from emp where job = 'MANAGER' with read only;

create or replace view 清华图书 as select * from 图书 where 出版社编号 = '01' with check option;

desc user_updatable_columns;
desc user_objects;

col col_name format a10;

grant create any index to user1;
grant drop any index to user1;
 
create index emp_jobsal on emp(job,sal);

select index_name, index_type, uniqueness,table_name from user_indexes;
select column_name from user_ind_columns;

select * from user_sys_privs;
select * from user_tab_privs;

select aaa.nextval,aaa.currval from dual;

insert into 图书 values('A'||to_char(bookid.nextval, 'fm0000'), '网页制作精选', '01' ,'刘莹', 4, 26.50);

grant create public synonym to user1;
grant create synonym to user1;
grant drop any synonym to user1;

synonym
dict dictionary
cat user_catalog
clu user_clusters
ind user_indexes
obj user_objects
seq user_sequences
syn user_synonyms
cols user_tab_columns
tabs user_tables

create cluster comm(stuno number(5), stuname varchar2(10), sex varchar2(2)) size 500 tablespace users;

create table student(...) cluster comm(stuno, stunname, sex);

create index inx_comm on cluster comm;
创建聚簇后,要创建使用聚簇的表,对聚簇还应该建立索引。如果不对聚簇建立索引,则不能对聚簇表进行插入、修改和删除操作。

drop cluster comm including tables cascade constraints;

create database link abc connect to scott identified by tiger using 'CHENKUND';
分布式查询
select ename, dname from emp@abc e, dept d where e.deptno = d.deptno;

PL/SQL块执行时需要在最后加一个“/”符号

set serveroutput on
declare
v_job varchar2(9);
v_count binary_integer default 0;
v_total_sal number(9,2) := 0;
v_date date:= sysdate+7;
c_tax_rate constant number(3,2) := 8.25;
c_valid boolean not null := true;
begin
v_job := 'MANAGER';
DBMS_OUTPUT.PUT_LINE(v_job);
DBMS_OUTPUT.PUT_LINE(v_count);
DBMS_OUTPUT.PUT_LINE(v_date);
DBMS_OUTPUT.PUT_LINE(c_tax_rate);
end;
/

DECLARE
v_ename emp.ename%TYPE;
BEGIN
...
END;

variable g_ename varchar2(100)
print g_ename

:g_ename := :g_ename || 'Hello~';

 declare
 emp_record emp%ROWTYPE;
 begin
 select * into emp_record from emp where empno = 7788;
 DBMS_OUTPUT.PUT_LINE(emp_record.ename);
 end;
 /

declare
type type_table is table of varchar2(10) index by binary_integer;
v_t type_table;
begin
v_t(1):='MONDAY';
v_t(2):='TUESDAY';
v_t(3):='WEDNESDAY';
v_t(4):='THURSDAY';
v_t(5):='FRIDAY';
DBMS_OUTPUT.PUT_LINE(v_t(3));
end;
/

declare
a number(5) := 2;
begin
DBMS_OUTPUT.PUT_LINE(a**3);
end;
/

IF-THEN-END IF
declare
v_temperature number(5):= 32;
v_result boolean := false;
begin
v_result:= v_temperature > 30;
if v_result then
dbms_output.put_line('温度'|| v_temperature ||'度,偏高')
end if;
end;
/
IF-THEN-ELSE-END IF
IF-THEN-ELSIF-ELSE-END IF

CASE-WHEN-THEN-...-ELSE-END CASE
declare
v_job varchar2(10);
begin
select job into v_job
from emp where empno=7788;
case v_job
when 'PRESIDENT' then
DBMS_OUTPUT.put_line('雇员职务:总裁');
else
DBMS_OUTPUT.put_line('雇员职务:未知');
end case;
end;
/

赋值
declare
v_grade varchar2(10);
v_result varchar2(10);
begin
v_grade:='B';
v_result := case v_grade
when 'A' then '优'
when 'B' then '良'
when 'C' then '中'
when 'D' then '差'
else '未知'
end; -- 没有case
dbms_output.put_line('等级:'|| v_result);
end;
/

表达式
declare
v_sal number(5);
begin
select sal into v_sal from emp where empno = 7788;
case
when v_sal >= 3000 then
dbms_output.put_line('high');
when v_sal >= 1500 then
dbms_output.put_line('middle');
else
dbms_output.put_line('low');
end case;
end;
/

 declare
 v_total number(5):=0;
 v_count number(5):=1;
 begin
 loop
 v_total := v_total + v_count**2;
 exit when v_count = 15;
 v_count:=v_count+2;
 end loop;
 dbms_output.put_line(v_total);
 end;
 /

begin
for i in 1..8
loop
dbms_output.put_line(to_char(i) || rpad('*', i,'*'));
end loop;
end;
/

 begin
 for i in reverse 1..8
 loop
 dbms_output.put_line(to_char(i));
 end loop;
 end;
 /

declare v_count number(2):=1;
begin
while v_count < 6 loop
insert into emp(empno, ename) values(5000+v_count, '临时');
v_count:=v_count+1;
end loop;
end;
/

SQL%ROWCOUNT SQL%FOUND SQL%NOTFOUND SQL%ISOPEN
begin
update emp set sal=sal+100 where empno = 1234;
if sql%found then
dbms_output.put_line('success');
commit;
else
dbms_output.put_line('fail');
end if;
end;
/

declare
v_ename varchar2(10);
v_job varchar2(10);
cursor emp_cursor is select ename, job from emp where empno = 7788;
begin
open emp_cursor;
fetch emp_cursor into v_ename, v_job;
dbms_output.put_line(v_ename ||','||v_job);
close emp_cursor;
end;
/

declare
cursor aaa is select ename, job, sal from emp where empno=7788;
emp_record aaa%rowtype;
begin
open aaa;
fetch aaa into emp_record;
dbms_output.put_line(emp_record.ename || emp_record.job || to_char(emp_record.sal));
close aaa;
end;
/

declare
cursor AAA is select ename, sal from emp order by sal desc
a AAA%rowtype;
begin
open AAA;
for i in 1..3
loop
fetch AAA into a;
dbms_output.put_line(a.ename ||','|| a.sal);
end loop;
close AAA;
end;
/

declare
cursor emp_cursor is
select empno, ename from emp;
begin
for emp_record in emp_cursor loop
dbms_output.put_line(emp_record.empno || emp_record.ename);
end loop;
end;
/

begin
for re in (select ename from emp)
loop
dbms_output.put_line(re.ename);
end loop;
end;
/

declare
v_ename varchar2(10);
cursor emp_cursor is select ename from emp;
begin
open emp_cursor;
if emp_cursor%isopen then
loop
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(to_char(emp_cursor%rowcount)||'-'||v_ename);
end loop;
close emp_cursor;
else
dbms_output.put_line('not open!!!');
end if;
end;
/

declare
v_empno number(5);
v_ename varchar2(10);
cursor emp_cursor(p_deptno number, p_job varchar2) is
select empno, ename from emp where deptno = p_deptno and job = p_job;
begin
open emp_cursor(10, 'CLERK');
loop
fetch emp_cursor into v_empno,v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_empno ||','||v_ename);
end loop;
end;
/

declare
v_empno number(5);
v_ename varchar2(10);
v_deptno number(5);
v_job varchar2(10);
cursor emp_cursor is
select empno, ename from emp where deptno = v_deptno and job = v_job;
begin
v_deptno :=10;
v_job:='CLERK';
open emp_cursor;
loop
fetch emp_cursor into v_empno,v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_empno ||','||v_ename);
end loop;
end;
/

declare
str varchar2(100);
v_ename varchar2(10);
begin
str:='select ename from scott.emp where empno=7788';
execute immediate str into v_ename;
dbms_output.put_line(v_ename);
end;
/

declare
type cur_type is ref cursor;
cur cur_type;
rec scott.emp%ROWTYPE;
str varchar2(50);
letter char:='A';
begin
loop
str:='select ename from emp where ename like ''%'||letter||'%''';
open cur for str;
dbms_output.put_line('contains '||letter||' name');
loop
fetch cur into rec.ename;
exit when cur%notfound;
dbms_output.put_line(rec.ename);
end loop;
exit when letter='Z';
letter:=chr(ascii(letter)+1);
end loop;
end;
/

declare
v_name varchar2(10);
begin
select ename into v_name from emp where empno = 1234;
DBMS_OUTPUT.PUT_LINE('name :'|| v_name);
exception
when no_data_found then
DBMS_OUTPUT.PUT_LINE('numero error');
when others then
DBMS_OUTPUT.PUT_LINE('other');
end;
/

declare
v_temp number(5):=1;
begin
v_temp := v_temp/0;
exception
when others then
DBMS_OUTPUT.PUT_LINE('error');
DBMS_OUTPUT.PUT_LINE(sqlcode());
DBMS_OUTPUT.PUT_LINE(sqlerrm());
end;
/

系统预定义异常
CURSOR_ALREADY_OPEN ORA_06511 试图打开已经打开的游标
INVALID_CURSOR ORA_01001 试图使用没有打开的游标
DUP_VAL_ON_INDEX ORA_00001 保存重复值到惟一索引约束的列中
ZERO_DIVIDE ORA_01476 发生除数为零的除法错误
INVALID_NUMBER ORA_01722 试图对无效字符进行数值转换
ROWTYPE_MISMATCH ORA_06504 主变量和游标的类型不兼容
VALUE_ERROR ORA_06502 转换、截断或算术运算发生错误
TOO_MANY_ROWS ORA_01422 SELECT INTO 语句返回多于一行的数据
NO_DATA_FOUND  ORA_01403  SELECT INTO 语句没有数据返回
TIMEOUT_ON_RESOURCE  ORA_00051  等待资源时发生超时错误
TRANSACTION_BACKED_OUT  ORA_00060  由于死锁,提交失败
STORAGE_ERROR  ORA_06500  发生内存错误
PROGRAM_ERROR  ORA_06501  发生PL/SQL 内部错误
NOT_LOGGED_ON  ORA_01012  试图操作未连接的数据库
LOGIN_DENIED  ORA_01017  在连接时提供了无效用户名或口令

 declare
 v_ename varchar2(10);
 null_insert_error exception;
 pragma exception_init(null_insert_error, -1400);
 begin
 insert into emp(empno) values(null);
 exception
 when null_insert_error then
 dbms_output.put_line('unable to insert null value');
 when others then
 dbms_output.put_line('other system error');
 end;
 /

declare
new_no number(10);
new_excp1 exception;
new_excp2 exception;
begin
new_no:= 6789;
insert into emp(empno, ename) values(new_no, 'xiaozheng');
if new_no < 7000 then
raise new_excp1;
end if;
if new_no > 8000 then
raise new_excp2;
end if;
commit;
exception
when new_excp1 then
rollback;
dbms_output.put_line('<7000');
when new_excp2 then
rollback;
dbms_output.put_line('>8000');
end;
/

RAISE_APPLICATION_ERROR

 create or replace procedure emp_count as v_total number(10);
 begin
 select count(*) into v_total from emp;
 dbms_output.put_line(v_total);
 end;
 /

execute emp_count;
begin emp_count end;/

grant execute on emp_count to user1;
alter procedure emp_count compile;

create or replace procedure change_salary(p_empno in number default 7788,
p_raise number default 10)
as
v_ename varchar2(10);
v_sal number(5);
begin
select ename, sal into v_ename, v_sal from emp where empno = p_empno;
update emp set sal = sal+p_raise where empno = p_empno;
dbms_output.put_line(v_ename || ' change to ' || to_char(v_sal + p_raise));
commit;
exception
when others then
dbms_output.put_line('error');
rollback;
end;
/

execute change_salary(7782, 80);
execute change_salary(p_empno=> 7782, p_raise=>80);

create or replace procedure emp_count(p_total out number) as
begin
select count(*) into p_total from emp;
end;
/

declare
v_empcount number;
begin
emp_count(v_empcount);
dbms_output.put_line(v_empcount);
end;
/

create or replace function get_emp_name(p_empno number default 7788)
return varchar2 as
v_ename varchar2(10);
begin
select ename into v_ename from emp where empno=p_empno;
return (v_ename);
exception
when no_data_found then
dbms_output.put_line('no data');
return (null);
when too_many_rows then
dbms_output.put_line('reduplicate');
when others then
dbms_output.put_line('others');
return(null);
end;
/

desc user_source;      //查询存储过程、函数
desc get_emp_name;    //查询其参数
show errors        //查看编译错误
desc user_dependencies;    //检查存储过程或函数的依赖性

常用系统包
DBMS_OUTPUT 在SQL*Plus 环境下输出信息
DBMS_DDL 编译过程函数和包
DBMS_SESSION 改变用户的会话,初始化包等
DBMS_TRANSACTION 控制数据库事务
DBMS_MAIL 连接Oracle*Mail
DBMS_LOCK 进行复杂的锁机制管理
DBMS_ALERT 识别数据库事件告警
DBMS_PIPE 通过管道在会话间传递信息
DBMS_JOB 管理Oracle 的作业
DBMS_LOB 操纵大对象
DBMS_SQL 执行动态SQL 语句


create or replace package employe is
procedure show_detail;
procedure get_employe(p_empno number);
procedure save_employe;
procedure change_name(p_newname varchar2);
procedure change_sal(p_newsal number);
end employe;
/

create or replace package body employe is
employe emp%rowtype;
procedure show_detail as
begin
dbms_output.put_line('info');
dbms_output.put_line(employe.empno);
dbms_output.put_line(employe.ename);
dbms_output.put_line(employe.job);
dbms_output.put_line(employe.sal);
dbms_output.put_line(employe.deptno);
end show_detail;
PROCEDURE GET_EMPLOYE(P_EMPNO NUMBER)
AS
BEGIN
SELECT * INTO EMPLOYE FROM EMP WHERE EMPNO=P_EMPNO;
DBMS_OUTPUT.PUT_LINE('获取雇员'||EMPLOYE.ENAME||'信息成功');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('获取雇员信息发生错误!');
END GET_EMPLOYE;
PROCEDURE SAVE_EMPLOYE
AS
BEGIN
UPDATE EMP SET ENAME=EMPLOYE.ENAME, SAL=EMPLOYE.SAL WHERE EMPNO=
EMPLOYE.EMPNO;
DBMS_OUTPUT.PUT_LINE('雇员信息保存完成!');
END SAVE_EMPLOYE;
PROCEDURE CHANGE_NAME(P_NEWNAME VARCHAR2)
AS
BEGIN
EMPLOYE.ENAME:=P_NEWNAME;
DBMS_OUTPUT.PUT_LINE('修改名称完成!');
END CHANGE_NAME;
PROCEDURE CHANGE_SAL(P_NEWSAL NUMBER)
AS
BEGIN
EMPLOYE.SAL:=P_NEWSAL;
DBMS_OUTPUT.PUT_LINE('修改工资完成!');
END CHANGE_SAL;
END EMPLOYE;
/

ALTER PACKAGE 包名 COMPILE PACKAGE
ALTER PACKAGE 包名 COMPILE PACKAGE BODY

grant execute on emp_pk to user1;

CREATE OR REPLACE TRIGGER DML_LOG
BEFORE --触发时间为操作前
DELETE OR INSERT OR UPDATE -- 由三种事件触发
ON emp
FOR EACH ROW -- 行级触发器
BEGIN
IF INSERTING THEN
INSERT INTO logs VALUES(logs_id_squ.NEXTVAL,'EMP','INSERT',:new.empno,SYSDATE,USER);
ELSIF DELETING THEN
INSERT INTO logs VALUES(logs_id_squ.NEXTVAL,'EMP','DELETE',:old.empno,SYSDATE,USER);
ELSE
INSERT INTO logs VALUES(logs_id_squ.NEXTVAL,'EMP','UPDATE',:new.empno,SYSDATE,USER);
END IF;
END;


create or replace trigger log_sal
before
update of sal
on emp
for each row
WHEN (new.job='CLERK' AND (ABS(new.sal-old.sal)>200))    //when中new old不加:
declare
v_no number;
begin
select count(*) into v_no from logerr;
INSERT INTO logerr VALUES(v_no+1,'雇员'||:new.ename||'的原工资:'||:old.sal||'新工资:'||:new.sal);
end;
/

数据库事件触发器的触发事件
种 类 关 键 字 说 明
CREATE 在创建新对象时触发模式级
ALTER 修改数据库或数据库对象时触发
DROP 删除对象时触发
STARTUP 数据库打开时触发
SHUTDOWN 在使用NORMAL 或IMMEDIATE 选项关闭数据库时触发数据库级
SERVERERROR 发生服务器错误时触发数据库级与模式级
LOGON 当用户连接到数据库,建立会话时触发
LOGOFF 当会话从数据库中断开时触发


语句级触发器适合于对整个表的操作权限进行控制

数据库事件属性
属 性 适用触发器类型 说 明
Sys.sysevent 所有类型 返回触发器触发事件字符串
Sys.instance_num 所有类型 返回Oracle 实例号
Sys.database_name 所有类型 返回数据库名字
Sys.server_error(stack_position) SERVERERROR
从错误堆栈指定位置返回错误号,参数为1 表示最近的错误
Is_servererror(error_number) SERVERERROR 判断堆栈中是否有参数指定的错误号
Sys.login_user 所有类型 返回导致触发器触发的用户名
Sys.dictionary_obj_type CREATE、ALTER、DROP 返回DDL 触发器触发时涉及的对象类型
Sys. dictionary_obj_name CREATE、ALTER、DROP 返回DDL 触发器触发时涉及的对象名称
Sys.des_encrypted_password CREATE、ALTER、DROP 创建或修改用户时,返回加密后的用户密码

grant administer database trigger to user1

create or replace trigger init_logon
after startup
on database
begin
delete from userlog;
end;
/

create or replace trigger database_logon
after logon
on database
begin
insert into userlog values(sys.login_user, sysdate);
end;
/

create or replace trigger nodrop_emp before
drop on schema
begin
if sys.dictionary_obj_name = 'EMP' then
raise_application_error(-20005, 'no drop emp');
end if;
end;
/

create or replace trigger change_name instead of insert on emp_name
declare
v_empno number(4);
begin
select max(empno)+1 into v_empno from emp;
insert into emp(empno, ename)
values (v_empno, :new.ename);
end;
/

user_triggers

你可能感兴趣的:(数据库)