这部分是我在看视频和看《oracle四大宝典》时写下的一点笔记,写的比较乱和烂。主要学的是数据库开发方面的知识和整体的架构,非常基础的内容。
dSql*plus常用命令:
1、conn 用户名/密码@网络服务器名 [as sysdba/sysoper]当用特权用户登录是要使用as[]
2、Disc退出 3、passw修改密码 4、desc table 查表结构
3、Creat user xxx identified by ****创建用户
4、授权grant [系统角色权限] to [user],grant [对象权限] on [对象名] (字段名) to [user] (with grant /admin option )权限传递下去
5、回收权限 revoke ......from ......级联回收的
6、创建profile锁定配置文件creat profile (filename) limit failed_login_attempts (count) password_lock_time (days) , alter user username profile (filename);
解锁:alter user (username) account unlock
Drop profile (filename)[cascade(删除相关的)]
Oracle数据类型:
Timestamp 精确到毫秒日期类型。
Char 比 varchar2 查询快很多
Blob 二进制数据类型 存放图片、视频、音频文件。
内嵌视图:
SQL> select * from t_student stu, (select avg(salary) as agv_sal,class_id from t_student group by class_id ) new where stu.salary > new.agv_sal and stu.class_id = new.class_id;
将(select avg(salary) as agv_sal,class_id from t_student group by class_id ) new作为一个内嵌的视图,其实也是内嵌的一张表
子查询:
多行子查询:
All用法:SQL> select * from t_student stu where stu.salary > all(select a.salary from t_student a where a.class_id = 2 );
ANY用法:SQL> select * from t_student stu where stu.salary >= any(select a.salary from t_student a where a.class_id = 3 );
分页:一共有三种方式(挑选出2、3行数据)
1、rownum分页:select * from t_student;
2、显示rownum[oracle分配的]
SQL> select a1.*, rownum rn from (select * from t_student) a1;
3、用的二分的一种机制
SQL> select a1.*, rownum rn from (select * from t_student) a1 where rownum < 4 and rownum > 1;对不起在oracle中rownum只认一次 行不通
正确方式:select * from (select a1.*, rownum rn from (select * from t_student) a1 where rownum < 4) where rn >= 2 ; 要指定查询列只需要修改红色部分
4、几个查询的变化:
A、要指定查询列只需要修改红色部分
B、排序同上修改SQL> select * from (select a1.*, rownum rn from (select stu.* , rownum rn1 from t_student stu order by stu.salary desc) a1 where rn1 < 4) where rn >= 2 ;
查询结果创建新表:
create table ss (VALUE_ID, VAR_NAME,CLASS_ID) as (select VALUE_ID, VAR_NAME,CLASS_ID from t_student);
create table ss as (select * from t_student);(复制整个表和数据)
合并查询:比and、or这些操作快很多
1、union 取并集 select * from t_student where class_id = 2 union select * from t_student where value_id = 3;去掉重复部分
2、union all 不去掉重复的记录
3、intersect 取交集
4、minus取差集
创建新的数据库
1、使用工具:数据库配置工具
2、使用命令手工创建
Java编程操作oracle数据库使用jdbcodbc(不能操作连接远程只能本地),jdbc(能操作远程oracle数据库)使用sql包进行sql操作。
只读事务:
Set transaction read only;当前用户使用了只读事务,那么这个用户就只能查询到当前时刻的数据。
Sql函数:
1、字符函数
lower(char)/upper(char):将字符串转换为小/大写
length(char)、substr(char, m, n)取子串
首字母变小写其他变大写:
SQL> select lower(substr(var_name, 1, 1)) || upper(substr(var_name, 2, length(var_name))) from t_student;
repalce()替换函数
2、数学函数
round(n, [m]):四舍五入保留m位小数
trunc(n, [m]):截取数字
mod(m, n):取余
Floor(n):返回小于或等于n的最大整数
Ceil():返回大于或等于的最小整数
3、日期函数
Oracle默认的日期格式是dd-mon-yy。
Sysdate:返回系统时间
add_months(d,n):在某个日期上加上n个月
6个月前出生的人
SQL> select * from t_student where sysdate > add_months(date_bir, 6);
last_months(month):返回指定日期在月份的最后一天
to_char():转换成指定格式的字符串
SQL> select * from t_student where sysdate > add_months(date_bir, 6);
系统函数:
1、sys_context()
参数:
terminal:当前会话客户所对应的终端标识符
language:语言
db_name:当前数据库名字
nls_date_formate:当前会话客户所对应的日期格式
Sessions_user:当前会话客户所对应的数据库名
Current_schema:当前客户所对应的默认方案名(一个用户对应一个方案)
Host:返回数据库所在的主机名
select sys_context('userenv', 'db_name') from t_student;
数据库管理:
1、sys用户:最高权限,拥有dba(3)、sysdba(1)、sysoper(2)角色的权限。包括oracle数据库的基表、动态视图。不能以normal登录。
2、system用户:包含次级数据,有dba、sysdba角色权限。如果以as sysdba就等同于sys用户
Sysdba和sysoper的区别
数据库的逻辑备份与恢复:
1、只能在open状态下才能进行。
2、导出备份:
导出表结构:
Exp userid=scott/tiger@myoral tables=(emp, dept) file=d:\e1.dmp rows=n
直接导出:在最后加 direct=y;
导出方案:
1、exp userid=scott/tiger@myoral owner=scott file=d:\e2.dmp
2、System可以导出除sys以外任何方案
exp userid=system/manager@myoral owner=(system,scott) file=d:\e2.dmp导出2个方案
导出数据库:
导入表:
导入方案:
数据字典:是数据库最重要的组成部分,包含数据库的一些系统信息,所有者是sys用户。
是只读表与视图的集合,在数据字典上只能执行查询,其维护与修改是有系统自动完成的。
就是有基表与动态视图(存放一些动态的数据)组成。数字字典视图类型user_xxx、all_xxx、dba_xxx三种类型。
动态性能视图:记载了例程启动后的相关信息
总结三者关系:
一个用户可以拥有多个角色,一个角色可以拥有多个权限。
select * from dba_roles;查询总共有多少个角色
select distinct p.privilege from dba_tab_privs p;对象权限种数
Oralce表空间和数据文件:
1、oracle的逻辑结构包括表空间-->段-->区-->块
2、表空间的作用:1、控制数据库占用的磁盘空间,其实就是能有效的使用磁盘空间
2、dba可以将不同的数据部署到不同的位置,这样有利于提高IO性能,备份和管理等操作。怎么可以提高IO性能?本来要去读很多数据文件,但是可以直接读表空间就可以把所有的表空间的数据文件一次读出来。
3、建立表空间需要特权用户或者dba用户才可以。
Create tbalespace (spacename) datafile'd:\*.dbf' size (<500M) uniform(区) size 20k;
4、使用表空间 creat table xxxx() tablespace (spacename);把表创建到指定的表空间,如果未指定就存在于system表空间中。
5、改变表空间的状态
表空间脱机/联机/只读:alter tablespace 表空间名 offline/online/read only;
6、删除表空间
Drop tablespace '表空间名' including contents and datafiles;
Ps:查询表空间信息在dba_tablespaces表中查询,
查询数据文件在哪个表空间可以在dba_data_files中查询。
7、扩展表空间
维护数据的完整性:三种方法:约束、触发器、应用程序。
约束:包括not null、unique、primary key(主键不能为空)、foreign key(外键)、check。
create table goods(goodsId char(8) primary key,
2 goodsname varchar2(30) not null,
3 price num(10,2) check (price > 0),
4 category varchar2(0),
5 provider varchar2(30));
如果建表时忘记了加约束,使用alter table (tablename) modify (alumname) not null;
alter table (tablename) add constraint (约束名) unique(alumname);
删除约束:
创建索引:
create index name_index on t_student(var_name, var_id);
创建自定义角色:
SQL> creat role myrole not identified;
授权要用系统管理system以后才可以授权
SQL> grant creat session to myrole with admin option
SQL> grant delete on tablename to myrole;
将角色授予给用户:
SQL> grant myrole to username;
SQL> Drop role rolename;
Java程序连接数据库实例
package com;
import java.sql.*;;
public class TestOracle {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Connection ct;
try{
//1、加载驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//2、得到连接
ct = DriverManager.getConnection("jdbc:oracle:thin:@10.153.98.18:1521:SZQX1","szidc","pwdidc");
//3、开始sql操作
Statement sm = ct.createStatement();
ResultSet rs = sm.executeQuery("select * from t_student");
//4、将查询的结果打印出来
while(rs.next()){
System.out.println(rs.getString(2));
}
//关闭资源
rs.close();
sm.close();
ct.close();
}
catch (Exception e){
e.printStackTrace();
}
}
}
Pl/sql编程
1 create procedure hq_pro1 is
2 begin
3 insert into t_student values(6, '清清', 3, to_date('19890613', 'yyyymmdd'), 10000, 19);
4 end;
5 /
如果编译报错:show error;
如何调用该过程
1、exec 过程名 (参数1, 参数2.......);
2、call 过程名 (参数1, 参数2.......);
一个简单的块
SQL> --声明一个变量
1 declare v_name varchar2(100);
2 begin
3 select stu.var_name into v_name from t_student stu where stu.value_id = 2;
4 dbms_output.put_line('学生名字:' || v_name);
5 end;
6 /
如果一次查询到多行把值给v_name这样是会报错的
一个整体的类JAVA流程的块
--声明一个变量
declare v_name varchar2(100);
begin
--执行部分
select stu.var_name into v_name from t_student stu where stu.value_id = &no;
--在控制台显示
dbms_output.put_line('学生名字:' || v_name);
--例外处理
exception
when no_data_found then
dbms_output.put_line('该学生不存在');
end;
一个过程实例
create or replace procedure hq_pro1(no number) is
--声明一个变量
v_name varchar2(100);
begin
--执行部分
update t_student stu set stu.var_name = '鸡鸡' where stu.value_id = no;
select stu.var_name into v_name from t_student stu where stu.value_id = no;
--在控制台显示
dbms_output.put_line('学生名字:' || v_name);
--例外处理
exception
when no_data_found then
dbms_output.put_line('该学生不存在');
end;
在JAVA中调用
package com;
import java.sql.*;
public class TestOracle {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Connection ct;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
ct = DriverManager.getConnection("jdbc:oracle:thin:@10.153.98.18:1521:SZQX1", "szidc", "pwdidc");
CallableStatement cs = ct.prepareCall("{call hq_pro1(?)}");
cs.setInt(1, 2);
cs.execute();
cs.close();
ct.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
--创建函数实例
create function fun1(no number) return number is
ysal number(7, 2):=3000;
begin
select 12*nvl(stu.salary , 0) into ysal from t_student stu where stu.value_id = no;
dbms_output.put_line('年工资=' || ysal);
return ysal;
end;
--在pl\sql中执行
SQL> var salary number ;
SQL> call fun1(2) into:salary;
--在java中调用
select fun1(2) from dual;
通过rs.getInt(1)获得返回值
--创建一个包
create package package_1 is
--声明该包有一个过程和一个函数
procedure hq_pro1(no number);
function fun1(no number) return number;
end;
--给包实现包体
create package body package_1 is
hq_pro1的实现部分
.....
Fun1的实现部分
.....
End;
调用包里面的函数or过程记得call 包名.函数名(参数)
开终端显示:
SQL> set serveroutput on;
2、--创建表的组合变量类型
declare
--定义一个类似数组的表组合类型sp_tab_type,以整数作为下标
type sp_tab_type is table of t_student.var_name%type index by binary_integer;--以整数作为下标
--使用上面类型定义变量
sp_table sp_tab_type;
begin
select var_name into sp_table(0) from t_student where value_id = 2;
dbms_output.put_line('二班学生的名字:' || sp_table(0));
end;
--建一个包里面包含一个游标类型,就类似于java中的类
create or replace package test_package AS
type test_cursr is ref cursor;
end test_package;
--创建使用这个包中包体内容的过程
create or replace procedure test_procedure(v_class_id number,sp_cursor out test_package.test_cursr ) is
begin
open sp_cursor for select stu.var_name from t_student stu where stu.class_id = v_class_id;
end;
参照变量:
declare
--定义一个游标类型
type sp_stu_cursor is ref cursor;
--定义一个游标类型的变量
test_cursor sp_stu_cursor;
v_name t_student.var_name%type;
v_id t_student.value_id%type;
--执行
begin
open test_cursor for select stu.value_id, stu.var_name from t_student stu where stu.class_id = 2;
--循环
(while可用来加条件)loop
--取出游标中的内容
fetch test_cursor into v_id, v_name;
--退出循环条件
exit when test_cursor%notfound;
dbms_output.put_line('id号:' || v_id || ' 学生名字:' || v_name);
end loop;
end;
--游标的另外一种定义方法
declare
myrecord t_student%rowtype;
cursor tab_cur(v_id number) is select * from t_student t where t.value_id = v_id;
begin
open tab_cur(1);
loop
fetch tab_cur into myrecord;
exit when tab_cur%notfound ;
dbms_output.put_line(myrecord.value_id ||' , '||myrecord.var_name);
end loop;
close tab_cur;
end;
Goto语句
--编写一个分页过程,输入乘数参数表名、每页记录数、当前页,返回总记录数、总页数、结果集
--创建一个包,包含一个游标类型
create or replace package result_set as
type table_cursor_type is ref cursor;
end result_set;
--创建过程
create or replace procedure pro_page
(v_tab_name in varchar2,
v_page_record in number,
v_cur_page in number,
v_records out number,
v_pages out number,
res_cur out result_set.table_cursor_type) is
--定义变量
v_sql varchar2(1000);
v_begin number:=(v_page_record-1)*v_cur_page+1;--起始行数
v_end number:=v_page_record*v_cur_page;--结束行数
--执行部分
begin
--拼接sql语句,分页语句
v_sql:= 'select * from (select * from (select stu1.*, rownum rn from '||v_tab_name
||' stu1) stu2 where stu2.rn > '||v_begin
||') where rn <= '||v_end;
--把执行结果放到游标变量中
open res_cur for v_sql;
--拼接sql
v_sql:='select count(*) from'||v_tab_name;
--执行拼接好的sql语句
execute immediate v_sql into v_records;
--注意取模不能用%
if mod(v_records, v_cur_page) = 0 then
v_pages:=v_records/v_cur_page;--不能空格
else
v_pages:=v_records/v_cur_page+1;
end if;
--关闭游标
close res_cur;
end;
declare
cursor mycur is
select stu.var_name, cls.class_name from t_student stu ,t_class cls
where stu.class_id = 2 and stu.class_id = cls.class_id for update;
v_myrecord t_student%rowtype;
v_myclass t_class.class_name%type;
begin
open mycur;
loop
fetch mycur into v_myrecord.var_name, v_myclass;
exit when mycur%notfound;
--视图的内容是改了是不会保存的,利用游标为判断条件
update t_student stu set stu.class_id = 1 where current of mycur;
dbms_output.put_line('名字: '||v_myrecord.var_name||'班级: '||v_myclass);
end loop;
end;
游标的隐式游标
例外:预定义例外、非预定义例外、自定义例外
预定义例外:
No_data_found
declare v_name varchar2(100);
begin
select stu.var_name into v_name from t_student stu where stu.value_id = &no;
dbms_output.put_line('学生名字:' || v_name);
--例外处理
exception
when no_data_found then
dbms_output.put_line('该学生不存在');
end;
No_case_found
declare
v_sal t_student.salary%type;
begin
select stu.salary into v_sal from t_student stu where stu.value_id=&nop;
case
when v_sal<1000 then
dbms_output.put_line('穷人');
when v_sal<2000 then
dbms_output.put_line('中资');
end case;
exception
when case_not_found then
dbms_output.put_line('你们是富人');
end; 在for循环出再次打开
自定义例外:
declare
myexcp exception;
begin
update t_student stu set stu.salary = stu.salary + 1000 where stu.value_id = &no;
--这是表示没有update
if sql%notfound then
--触发例外
raise myexcp;
end if;
exception
when myexcp then
dbms_output.put_line('没有更新');
end;
视图:
单表:create view myview as select * from t_student stu where stu.salary >3000;
双表:create or replace view myview1 as select stu.*, cls.class_name from t_student stu, t_class cls where stu.salary >3000 and cls.class_id = stu.class_id;
同义词:就是建立目标的一个别名。
公共:所有用户都可以使用
私有的:仅仅可以当前用户使用
Create or replace synonym stu for szidc.dept;
触发器
行级触发器
--创建一个删除触发器
create or replace trigger del_trig
after delete on t_class for each row
begin
delete from t_student where class_id = :old.class_id;
end del_trig;
触发器中常用的2个内存表,是增、删、改三个操作的暂存缓存
--更新操作触发器实例
create or replace trigger update_trig
after update of class_id on t_class for each row
begin
update t_student set class_id = :new.class_id where class_id = :old.class_id;
end;
触发器中不可以写rollback;那如果我们需要回退呢?
比如我们不允许删除某个记录,但是又不能回滚怎么办?
--抛出一个应用错误来实现
create or replace trigger del_trig
after delete on t_class for each row
begin
if :old.class_id = 2 then
raise_application_error('-20000', '不允许删除此记录');
end if;
end del_trig;
语句级触发器
不仅仅再是对某一行发生改变是做处理,而是只要你有某个动作就触发处理过程
create or replace trigger stu_trig
after delete or insert or update on t_student
begin
if deleting then
insert into log_tab values('删除成功!');
elsif inserting then
insert into log_tab values('插入成功!');
else
insert into log_tab values('更新成功!');
end if;
end;
--用触发器实现序列的功能
create or replace trigger stu_trig
before insert on t_student (for each row)--可以行级也可以语句级
declare
lid t_student.value_id%type;
begin
select max(value_id) into lid from t_student;
:new.value_id := lid + 1;
end;
替换触发器--只能操作视图
create or replace trigger myview_trig
instead of insert on v_myview for each row
Begin
Insert into t_student values(:new.value_id, :new.var_name, :new.class_id, :new.date_bir, :new.salary);
insert into t_class values(:new.class_id, :new.class_name) ;
end;
INSTEAD OF 触发器更新视图 :
--创建一个视图
Create or replace view company_phone_book as
Select first_name||', '||last_name name, email, phone_number,
employee_id emp_id
From hr.employees;
尝试更新email和name
update hr.company_phone_book
set name='Chen1, Donny1'
where emp_id=100
create or replace trigger update_name_company_phone_book
INSTEAD OF
Update on hr.company_phone_book
Begin
Update hr.employees
Set employee_id=:new.emp_id,
First_name=substr(:new.name, instr(:new.name,',')+2),
last_name= substr(:new.name,1,instr(:new.name,',')-1),
phone_number=:new.phone_number,
email=:new.email
where employee_id=:old.emp_id;
end;
4、 系统事件触发器
系统事件:数据库启动、关闭,服务器错误
create trigger ad_startup
after startup
on database
begin
-- do some stuff
end;
/
alter trigger <trigger_name> disable;
alter trigger <trigger_name> enable;
事务处理:
在触发器中,不能使用commit / rollback
因为ddl语句具有隐式的commit,所以也不允许使用
详细出处参考:http://www.jb51.net/article/18252.htm