這是我第一次寫博客,主要是記錄下自己這半個多月以來的學習筆記,以備以后可以隨時查看。
首先就是安裝Oracle的問題的,我系統是Win7 64位的,出現各種問題郁悶得不行,最終安裝個Oracle10203_vista_w2k8_x86_client客戶端連接公司的服務器暫時先用着吧,如果需要使用Odbc則需在C:\Windows\SysWOW64\odbcad32.exe上的系統DSN中添加Odbc的驅動管理,選擇Oracle in OraClient10g_home1,有很多警告框的不用管它,Data Source Name的名稱是Odbc連接字符串中的DSN名稱,其他的就不羅嗦了。
安裝完客戶端就安裝PLSQL+Developer9.0.2來操作數據庫了,默認是英文的,只要把Chinese.lang文件放到pl/sql安裝目錄下,再Tools->Preferences->Appearance的Language里選擇Chinese.lang就可以了,為了能更加快速的找到Tables等文件夾的信息,隨便把工具->瀏覽器文件夾中的Tables、Procedures、Indexes、Functions、Triggers、Views、Sequences、Tablespaces、Packages、Roles、Users移到最上面並將顏色設為藍色,把工具->瀏覽器過濾器中的My objects設為默認,最后按照自己的習慣,把窗口的位置調整下,選擇窗口->保存版面,好了,大功告成了。
現在開始Oracle的學習了,Oracle跟SQL Server很大的一個不同點就是Oracle使用表空間這一個概念,我感覺表空間就類似SQL Server的一個數據庫了,然后Oracle中沒有SQL Server中的自增這一概念,不過可以使用Sequences代替,使用方法是:
1 CREATE SEQUENCE Seq_test 2 3 INCREMENT BY 1 -- 每次加幾個 4 START WITH 1 -- 從1開始計數 5 NOMAXVALUE -- 不設置最大值 6 NOCYCLE -- 一直累加,不循環 7 CACHE 10;
創建完之后就可以直接使用了
insert tb_Test(tId,tName) values(Seq_test.NEXTVAL,'測試'); select Seq_test.CURRVAL from dual; --返回當前的序列值
注意第一次NEXTVAL返回的是初始值;隨后的NEXTVAL會自動增加你定義的INCREMENT BY值,然后返回增加后的值。CURRVAL 總是返回當前SEQUENCE的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否則會出錯。而dual是一個偽表,不用自己創建的,只是為了操作上的方便而存在的,例如select返回的變量,入日期等。
使用Oracle最開始就是先創建表空間跟用戶了
1 -----------------創建表空間----------------------------- 2 create tablespace DBTest_tbs --一般建N個存數據的表空間和一個索引空間 3 datafile 'E:\Oracle\oradata\DBTest_tbs\Ordering.dbf' --表空間的路徑 4 size 100M --大小 5 autoextend on --自動增長 6 --定義大小的命令 7 next 1M maxsize 1000M extent management local; 8 --刪除表空間 9 --drop tablespace DBTest_tbs including contents and datafiles cascade constraints; 10 --創建臨時表空間 11 create temporary tablespace DBTest_temp 12 tempfile 'E:\Oracle\oradata\DBTest_tbs\Temp.dbf' size 100M autoextend on next 1M maxsize 1000M extent management local; 13 --創建索引表空間 14 create tablespace DBTest_index 15 datafile 'E:\Oracle\oradata\DBTest_tbs\Index.dbf' size 100M extent management local;
然后就是創建用戶了
1 create user DBTest_user identified by 441821 2 default tablespace DBTest_tbs 3 temporary tablespace DBTest_temp; 4 --授權 5 --一般授予的權限:create session,create table,unlimited tablespace; 6 --對象權限:用戶創建的表屬於用戶自己的,想給被所有人用,則grant all on table to public; 7 --可以指定列的權限:grant update(name) on tb to DBTest_user; 8 grant connect,resource,dba to DBTest_user; 9 --收權 10 Revoke dba from DBTest_user;
創建完用戶並授予相應的權限就可以創建表之類的DDL操作了,具體語法跟T-SQL語法差不多的,注意一下Oracle的數據類型就可以了。
然后記錄下PL/SQL的基本使用方法:
1 ----------------------PL/SQL語句基礎------------------------ 2 --merge into的用法,通過MERGE語句,根據一張表或子查詢的連接條件對另外一張表進行查詢, 3 --連接條件匹配上的進行UPDATE,無法匹配的執行INSERT,效率要高於INSERT+UPDATE 4 merge into fzq1 aa --fzq1表是需要更新的表 5 using fzq bb -- 關聯表 6 on (aa.id=bb.id) --關聯條件 7 when matched then --匹配關聯條件,作更新處理 8 update set 9 aa.chengji=bb.chengji+1, 10 aa.name=bb.name --此處只是說明可以同時更新多個字段。 11 when not matched then --不匹配關聯條件,作插入處理。如果只是作更新,下面的語句可以省略。 12 insert values( bb.id, bb.name, bb.sex,bb.kecheng,bb.chengji); 13 14 --pl/sql語句塊 15 declare 16 ecount tb_food.count%Type; --定義表中的字段類型 17 eno number; 18 eresult number; 19 food tb_food%rowtype; --定義表類型,只能存儲一條記錄 20 begin 21 eno:=&no; --要用戶輸入信息 22 select count into ecount from tb_food where foodID='F001'; 23 select * into food from tb_food where foodID='F001'; 24 eresult:=ecount/eno; 25 dbms_output.put_line(ecount||'/'||eno||'='||eresult); 26 dbms_output.put_line(food.FoodID); 27 exception --捕捉異常 28 when zero_divide then 29 dbms_output.put_line('error'); 30 end; 31 / --執行語句 32 33 --loop循環 34 declare 35 cou number; 36 begin 37 cou:=1; 38 loop 39 dbms_output.put_line('cou='||cou); 40 exit when cou>10; 41 cou:=cou+1; 42 end loop; 43 end; 44 / 45 46 --while循環 47 declare 48 cou number; 49 begin 50 cou:=1; 51 while(cou<10) 52 loop 53 dbms_output.put_line('cou='cou); 54 cou:=cou+1; 55 end loop; 56 end; 57 / 58 59 --for循環 60 declare 61 cou number; 62 begin 63 for cou in 1..10 loop 64 dbms_output.put_line('cou='||cou); 65 end loop; 66 end; 67 / 68 69 --if...else語句 70 declare 71 cou number; 72 begin 73 cou:=1; 74 if cou>10 then 75 dbms_output.put_line('cou='||cou); 76 else 77 dmbs_ouput.put_line(條件不滿足); 78 end if; 79 end; 80 / 81 82 --goto語句 83 declare 84 eID tb_food.FoodID%Type; 85 ecount tb_food.Count%Type; 86 begin 87 eID:=%ne; 88 select count into ecount from tb_food where FoodID=eID; 89 if ecout>5 then 90 goto po1; 91 else 92 goto po2; 93 end if; 94 <<po1>>dbms_output.put_line('數量大於5'); 95 <<po2>>dbms_output.put_line('數量小於等於5'); 96 end; 97 /
注意:PL/SQL中的賦值是使用":="代替的,而字符串連接則使用"||"代替。
創建函數的方法:
1 create or replace function myfun(fid tb_food.foodID%type) 2 return number 3 as 4 Fname narchar2; 5 select FoodName into Fname from tb_food where FoodId=fid; 6 return Fname; 7 end; 8 / 9 --調用函數 10 select myfun('F001') from dual;
創建存儲過程的方法:
1 create or replace procedure myproc 2 (fid in out tb_food.foodId%type) --帶值進帶值出 3 as 4 cou number; 5 v_id char; 6 begin 7 select count(*) into cou from tb_food where foodId=fid; 8 if cou=0 then --不存在ID 9 insert into tb_food values(fid,'名稱'); 10 else --已存在,不能插入 11 fid:=-1; 12 end if; 13 end; 14 / 15 16 --執行存儲過程 17 declare 18 fid tb_food.foodid%type; 19 begin 20 fid:='F001'; 21 myproc(fid); 22 dbms_output.put_line(fid); 23 end; 24 / 25 26 --刪除存儲過程 27 drop procedure myproc;
注意:存儲過程返回數據集不像SQL Server的一樣直接select就可以了,需要使用游標來存儲數據集,具體使用方法如下:
1 --帶結果集的存儲過程 2 --創建包 3 create or replace package pak_test 4 is type refcursor is ref cursor; 5 procedure pro_test(cur out refcursor); 6 end; 7 / 8 --創建包體 9 create or replace package body pak_test is 10 procedure pro_test 11 (cur out refcursor) 12 is 13 begin 14 open cur for 15 select * from tb_food; 16 return; 17 end; 18 end; 19 / 20 21 --執行存儲過程 22 declare 23 v_cur pak_test.refcursor; 24 v_food tb_food%rowtype; 25 begin 26 pak_test.pro_test(v_cur); 27 FETCH v_cur INTO v_food; 28 WHILE v_cur%FOUND LOOP 29 DBMS_OUTPUT.PUT_LINE(v_food.FoodID); 30 FETCH v_cur INTO v_food; 31 END LOOP; 32 end; 33 /
創建觸發器的方法:
1 --------觸發器------------ 2 --觸發器不能從觸發器所對應的基本中讀取數據,否則執行時會出錯 3 --Before語句觸發器 4 create or replace trigger tr_src_emp 5 before insert or update or delete on emp 6 begin 7 if to_char(sysdate,'DY','nls_date_language=AMERICAN') in('SAT','SUN') then 8 raise_application_error(-20001,'工作人員不能在周末改變雇員信息'); 9 end if; 10 end; 11 / 12 13 --Bofre行觸發器,沒作用一行就觸發一次觸發器 14 create or replace trigger tr_emp_sal 15 before update of sal on emp 16 for each row 17 begin 18 if:new.sal<:old.sal then 19 raise_application_error(-20010,'員工工資不能低於原有工資'); 20 end if; 21 end; 22 / 23 24 --限制行觸發器 25 create or replace trigger tr_sal_sal 26 after update of sal on emp 27 for each row 28 when (old.job='salesman') 29 declare 30 v_temp int; 31 begin 32 select count(*) into v_temp from emp where name=:old.name; 33 if v_temp=0 then 34 insert into emp values(:old.name,:old.sal,:new.sal); 35 else 36 update emp set oldsal=:old.sal,newsal=:new.sal where name=:old.name; 37 end if; 38 end; 39 /
動態執行SQL語句的方法:
1 ----------動態執行SQL語句------------ 2 declare 3 sql_stmt varchar2(200); --動態SQL語句 4 kind_name nvarchar2(50):='測試'; 5 kind_id tb_foodKind.Kindid%type:='55'; 6 cur_foodkind tb_foodKind%rowtype; 7 begin 8 --無子句的execute immediate 9 execute immediate 'create table t_test(id number)'; 10 --using子句的execute immediate 11 sql_stmt:='insert into tb_foodKind(kindid,KindName) values(:1,:2)'; 12 execute immediate sql_stmt using kind_id,kind_name; 13 --into子句的execute immediate 14 --sql_stmt:='select * from tb_foodkind where kindID=:1'; 15 execute immediate sql_stmt into cur_foodkind using kind_id; 16 dbms_output.put_line(cur_foodkind.kindid); 17 --returning into子句的execute immediate 18 --returning 可以把操作影響行中的數據返回 19 sql_stmt:='update tb_foodkind set kindname=''西瓜'' where kindid=:1 returning kindname into :2'; 20 execute immediate sql_stmt using kind_id returning into kind_name; 21 dbms_output.put_line(kind_name); 22 end; 23 /
最后,講一下在C#中操作Oracle數據庫,我使用的是Odbc連接數據庫的,連接字符串是"DSN=testdb;uid=dbtest;pwd=dbtest",DSN就是之前添加的ODBC驅動名稱,其他的也就跟Sql的差不多了,還需要注意的是使用OdbcParameter參數的SQL語句中,參數的要用"?"作為替代符,例如"select * from tb_foodKind where KindID=?",而且如果想使用ODBC來調用存儲過程,存儲過程中如果存在參數,則需要使用cmd.CommandText = "{call pro_AddPackageDetail(?,?,?,?,?)}"這樣的格式才能執行,如果沒有參數則可以直接使用存儲過程名稱。
好了,暫時就先記錄到這里了,如果以后有繼續學到更多的知識再來補充。
