这是我第一次写博客,主要是记录下自己这半个多月以来的学习笔记,以备以后可以随时查看。
首先就是安装Oracle的问题的,我系统是Win764位的,出现各种问题郁闷得不行,最终安装个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代替,使用方法是:
1CREATESEQUENCE Seq_test23INCREMENTBY1--每次加几个4STARTWITH1--从1开始计数5NOMAXVALUE--不设置最大值6NOCYCLE--一直累加,不循环7CACHE10;
创建完之后就可以直接使用了
inserttb_Test(tId,tName)values(Seq_test.NEXTVAL,'测试');selectSeq_test.CURRVALfromdual;--返回当前的序列值
注意第一次NEXTVAL返回的是初始值;随后的NEXTVAL会自动增加你定义的INCREMENT BY值,然后返回增加后的值。CURRVAL 总是返回当前SEQUENCE的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否则会出错。而dual是一个伪表,不用自己创建的,只是为了操作上的方便而存在的,例如select返回的变量,入日期等。
使用Oracle最开始就是先创建表空间跟用户了
1-----------------创建表空间-----------------------------2createtablespace DBTest_tbs--一般建N个存数据的表空间和一个索引空间3datafile'E:\Oracle\oradata\DBTest_tbs\Ordering.dbf'--表空间的路径4size 100M--大小5autoextendon--自动增长6--定义大小的命令7next1M maxsize 1000M extent management local;8--删除表空间9--drop tablespace DBTest_tbs including contents and datafiles cascade constraints;10--创建临时表空间11createtemporarytablespace DBTest_temp12tempfile'E:\Oracle\oradata\DBTest_tbs\Temp.dbf'size 100M autoextendonnext1M maxsize 1000M extent management local;13--创建索引表空间14createtablespace DBTest_index15datafile'E:\Oracle\oradata\DBTest_tbs\Index.dbf'size 100M extent management local;
然后就是创建用户了
1createuserDBTest_user identifiedby4418212defaulttablespace DBTest_tbs3temporarytablespace DBTest_temp;4--授权5--一般授予的权限:createsession,create table,unlimited tablespace;6--对象权限:用户创建的表属于用户自己的,想给被所有人用,则grant all on table to public;7--可以指定列的权限:grant update(name) on tb to DBTest_user;8grantconnect,resource,dbatoDBTest_user;9--收权10RevokedbafromDBTest_user;
创建完用户并授予相应的权限就可以创建表之类的DDL操作了,具体语法跟T-SQL语法差不多的,注意一下Oracle的数据类型就可以了。
然后记录下PL/SQL的基本使用方法:
1----------------------PL/SQL语句基础------------------------2--merge into的用法,通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,3--连接条件匹配上的进行UPDATE,无法匹配的执行INSERT,效率要高于INSERT+UPDATE4mergeintofzq1 aa--fzq1表是需要更新的表5using fzq bb--关联表6on(aa.id=bb.id)--关联条件7whenmatchedthen--匹配关联条件,作更新处理8updateset9aa.chengji=bb.chengji+1,10aa.name=bb.name--此处只是说明可以同时更新多个字段。11whennotmatchedthen--不匹配关联条件,作插入处理。如果只是作更新,下面的语句可以省略。12insertvalues( bb.id, bb.name, bb.sex,bb.kecheng,bb.chengji);1314--pl/sql语句块15declare16ecount tb_food.count%Type;--定义表中的字段类型17enonumber;18eresultnumber;19food tb_food%rowtype;--定义表类型,只能存储一条记录20begin21eno:=&no;--要用户输入信息22selectcountintoecountfromtb_foodwherefoodID='F001';23select*intofoodfromtb_foodwherefoodID='F001';24eresult:=ecount/eno;25dbms_output.put_line(ecount||'/'||eno||'='||eresult);26dbms_output.put_line(food.FoodID);27exception--捕捉异常28whenzero_dividethen29dbms_output.put_line('error');30end;31/--执行语句3233--loop循环34declare35counumber;36begin37cou:=1;38loop39dbms_output.put_line('cou='||cou);40exitwhencou>10;41cou:=cou+1;42endloop;43end;44/4546--while循环47declare48counumber;49begin50cou:=1;51while(cou<10)52loop53dbms_output.put_line('cou='cou);54cou:=cou+1;55endloop;56end;57/5859--for循环60declare61counumber;62begin63forcouin1..10loop64dbms_output.put_line('cou='||cou);65endloop;66end;67/6869--if...else语句70declare71counumber;72begin73cou:=1;74ifcou>10then75dbms_output.put_line('cou='||cou);76else77dmbs_ouput.put_line(条件不满足);78endif;79end;80/8182--goto语句83declare84eID tb_food.FoodID%Type;85ecount tb_food.Count%Type;86begin87eID:=%ne;88selectcountintoecountfromtb_foodwhereFoodID=eID;89ifecout>5then90gotopo1;91else92gotopo2;93endif;94<<po1>>dbms_output.put_line('数量大于5');95<<po2>>dbms_output.put_line('数量小于等于5');96end;97/
View Code
注意:PL/SQL中的赋值是使用":="代替的,而字符串连接则使用"||"代替。
创建函数的方法:
1createorreplacefunctionmyfun(fid tb_food.foodID%type)2returnnumber3as4Fname narchar2;5selectFoodNameintoFnamefromtb_foodwhereFoodId=fid;6returnFname;7end;8/9--调用函数10selectmyfun('F001')fromdual;
创建存储过程的方法:
1createorreplaceproceduremyproc2(fidinout tb_food.foodId%type)--带值进带值出3as4counumber;5v_idchar;6begin7selectcount(*)intocoufromtb_foodwherefoodId=fid;8ifcou=0then--不存在ID9insertintotb_foodvalues(fid,'名称');10else--已存在,不能插入11fid:=-1;12endif;13end;14/1516--执行存储过程17declare18fid tb_food.foodid%type;19begin20fid:='F001';21myproc(fid);22dbms_output.put_line(fid);23end;24/2526--删除存储过程27dropproceduremyproc;
注意:存储过程返回数据集不像SQL Server的一样直接select就可以了,需要使用游标来存储数据集,具体使用方法如下:
1--带结果集的存储过程2--创建包3createorreplacepackage pak_test4istype refcursorisrefcursor;5procedurepro_test(cur out refcursor);6end;7/8--创建包体9createorreplacepackage body pak_testis10procedurepro_test11(cur out refcursor)12is13begin14opencurfor15select*fromtb_food;16return;17end;18end;19/2021--执行存储过程22declare23v_cur pak_test.refcursor;24v_food tb_food%rowtype;25begin26pak_test.pro_test(v_cur);27FETCHv_curINTOv_food;28WHILEv_cur%FOUND LOOP29DBMS_OUTPUT.PUT_LINE(v_food.FoodID);30FETCHv_curINTOv_food;31ENDLOOP;32end;33/
创建触发器的方法:
1--------触发器------------2--触发器不能从触发器所对应的基本中读取数据,否则执行时会出错3--Before语句触发器4createorreplacetriggertr_src_emp5beforeinsertorupdateordeleteonemp6begin7ifto_char(sysdate,'DY','nls_date_language=AMERICAN')in('SAT','SUN')then8raise_application_error(-20001,'工作人员不能在周末改变雇员信息');9endif;10end;11/1213--Bofre行触发器,没作用一行就触发一次触发器14createorreplacetriggertr_emp_sal15beforeupdateofsalonemp16foreach row17begin18if:new.sal<:old.salthen19raise_application_error(-20010,'员工工资不能低于原有工资');20endif;21end;22/2324--限制行触发器25createorreplacetriggertr_sal_sal26afterupdateofsalonemp27foreach row28when(old.job='salesman')29declare30v_tempint;31begin32selectcount(*)intov_tempfromempwherename=:old.name;33ifv_temp=0then34insertintoempvalues(:old.name,:old.sal,:new.sal);35else36updateempsetoldsal=:old.sal,newsal=:new.salwherename=:old.name;37endif;38end;39/
动态执行SQL语句的方法:
1----------动态执行SQL语句------------2declare3sql_stmtvarchar2(200);--动态SQL语句4kind_name nvarchar2(50):='测试';5kind_id tb_foodKind.Kindid%type:='55';6cur_foodkind tb_foodKind%rowtype;7begin8--无子句的execute immediate9executeimmediate'create table t_test(id number)';10--using子句的execute immediate11sql_stmt:='insert into tb_foodKind(kindid,KindName) values(:1,:2)';12executeimmediate sql_stmt using kind_id,kind_name;13--into子句的execute immediate14--sql_stmt:='select * from tb_foodkind where kindID=:1';15executeimmediate sql_stmtintocur_foodkind using kind_id;16dbms_output.put_line(cur_foodkind.kindid);17--returning into子句的execute immediate18--returning 可以把操作影响行中的数据返回19sql_stmt:='update tb_foodkind set kindname=''西瓜''where kindid=:1 returning kindname into :2';20executeimmediate sql_stmt using kind_id returningintokind_name;21dbms_output.put_line(kind_name);22end;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(?,?,?,?,?)}"这样的格式才能执行,如果没有参数则可以直接使用存储过程名称。
好了,暂时就先记录到这里了,如果以后有继续学到更多的知识再来补充。