這部分是我在看視頻和看《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