Oracle汇总笔记
http://gzf_PC:1158/em
数据库配置文件已经安装到 D:\WorkC,同时其他选定的安装组件也已经安装到 D:\WorkC\oracle。
iSQL*Plus URL 为:
http://gzf_PC:5560/isqlplus
iSQL*Plus DBA URL 为:
http://gzf_PC:5560/isqlplus/dba
-- 创建表
drop table test;
create table test(
Id int,
UName varchar2(20),
constraint ucon unique(Id)
);
-- 创建的同时 指定主键值;
create table cdpt(
id number(6),
name varchar2(30),
constraint pk_id primary key(id)
);
insert into test values(1,'郭泽峰');
select * from test;
-- 复制表和数据(不复制表约束)
create table testback as select * from test;
-- 复制表结构
drop table testback;
create table testback as select * from test where 1=2;
-- 创建索引
create index i_1 on test(uname asc);
-- 给表或视图取一个别名
create synonym testother for test;
-- 添加列
alter table test add (other int)
-- 删除列
alter table test modify (other varchar2(50))
alter table test drop (other)
-- 修改表名
rename test11 to test
-- 添加外键约束
Alter table emp add constraint S_F Foreign key (deptno) references dept(deptno);
--
/*
5 .对已经存在的表添加约束
ALTER TABLE <table_name> ADD CONSTRAINT <constraint_name> 约束类型 (针对的字段名);
示例:
Alter table emp add constraint S_F Foreign key (deptno) references dept(deptno);
6 .对表里的约束禁用;
ALTER TABLE <table_name> DISABLE CONSTRAINT <constraint_name>;
7 .对表里的约束重新启用;
ALTER TABLE <table_name> ENABLE CONSTRAINT <constraint_name>;
8 .删除表中约束
ALTER TABLE <table_name> DROP CONSTRAINT <constraint_name>;
示例:
ALTER TABLE emp drop CONSTRAINT <Primary key>;
*/
-- 删除
drop table aa
drop index aa
drop synonym aa -- 删除别名
-- 删除
SELECT [DISTINCT] <column1 [as new name] ,columns2,...>
FROM <table1>
[WHERE <条件>]
[GROUP BY <column_list>]
[HAVING <条件>]
[ORDER BY <column_list> [ASC|DESC]]
--
select * from emp where not deptno=10;
select * from emp where empno in(7788,7369,7499);
select * from emp where sal between 1000 and 3000;
select * from emp where ename like '_C%';
--
select * from emp where sal=(select max(sal) from emp);
--找出比deptno=30的员工最低工资高的其他部门的员工
select * from emp where sal>ANY(select sal from emp where deptno=30) and deptno<>30;
-- 找出比deptno=30的员工最高工资高的其他部门的员工
select * from emp where sal>ALL(select sal from emp where deptno=30) and deptno<>30;
-- 两个表链接
select empno,ename,dname from emp,dept where emp.deptno=dept.deptno;
--
select * from emp where rownum<=10;--查询前10行记录
--注意ROWNUM只能为1 因此不能写 select * from emp where rownum between 20 and 30;
--
select * from emp where rownum<=3 and empno not in (select empno from emp where rownum<=3);
---结果可以返回整个数据的3-6行;
-- oracle分页查询:效率最低
select * from (select t.*,row_number() over(order by Id desc) rk from test t) where rk<5 and rk>2;
--另一种分页效率稍微高[必须先小于后大于]
select * from(select t.*,rownum rn from(select * from test order by Id asc) t where rownum<7) where rn>5;
-- 效率比较低
SELECT b.* FROM (SELECT A.*, ROWNUM RN FROM (SELECT * FROM test order by Id) A ) b WHERE b.RN BETWEEN 4 AND 5
--
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM test) A
WHERE ROWNUM <= 5
)
WHERE RN >= 3
-- 创建视图
drop view testView
create view testView
as
select Id from test
-- 创建存储过程 (修改 or replace)
create procedure guo(
a int,
)
as
begin
select a;
end
/*
Create 创建
Sequence 序列 seqEmop 序列名称
Increment by 步长
Stat with 1 开始值
Maxvalue 最大值
Minvalue 最小值
*/
-- 创建序列:
Create sequence seq_cdpt
Increment by 1
Start with 1
Maxvalue 999999
Minvalue 1
Nocycle
nocache;
-- 修改序列
Alter sequence seqEmp maxvalue 5;
-- 查询序列
Select seq_cdpt.nextval from dual;
Select seq_cdpt.currval from dual;
-- 使用序列
insert into test(Id) values(444);
insert into test(Id) values(seq_cdpt.nextVal);
commit;-- 必须有commit;
select * from user_indexes where table='test' ;
-- 查看数据及log
select name,log_mode from v$database;
-- 查看实例名字
select instance_name,status from v$instance;
--
select tablespace_name,status,extent_management from dba_tablespaces;
--查看控制文件位置
select name from v$controlfile;
-- 查看数据文件的位置和大小
select name,bytes from v$datafile;
--
SELECT VIEW_NAME FROM USER_VIEWS;
--
SELECT * FROM all_views t where view_name='testview'
--与
select object_name from user_objects where object_type='VIEW'
-- 查看视图内容
select text from user_views where view_name=upper('testview');
-- 变量声明:
declare
guo nvarchar2(50);
begin
guo:='234';
dbms_output.put_line(guo);
end;
-- 查看oracle安装平台:
select * from v$version;
-- 查看控制文件:
select name from v$controlfile;
-- 查看日志文件
select member from v$logfile;
-- 查看数据库对象:
select owner, object_type, status, count(*) count# from all_objects group by owner, object_type, status;
-- 查看数据库版本:
Select version FROM Product_component_version Where SUBSTR(PRODUCT,1,6)='Oracle';
-- 查看数据库日期和归档方式
Select Created, Log_Mode, Log_Mode From V$Database;
-- 创建用户:
CREATE USER <user_name> [profile "DEFAULT"]
identified by "<password>" [default tablespace "USERS"]
-- 删除用户:
DROP USER <user_name> CASCADE
-- 创建角色:
CREATE ROLE <role_name>
identified by "<password>"
-- 删除角色
DROP ROLE <role_name>
--
select * from user_tables
--
--修改密码
alter user gzf identified by gzf;
-- 查询查看当前用户拥有的角色权限信息
select * from role_sys_privs;
-- 查询当前用户
select * from user_users;
-- 查看当前用户的角色信息
select * from user_role_privs;
-- 删除权限:
revoke resource from gzf;
--授予用户权限:
grant connect,resource to gzf;
grant select on scott.Test to gzf;
--删除权限:
revoke select on scott.Test from gzf;
--查询当前时间
select sysdate from dual
/*
boolean:true,false,null;用number(1)来标示;
*/
-- 变量声明:如果错误的话,将用exception输出;
declare guo int:=123123123;
res varchar2(50);
begin
--输出:
guo:=2*2+3/0;
-- set serveroutput on;
res:=To_Char(guo);
dbms_output.put_line(guo);
exception
when others then
dbms_output.put_line('error');
-- commit;
end;
-- 类型在转换
select to_char(12) from dual;
select to_date('2005-01-01 13:14:20','yyyy-MM-dd HH24:mi:ss') from dual;
select to_date('2005-01-03','yyyy-dd-MM') from dual;
select to_number('123') as cc from dual;
-- 打印变量 -- number也存储小数,所以整形,建议用binary_integer;
declare a number:=123.12;
b nvarchar2(10);
c boolean:=true;
begin
b:=to_char(a);
dbms_output.put_line(b);
exception
-- 啥意思?
when others then
dbms_output.put_line('error');
end;
--
--number:如果第二个参数是负数的话,说明四舍五入整数位,123.123 (5,-2)结果:100
declare a number(5,-5):=123.23;
begin
dbms_output.put_line(a);
end;
--多变量声明
declare a int;b int;
begin
a:=123;b:=234;
dbms_output.put_line(a);
end;
-- record类型:v与v1值可以互换;
declare
type guo_type is record(
u_Id int,
u_Name varchar2(50)
);
v guo_type;
v1 guo_type;
begin
v.u_Id:=123;
v.u_Name:='sdfsdf';
dbms_output.put_line(v.u_Name);
end;
-- table类型:相当于数组,可以存储record类型
declare
type ta is table of varchar2(50) index by binary_integer;
va ta;
begin
va(100):='gzf0';
va(101):='gzf1';
va(102):='gzf2';
dbms_output.put_line('索引为100的数据记录va(100):'||va(100));
dbms_output.put_line('第一条记记录va.first:'||va(va.first));
dbms_output.put_line('最后一条记录va.last:'||va(va.last));
dbms_output.put_line('第二条记录的前一条记录va.prior:'||va(va.prior(101)));-- 101是索引
dbms_output.put_line('第二条记录的后一条记录'||va(va.next(101)));
dbms_output.put_line('总记录va.count:'||to_char(va.count));
end;
-- 存储record类型:
declare
type re is record(id varchar2(50));
type ta is table of re index by binary_integer;
va ta;
begin
va(100).id:='gzf123';
dbms_output.put_line(va(100).id);
end;
-- 定义多维度表变量:好像只能填充一条数据:
declare
type tt is table of test%rowtype index by binary_integer;
t tt;
begin
select * BULK COLLECT into t from test where id>0;
for aa in 1..t.count loop
dbms_output.put_line(t(aa).uname);
end loop;
end;
select * from test;
-- 设置类型为表中某个字段类型,这样一旦表类型变化,变量类型也跟着变化;
declare
guo test.ID%type;
begin
guo:=123;
dbms_output.put_line(guo);
end;
-- 行类型:
declare
guo test%rowtype;
begin
select * into guo from test where id=1;
dbms_output.put_line(guo.UNAME||'sfsdf');
end;
--控制语句:if elsif else end if;
declare
a int:=25;
begin
if a>0 and a<10 then
dbms_output.put_line('1');
elsif a>20 and a<40 then
dbms_output.put_line('2');
else
dbms_output.put_line('3');
end if;
end;
--loop: if then exit;也可以,exit when ;也可以
declare
guo int:=0;
begin
loop
guo:=guo+1;
dbms_output.put_line(guo);
if guo=10 then
exit;
end if;
end loop;
end;
-- 或
declare
guo int:=0;
begin
loop
guo:=guo+1;
dbms_output.put_line(guo);
exit when guo=5;
end loop;
end;
-- while循环
declare
guo int:=0;
begin
while guo<10 loop
guo:=guo+1;
dbms_output.put_line(guo);
end loop;
end;
-- for循环:
declare
guo int:=0;
begin
for a in 1..10 loop
guo:=guo+1;
dbms_output.put_line(guo);
end loop;
end;
--异常
begin
dbms_output.put_line(1/0);
exception
when others then
dbms_output.put_line('error');
end;
-- 游标
declare
t test%rowtype;
cursor c is select * from test where id>0;
begin
open c;
loop
fetch c into t;
dbms_output.put_line(t.UName);
exit when c%notfound;
end loop;
close c;
end;
-- 存储过程:out在类型前面;---像varchar2千万不要加长度否则会报错...好变态啊...
create or replace procedure guo11(
iid int,
uname out varchar2
) is
begin
uname:='123rrrr';
end guo11;
--
create or replace procedure guo12(
iid int
)
is
begin
dbms_output.put_line(iid);
end guo12;
--
create or replace procedure guo13
is
begin
dbms_output.put_line(123);
end;
--创建包:--------一些函数或存储过程的包头;
--创建包头
create or replace package package_demo is
function Getage(birthst varchar,birthend varchar) return integer;
function Getsalary(VFpsncode varchar) return number;
end package_demo;
--创建包体
create or replace package body package_demo is
function Getage(birthst varchar,birthend varchar) return integer --得到年龄函数
is
V_birth integer;
ToDateEnd Date;
Toyear number(4);
Tomonth number(4);
Fromyear number(4);
Frommonth number(4);
begin
if (birthend='') or (birthend is null) then
select sysdate into ToDateEnd from dual; --得到系统时间
end if;
Toyear := to_number(to_char(ToDateEnd,'YYYY')); --得到最后年月
Tomonth := to_number(to_char(ToDateEnd,'MM'));
Fromyear := to_number(substr(birthst,1,4));--计算的年月
Frommonth := to_number(substr(birthst,6,2));
if Tomonth-Frommonth>0 then V_birth:=Toyear-fromyear;
else V_birth:=Toyear-fromyear-1;
end if;
return(V_birth);
end Getage;
function getSalary(VFpsncode varchar) return number--返回工资情况
is
V_psnSalary number(8,2);
begin
Select 2 into V_psnSalary from dual;
return(V_psnSalary);
end getSalary;
end package_demo;
-- 调用包体:
select package_demo.getsalary('C001') from dual;
-- 存储过程返回结果集;********************************************************存储过程**************************
----------------------声明一个Package--------------
CREATE OR REPLACE PACKAGE pkg_test
AS
TYPE myrctype IS REF CURSOR;
PROCEDURE get_r(p_id NUMBER,p_rc OUT myrctype); --Package中声明名为get 的Procedure(只有接口没内容)
END pkg_test;
---声明包体
CREATE OR REPLACE PACKAGE BODY pkg_test
AS
PROCEDURE get_r(p_id NUMBER,p_rc OUT myrctype)
IS
sqlstr VARCHAR2 (500);
BEGIN
IF p_id = 0 THEN
OPEN p_rc FOR
SELECT * FROM test;
ELSE
sqlstr :=
'select *
from test where id=:w_id'; --w_id是个参数,
--以下 p_rc是个REF CURSOR游标类型,而且是OUT型参数,即可返回一个记录集了。USING p_id就是替换上面SQL中:w_id值拉:)
OPEN p_rc FOR sqlstr USING p_id;
END IF;
END get;
END pkg_test;
--简单存储过程。。。。。。。。。。。。。。
CREATE OR REPLACE PROCEDURE getcity (
citycode IN int,
ref_cursor OUT sys_refcursor /* 这个sys_refcursor类型在SYS.STANDARD包中 */
)
AS
BEGIN
OPEN ref_cursor FOR
SELECT *
FROM test
WHERE id != citycode;
END;
-- 调用存储过程
declare
t test%rowtype;
cur sys_refcursor;
begin
getcity(1,cur);
-- open cur; --这里游标已经打开,所以不用继续打开
loop
fetch cur into t;
dbms_output.put_line(t.UNAME);
exit when cur%notfound;
end loop;
close cur;
end;
-- 存储过程:参数可以缺省;
/*
create procedure guo(
iid int,
uname varchar,
)
--执行存储过程(默认缺省)
begin
guo();
end
制定一个参数:
begin
guo(uname=>'cheng');
end
*/
begin
guo11();
end;
-- 执行:
declare
uname varchar2(20);
iid int:=123;
begin
guo11(iid,uname);
dbms_output.put_line(uname);
end;
--执行
-- 授予权限...
GRANT SELECT ANY TABLE TO scott WITH ADMIN OPTION;
-- 函数:创建函数:
create or replace function fun(vaName in varchar2)
return varchar2
is
begin
return '111'||vaName;
end;
-- 调用函数:
declare
myresult varchar2(20);
begin
myresult:=fun('hhhh');
dbms_output.put_line(myresult);
end;
-- 打印带out参数的结果:
create or replace function fun1(vaName in varchar2,vaout out varchar2)
return varchar2
is
begin
vaout:='gzf000';
return '111'||vaName;
end;
-- 查询结果:
declare
one varchar2(20);
two varchar2(20);
begin
one:=fun1('fff',two);
dbms_output.put_line(one);
dbms_output.put_line(two);
end;
-- 创建自增列...
Oracle没有自增字段这样的功能,但是通过触发器(trigger)和序列(sequence)可以实现。
先建一个测试表了:
create table userlogin
(
id number(6) not null,
name varchar2(30) not null primary key
)
tablespace users
/
第一步:创建SEQUENCE
create sequence userlogin_seq increment by 1 start with 1 minvalue 1 maxvalue 9999999999999 nocache order;
第二步:创建一个基于该表的before insert 触发器,在触发器中使用刚创建的SEQUENCE
create or replace trigger userlogin_trigger
before insert on userlogin
for each row
begin
select userlogin_seq.nextval into:new.id from sys.dual ;
end;
-- 创建触发器:
例1: 建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去。
CREATE TABLE emp_his AS SELECT * FROM EMP WHERE 1=2;
CREATE OR REPLACE TRIGGER tr_del_emp
BEFORE DELETE --指定触发时机为删除操作前触发
ON scott.emp
FOR EACH ROW --说明创建的是行级触发器
BEGIN
--将修改前数据插入到日志记录表 del_emp ,以供监督使用。
INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )
VALUES( :old.deptno, :old.empno, :old.ename , :old.job,:old.mgr, :old.sal, :old.comm, :old.hiredate );
END;
DELETE emp WHERE empno=7788;
DROP TABLE emp_his;
DROP TRIGGER del_emp;
例2:限制对Departments表修改(包括INSERT,DELETE,UPDATE)的时间范围,即不允许在非工作时间修改departments表。
CREATE OR REPLACE TRIGGER tr_dept_time
BEFORE INSERT OR DELETE OR UPDATE
ON departments
BEGIN
IF (TO_CHAR(sysdate,'DAY') IN ('星期六', '星期日')) OR (TO_CHAR(sysdate, 'HH24:MI') NOT BETWEEN '08:30' AND '18:00') THEN
RAISE_APPLICATION_ERROR(-20001, '不是上班时间,不能修改departments表');
END IF;
END;
例3:限定只对部门号为80的记录进行行触发器操作。
CREATE OR REPLACE TRIGGER tr_emp_sal_comm
BEFORE UPDATE OF salary, commission_pct
OR DELETE
ON HR.employees
FOR EACH ROW
WHEN (old.department_id = 80)
BEGIN
CASE
WHEN UPDATING ('salary') THEN
IF :NEW.salary < :old.salary THEN
RAISE_APPLICATION_ERROR(-20001, '部门80的人员的工资不能降');
END IF;
WHEN UPDATING ('commission_pct') THEN
IF :NEW.commission_pct < :old.commission_pct THEN
RAISE_APPLICATION_ERROR(-20002, '部门80的人员的奖金不能降');
END IF;
WHEN DELETING THEN
RAISE_APPLICATION_ERROR(-20003, '不能删除部门80的人员记录');
END CASE;
END;
/*
实例:
UPDATE employees SET salary = 8000 WHERE employee_id = 177;
DELETE FROM employees WHERE employee_id in (177,170);
*/
例4:利用行触发器实现级联更新。在修改了主表regions中的region_id之后(AFTER),级联的、
自动的更新子表countries表中原来在该地区的国家的region_id。
CREATE OR REPLACE TRIGGER tr_reg_cou
AFTER update OF region_id
ON regions
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('旧的region_id值是'||:old.region_id
||'、新的region_id值是'||:new.region_id);
UPDATE countries SET region_id = :new.region_id
WHERE region_id = :old.region_id;
END;
例5:在触发器中调用过程。
CREATE OR REPLACE PROCEDURE add_job_history
( p_emp_id job_history.employee_id%type
, p_start_date job_history.start_date%type
, p_end_date job_history.end_date%type
, p_job_id job_history.job_id%type
, p_department_id job_history.department_id%type
)
IS
BEGIN
INSERT INTO job_history (employee_id, start_date, end_date,
job_id, department_id)
VALUES(p_emp_id, p_start_date, p_end_date, p_job_id, p_department_id);
END add_job_history;
--创建触发器调用存储过程...
CREATE OR REPLACE TRIGGER update_job_history
AFTER UPDATE OF job_id, department_id ON employees
FOR EACH ROW
BEGIN
add_job_history(:old.employee_id, :old.hire_date, sysdate,
:old.job_id, :old.department_id);
END;
8.2.3 创建替代(INSTEAD OF)触发器
创建触发器的一般语法是:
CREATE [OR REPLACE] TRIGGER trigger_name
INSTEAD OF
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.] view_name --只能定义在视图上
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ] --因为INSTEAD OF触发器只能在行级上触发,所以没有必要指定
[WHEN condition]
PL/SQL_block | CALL procedure_name;
--- 变量还可以既取值又赋值...
/*
create or replace function fun1(vaName in out varchar2)
*/
-- 存储过程可以参数缺省值:为参数指定默认参数...
-- 表复制:
-- 子查询...
--select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
-- 外联
-- select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
--
-- delete from info where not exists(select * from infobz where info.infid=infobz.infid )