仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1108|回复: 7
打印 上一主题 下一主题

[学习教程] MYSQL网站制作之从SQL SERVER 向ORACLE 8迁徙的手艺完成...

[复制链接]
金色的骷髅 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 22:40:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
由于在MySQL中有如此众多的额外功能可选,诸如存储引擎等,你可以选择最适合你公司的一个,或者尝试选用多个引擎。MySQL开始非常小巧,但是可以随着公司的成长而不断地变强大。oracle|server
不晓得从那里失掉这个文档,有效就放下去了-gwb


数据库端SQL语法的迁徙
以下为经常使用的SQL语法迁徙,包含数据范例、ID列向SEQUENCE迁徙、表(主键、外键、CHECK、UNIQUE、DEFAULT、INDEX)、游标、存储历程、函数、触发器、经常使用SQL语法与函数几个方面,思索SQLSERVER的实践情形,没有触及ORACLE独有的PACKAGE、EXCEPTION等。在以下的形貌中,将SQLSERVER的TRANSACT-SQL简称为T-SQL。在ORACLE中,其语法集称为PL/SQL。


<一>数据范例的迁徙
<1>、ORACLE端语法申明

在ORACLE中,剖析其数据范例,大抵可分为数字、字符、日期工夫和特别四年夜类。个中,数字范例有NUMBER;字符范例有CHAR与VARCHAR2;日期工夫范例只要DATE一种;除此以外,LONG、RAW、LONGRAW、BLOB、CLOB和BFILE等数据范例都可视为特别数据范例。



<2>、SQLSERVER端语法申明

在SQLSERVER中,参照下面对ORACLE的分别,数据范例也大抵可分为数字、字符、日期工夫和特别四年夜类。数字范例又可分为准确数值、近似数值、整数、二进制数、泉币等几类,个中,准确数值有DECIMAL[(P[,S])]与NUMERIC[(P[,S])];近似数值有FLOAT[(N)];整数有INT、SMALLINT、TINYINT;二进制数有BINARY[(N)]、VARBINARY[(N)];泉币有MONEY、SMALLMONEY。字符范例有CHAR[(N)]与VARCHAR[(N)]。日期工夫范例有DATETIME、SMALLDATETIME。除此以外,BIT、TIMESTAMP、TEXT和IMAGE、BINARYVARING等数据范例都可视为特别数据范例。



<3>、从SQLSERVER向ORACLE的迁徙计划

对照ORACLE与SQLSERVER在数据范例上的分歧,当从SQLSERVER向ORACLE迁徙时,能够做以下调剂:



SQLSERVER

ORACLE

数字范例

DECIMAL[(P[,S])]

NUMBER[(P[,S])]

NUMERIC[(P[,S])]

NUMBER[(P[,S])]

FLOAT[(N)]

NUMBER[(N)]

INT

NUMBER

SMALLINT

NUMBER

TINYINT

NUMBER

MONEY

NUMBER[19,4]

SMALLMONEY

NUMBER[19,4]

字符范例

CHAR[(N)]

CHAR[(N)]

VARCHAR[(N)]

VARCHAR2[(N)]

日期工夫范例

DATETIME

DATE

SMALLDATETIME

DATE

别的

TEXT

CLOB

IMAGE

BLOB

BIT

NUMBER(1)

办法:

公司原体系中的Money用于金额时转换用number(14,2);用于单价时用number(10,4)取代;
<二>ID列向SEQUENCE迁徙
<1>、SQLSERVER端语法申明

在SQLSERVER中,能够将数据库中的某一字段界说为IDENTITY列以做主键辨认,如:

jlbhnumeric(12,0)identity(1,1)/*纪录编号字段*/

CONSTRAINTPK_tbl_examplePRIMARYKEYnonclustered(jlbh)/*主键束缚*/

在这里,jlbh是一个ID列,在向具有该列的表拔出纪录时,体系将从1入手下手以1的步长主动对jlbh的值举行保护。



<2>、ORACLE端语法申明

但在ORACLE中,没有如许的ID列界说,而是接纳另外一种办法,即创立SEQUENCE。

如:

/*--1、创立各利用区域编码表--*/

droptableLT_AREA;

createtableLT_AREA

(

area_idnumber(5,0)NOTNULL,/*区域编码*/

area_namevarchar2(20)NOTNULL,/*区域称号*/

constraintPK_LT_AREAPRIMARYKEY(area_id)

);



/*--2、创立SEQUENCE,将列area_id类ID化--*/

dropsequenceSEQ_LT_AREA;

createsequenceSEQ_LT_AREAincrementby1/*该SEQUENCE以1的步长递增*/

startwith1maxvalue99999;/*从1入手下手,最年夜增加到99999*/



/*--3、实践操纵时援用SEQUENCE的下一个值--*/

insertintoLT_AREA(area_id,area_name)values(SEQ_LT_AREA.NEXTVAL,深圳);

insertintoLT_AREA(area_id,area_name)values(SEQ_LT_AREA.NEXTVAL,广州);

insertintoLT_AREA(area_id,area_name)values(SEQ_LT_AREA.NEXTVAL,北京);



/*--4、新拔出一连三笔记录后,下一条语句运转后,‘上海’区域的area_id为4--*/

insertintoLT_AREA(area_id,area_name)values(SEQ_LT_AREA.NEXTVAL,上海);



<3>、从SQLSERVER向ORACLE的迁徙计划



依据以上剖析,当从SQLSERVER向ORACLE迁徙时,能够做以下调剂:

1、往失落建表语句中有关ID列的identity声明关头字;

2、创立SEQUENCE,将此SEQUENCE与需类ID化的列对应;

3、在INSERT语句中对响应列援用其SEQUENCE值:SEQUENCENAME.NEXTVAL

实践上,处置以下情况在ORACLE中接纳的办法为对有主动增加字段的表增添一拔出前触发器(详细材料见后“触发器”一节),以下:

CREATEORREPLACETRIGGERGenaerateAreaID

BEFOREINSERTONLT_AREA

FOREACHROW

SelectSEQ_LT_AREA.NEXTVALINTO:NEW.ID

FROMDUAL;

BEGIN

ENDGenaerateAreaID;

GenaerateAreaID实践上修正了伪纪录:new的area_id值。:new最有效的一个特征----当该语句真正被实行时,:new中的存储内容就会被利用。以是体系每次都能主动天生新的号码。
<三>表(主键、外键、CHECK、UNIQUE、DEFAULT、INDEX)
<1>、SQLSERVER端语法申明

有以下SQLSERVER语句:

/*------------------------创立employee表------------------------*/

IFEXISTS(SELECT1FROMSYSOBJECTSWHERENAME=‘employee’

ANDTYPE=‘U’)

DROPTABLEemployee

GO



CREATETABLEemployee

(

emp_idempid/*empid为用户自界说数据范例*/

/*创立自定名主键束缚*/

CONSTRAINTPK_employeePRIMARYKEYNONCLUSTERED

/*创立自定名CHECK束缚*/

CONSTRAINTCK_emp_idCHECK(emp_idLIKE

[A-Z][A-Z][A-Z][1-9][0-9][0-9][0-9][0-9][FM]or

emp_idLIKE[A-Z]-[A-Z][1-9][0-9][0-9][0-9][0-9][FM]),

/*CHECK束缚申明:EachemployeeIDconsistsofthreecharactersthat

representtheemployeesinitials,followedbyafive

digitnumberrangingfrom10000to99999andthenthe

employeesgender(MorF).A(hyphen)-isacceptable

forthemiddleinitial.*/

fnamevarchar(20)NOTNULL,

minitchar(1)NULL,

lnamevarchar(30)NOTNULL,



ss_idvarchar(9)UNIQUE,/*创立独一性束缚*/



job_idsmallintNOTNULL

DEFAULT1,/*设定DEFAULT值*/

job_lvltinyint

DEFAULT10,/*设定DEFAULT值*/

/*Entryjob_lvlfornewhires.*/

pub_idchar(4)NOTNULL

DEFAULT(9952)/*设定DEFAULT值*/

REFERENCESpublishers(pub_id),/*创立体系定名外键束缚*/

/*Bydefault,theParentCompanyPublisheristhecompany

towhomeachemployeereports.*/

hire_datedatetimeNOTNULL

DEFAULT(getdate()),/*设定DEFAULT值*/

/*Bydefault,thecurrentsystemdatewillbeentered.*/

CONSTRAINTFK_employee_jobFOREIGNKEY(job_id)

REFERENCESjobs(job_id)/*创立自定名外键束缚*/

)

GO



/*---------------------创立employee表上的index---------------------*/

IFEXISTS(SELECT1FROMsysindexes

WHEREname=emp_pub_id_ind)

DROPINDEXemployee.emp_pub_id_ind

GO



CREATEINDEXemp_pub_id_ind

ONemployee(pub_id)

GO



<2>、ORACLE端语法申明

在ORACLE真个语法以下:

/*----------------------创立employee表----------------------*/

DROPTABLEemployee;



CREATETABLEemployee

(

emp_idvarchar2(9)/*依据用户自界说数据范例的界说调剂为varchar2(9)*/

/*创立自定名主键束缚*/

CONSTRAINTPK_employeePRIMARYKEYNONCLUSTERED

/*创立自定名CHECK束缚*/

CONSTRAINTCK_emp_idCHECK(emp_idLIKE

[A-Z][A-Z][A-Z][1-9][0-9][0-9][0-9][0-9][FM]or

emp_idLIKE[A-Z]-[A-Z][1-9][0-9][0-9][0-9][0-9][FM]),

/*CHECK束缚申明:EachemployeeIDconsistsofthreecharactersthat

representtheemployeesinitials,followedbyafive

digitnumberrangingfrom10000to99999andthenthe

employeesgender(MorF).A(hyphen)-isacceptable

forthemiddleinitial.*/

fnamevarchar2(20)NOTNULL,

minitvarchar2(1)NULL,

lnamevarchar2(30)NOTNULL,



ss_idvarchar2(9)UNIQUE,/*创立独一性束缚*/



job_idnumber(5,0)NOTNULL

/*这里思索了SMALLINT的长度,也可调剂为number*/

DEFAULT1,/*设定DEFAULT值*/

job_lvlnumber(3,0)

/*这里思索了TINYINT的长度,也可调剂为number*/

DEFAULT10,/*设定DEFAULT值*/

/*Entryjob_lvlfornewhires.*/

pub_idvarchar2(4)NOTNULL

DEFAULT(9952)/*设定DEFAULT值*/

REFERENCESpublishers(pub_id),/*创立体系定名外键束缚*/

/*Bydefault,theParentCompanyPublisheristhecompany

towhomeachemployeereports.*/

hire_datedateNOTNULL

DEFAULTSYSDATE,/*设定DEFAULT值*/

/*这里,SQLSERVER的getdate()调剂为ORACLE的SYSDATE*/

/*Bydefault,thecurrentsystemdatewillbeentered.*/

CONSTRAINTFK_employee_jobFOREIGNKEY(job_id)

REFERENCESjobs(job_id)/*创立自定名外键束缚*/

);



/*--------------------创立employee表上的index--------------------*/

DROPINDEXemployee.emp_pub_id_ind;

CREATEINDEXemp_pub_id_indONemployee(pub_id);



<3>、从SQLSERVER向ORACLE的迁徙计划

对照这两段SQL代码,能够看出,在创立表及其主键、外键、CHECK、UNIQUE、DEFAULT、INDEX时,SQLSERVER与ORACLE的语法大抵不异,但时迁徙时要注重以下情形:

(1)Oracle界说表字段的default属性要紧跟字段范例以后,以下:

CreatetableMZ_Ghxx

(ghlxhnumberprimaykey,

rqdatedefaultsysdatenotnull,

….

)

而不克不及写成

CreatetableMZ_Ghxx

(ghlxhnumberprimaykey,

rqdatenotnulldefaultsysdate,

….

)

(2)T-SQL界说表布局时,假如触及到用默许工夫和默许修正职员,全体修正以下:

ZHXGRQDATEDEFAULTSYSDATENULL,

ZHXGRCHAR(8)DEFAULT‘FUTIAN’NULL,

(3)如表有identity定段,要先将其纪录上去,建完表以后,即刻建响应的序列和表触发器,并作为纪录。
<四>游标
<1>、SQLSERVER端语法申明

1、DECLARECURSOR语句

语法:

DECLAREcursor_name[INSENSITIVE][SCROLL]CURSOR

FORselect_statement

[FOR{READONLY|UPDATE[OFcolumn_list]}]

例:

DECLAREauthors_cursorCURSORFOR

SELECTau_lname,au_fname

FROMauthors

WHEREau_lnameLIKE‘B%’

ORDERBYau_lname,au_fname



2、OPEN语句

语法:

OPENcursor_name

例:

OPENauthors_cursor



3、FETCH语句

语法:

FETCH

[[NEXT|PRIOR|FIRST|LAST|ABSOLUTEn|RELATIVEn]

FROMcursor_name

[INTO@variable_name1,@variable_name2,…]

例:

FETCHNEXTFROMauthors_cursor

INTO@au_lname,@au_fname



4、CLOSE语句

语法:

CLOSEcursor_name

例:

CLOSEauthors_cursor



5、DEALLOCATE语句

语法:

DEALLOCATEcursor_name

例:

DEALLOCATEauthors_cursor



6、游标中的尺度轮回与轮回停止前提判别

(1)FETCHNEXTFROMauthors_cursorINTO@au_lname,@au_fname



(2)--Check@@FETCH_STATUStoseeifthereareanymorerowstofetch.

WHILE@@FETCH_STATUS=0

BEGIN

--Concatenateanddisplaythecurrentvaluesinthevariables.

PRINT"Author:"+@au_fname+""+@au_lname



--Thisisexecutedaslongasthepreviousfetchsucceeds.

FETCHNEXTFROMauthors_cursorINTO@au_lname,@au_fname

END



(3)CLOSEauthors_cursor

7、隐式游标

MSSqlServer中关于数据利用语句受影响的行数,有一个全局的变量:@@rowcount,实在它是一个隐式的游标,它纪录了上条数据利用语句所影响的行数,当@@rowcount小于1时,表时,前次没有找到相干的纪录,以下:

Updatestudentssetlastname=‘John’wherestudent_id=‘301’

If@@rowcount<1then

Insertintostudentsvalues(‘301’,’stdiv’,’john’,’996-03-02’)

暗示假如数据表中有学号为“301”的纪录,则修正其名字为“John”,假如找不到响应的纪录,则向数据库中拔出一条“John”的纪录。

8、示例:

--DeclarethevariablestostorethevaluesreturnedbyFETCH.

DECLARE@au_lnamevarchar(40),@au_fnamevarchar(20)



DECLAREauthors_cursorCURSORFOR

SELECTau_lname,au_fname

FROMauthors

WHEREau_lnameLIKE‘B%’

ORDERBYau_lname,au_fname



OPENauthors_cursor



--Performthefirstfetchandstorethevaluesinvariables.

--Note:Thevariablesareinthesameorderasthecolumns

--intheSELECTstatement.



FETCHNEXTFROMauthors_cursorINTO@au_lname,@au_fname



--Check@@FETCH_STATUStoseeifthereareanymorerowstofetch.

WHILE@@FETCH_STATUS=0



BEGIN

--Concatenateanddisplaythecurrentvaluesinthevariables.

PRINT"Author:"+@au_fname+""+@au_lname



--Thisisexecutedaslongasthepreviousfetchsucceeds.

FETCHNEXTFROMauthors_cursorINTO@au_lname,@au_fname

END



CLOSEauthors_cursor



DEALLOCATEauthors_cursor



<2>、ORACLE端语法申明

1、DECLARECURSOR语句

语法:

CURSORcursor_nameISselect_statement;

例:

CURSORauthors_cursorIS

SELECTau_lname,au_fname

FROMauthors

WHEREau_lnameLIKE‘B%’

ORDERBYau_lname,au_fname;



2、OPEN语句

语法:

OPENcursor_name

例:

OPENauthors_cursor;



3、FETCH语句

语法:

FETCHcursor_nameINTOvariable_name1[,variable_name2,…];

例:

FETCHauthors_cursorINTOau_lname,au_fname;



4、CLOSE语句

语法:

CLOSEcursor_name

例:

CLOSEauthors_cursor;



5、复杂游标提取轮回布局与轮回停止前提判别

1>用%FOUND做轮回判别前提的WHILE轮回

(1)FETCHauthors_cursorINTOau_lname,au_fname;

(2)WHILEauthors_cursor%FOUNDLOOP

--Concatenateanddisplaythecurrentvaluesinthevariables.

DBMS_OUTPUT.ENABLE;

DBMS_OUTPUT.PUT_LINE(‘Author:‘||au_fname||‘‘||au_lname);

FETCHauthors_cursorINTOau_lname,au_fname;

ENDLOOP;

(3)CLOSEauthors_cursor;



2>用%NOTFOUND做轮回判别前提的复杂LOOP...ENDLOOP轮回

(1)OPENauthors_cursor;

(2)LOOP

FETCHauthors_cursorINTOau_lname,au_fname;

--Exitloopwhentherearenomorerowstofetch.

EXITWHENauthors_cursor%NOTFOUND;

--Concatenateanddisplaythecurrentvaluesinthevariables.

DBMS_OUTPUT.ENABLE;

DBMS_OUTPUT.PUT_LINE(‘Author:‘||au_fname||‘‘||au_lname);

ENDLOOP;

(3)CLOSEauthors_cursor;

3>用游标式FOR轮回,以下:

DECLARE

CURSORc_HistoryStudentsIS

SELECTid,first_name,last_name

FROMStudents

WHEREmajor=‘History’

BEGIN

FORv_StudentDataINc_HistoryStudentsLOOP

INSERTINTOregistered_students

(student_id,first_name,last_name,department,course)

VALUES(v_StudentData.ID,v_StudentData.first_name,v_StudentData.last_name,’HIS’,301);

ENDLOOP;

COMMIT;

END;

起首,纪录v_StudentData没有在块的声明部分举行声明,些变量的范例是c_HistoryStudents%ROWTYPE,v_StudentData的感化域仅限于此FOR轮回自己;实在,c_HistoryStudents以隐含的体例被翻开和提取数据,并被轮回封闭。

6、隐式游标SQL%FOUND与SQL%NOTFOUND

与MSSQLSERVER一样,ORACLE也有隐式游标,它用于处置INSERT、DELETE和单行的SELECT..INTO语句。由于SQL游标是经由过程PL/SQL引擎翻开和封闭的,以是OPEN、FETCH和CLOSE命令是有关的。可是游标属性能够被使用于SQL游标,以下:

BEGIN

UPDATErooms

SETnumber_seats=100

WHEREroom_id=9990;

--假如找不响应的纪录,则拔出新的纪录

IFSQL%NOTFOUNDTHEN

INSERTINTOrooms(room_id,number_seats)

VALUES(9990,100)

ENDIF

END;

7、示例:

--DeclarethevariablestostorethevaluesreturnedbyFETCH.

--DeclaretheCURSORauthors_cursor.

DECLARE

au_lnamevarchar2(40);

au_fnamevarchar2(20);

CURSORauthors_cursorIS

SELECTau_lname,au_fname

FROMauthors

WHEREau_lnameLIKE‘B%’

ORDERBYau_lname,au_fname;



BEGIN

OPENauthors_cursor;

FETCHauthors_cursorINTOau_lname,au_fname;

WHILEauthors_cursor%FOUNDLOOP

--Concatenateanddisplaythecurrentvaluesinthevariables.

DBMS_OUTPUT.ENABLE;

DBMS_OUTPUT.PUT_LINE(‘Author:‘||au_fname||‘‘||au_lname);

FETCHauthors_cursorINTOau_lname,au_fname;

ENDLOOP;



CLOSEauthors_cursor;

END;



<3>、从SQLSERVER向ORACLE的迁徙计划

对照上述SQL代码,在迁徙过程当中要做以下调剂:

(1)T-SQL对CURSOR的声明在主体代码中,而PL/SQL中对CURSOR的声明与变

量声明同步,都要在主体代码(BEGIN关头字)之前声明,以是在迁徙时要

将游标声明提早,MSSQLSERVER的Cursor界说后的参数省往;

(2)对CUOSOR操纵的语法中PL/SQL没有T-SQL里DEALLOCATECURSOR这一部分,

迁徙时要将该部分语句删除。

(3)PL/SQL与T-SQL对游标中的轮回与轮回停止前提判别的处置不太一样,根

据后面的会商并参考前面对两种语法集举行把持语句对照剖析部分的叙说,

倡议将T-SQL中的游标提取轮回调剂为PL/SQL中的WHILE游标提取轮回结

构,如许可坚持轮回的基础布局大抵稳定,同时在举行轮回停止前提判别时

要注重将T-SQL中的对@@FETCH_STATUS全局变量的判别调剂为对

CURSOR_NAME%FOUND语句举行判别。

(4)关于T-SQL,没有界说语句停止标记,而PL/SQL用“;”停止语句。

(5)关于原MSSQLSERVER范例的游标,假如游标掏出的值没有介入运算的,全体接纳FOR轮回体例来交换;而关于掏出的值还要举行别的运算的,能够接纳间接在界说变量地位界说变量。

(6)MSSQL中关于统一游标反复界说几回的情形在ORACLE中可经由过程游标变量来办理.以下:

MSSQLSERVER中:

Declarecur_ypdmcursorfor

Select*fromyp

Opencur_yp

Fetchcur_ypinto@yp,@mc…

While@@fetch_status-1

Begin

If@@fetch_status-2

Begin

….

End

Fetchcur_ypinto@yp,@mc…

End

Closecur_ypdm

Deallocatecur_ypdm

..

Declarecur_ypdmcursorfor

Select*fromypwherecondition1

Opencur_yp

Fetchcur_ypinto@yp,@mc…

While@@fetch_status-1

Begin

If@@fetch_status-2

Begin

….

End

Fetchcur_ypinto@yp,@mc…

End

Closecur_ypdm

Deallocatecur_ypdm

..

Declarecur_ypdmcursorfor

Select*fromypwherecondition2

Opencur_yp

Fetchcur_ypinto@yp,@mc…

While@@fetch_status-1

Begin

If@@fetch_status-2

Begin

….

End

Fetchcur_ypinto@yp,@mc…

End

Closecur_ypdm

Deallocatecur_ypdm

..

在程序中,三次界说统一游标cur_yp

在迁徙过程当中,最好先界说一游标变量,在程序顶用open翻开,以下:

declare

typecur_typeisrefcur_type;

cur_ypcur_type;



begin

opencur_ypforselect*fromyp;

loop

fetchcur_ypintoyp,mc…

ExitWhencur_yp%NotFound;

….

endloop;

closecur_yp;

opencur_ypforselect*fromypwherecondition1;

loop

fetchcur_ypintoyp,mc…

ExitWhencur_yp%NotFound;

….

endloop;

closecur_yp;

opencur_ypforselect*fromypwherecondition2;

loop

fetchcur_ypintoyp,mc…

ExitWhencur_yp%NotFound;

….

endloop;

closecur_yp;

end;

(7)请注重,游标轮回中中必定要加入语名,要否则实行时会呈现逝世轮回。

<五>存储历程/函数

<1>、SQLSERVER端语法申明

1、语法:

CREATEPROC[EDURE][owner.]procedure_name[;number]

[(parameter1[,parameter2]…[,parameter255])]

[{FORREPLICATION}|{WITHRECOMPILE}

[{[WITH]|[,]}ENCRYPTION]]

AS

sql_statement[...n]

个中,Parameter=@parameter_namedatatype[=default][output]



申明:T-SQL中存储历程的布局大抵以下

CREATEPROCEDUREprocedure_name

/*输出、输入参数的声明部分*/

AS

DECLARE

/*部分变量的声明部分*/

BEGIN

/*主体SQL语句部分*/

/*游标声明、利用语句在此部分*/

END



2、示例:

IFEXISTS(SELECT1FROMsysobjects

WHEREname=titles_sumANDtype=P)

DROPPROCEDUREtitles_sum

GO



CREATEPROCEDUREtitles_sum

@TITLEvarchar(40)=%,@SUMmoneyOUTPUT

AS

BEGIN

SELECTTitleName=title

FROMtitles

WHEREtitleLIKE@TITLE

SELECT@SUM=SUM(price)

FROMtitles

WHEREtitleLIKE@TITLE

END



<2>、ORACLE端PROCEDURE语法申明

1、语法:

CREATE[ORREPLACE]PROCEDUREprocedure_name

[(parameter1[{IN|OUT|INOUT}]type,



parametern[{IN|OUT|INOUT}]type)]

{IS|AS}

[BEGIN]

sql_statement[...n];

[END];



申明:PL/SQL中存储历程的布局大抵以下

CREATEORREPLACEPROCEDUREprocedure_name

(/*输出、输入参数的声明部分*/)

AS

/*部分变量、游标等的声明部分*/

BEGIN

/*主体SQL语句部分*/

/*游标利用语句在此部分*/

EXCEPTION

/*非常处置部分*/

END;



2、示例:

CREATEORREPLACEPROCEDUREdrop_class

(arg_student_idINvarchar2,

arg_class_idINvarchar2,

statusOUTnumber)

AS

counternumber;

BEGIN

status:=0;

--Verifythatthisclassreallyispartofthestudent’sschedule.

selectcount(*)intocounter

fromstudent_schedule

wherestudent_id=arg_student_id

andclass_id=arg_class_id;



IFcounter=1THEN

deletefromstudent_schedule

wherestudent_id=arg_student_id

andclass_id=arg_class_id;

status:=-1;

ENDIF;

END;

<3>ORACLE端FUNCTION语法申明

(1)语法

CREATE[ORREPLACE]FUNCTIONfunction_name

[(argument[{IN|OUT|INOUT}])type,



[(argument[{IN|OUT|INOUT}])type

RETURNreturn_type{IS|AS}

BEGIN



END;

关头字return指定了函数前往值的数据范例。它能够是任何正当的PL/SQL数据范例。每一个函数都必需有一个return子句,由于在界说上函数必需前往一个值给挪用情况。

(2)示例

CREATEORREPLACEFUNCTIONblanace_check(Person_NameINvarchar2)

RETURNNUMBER

IS

BalanceNUMBER(10,2);

BEGIN

Selectsum(decode(acton,’BOUGHT’,Amount,0))

INTObalance

FROMledger

WHEREPerson=Person_name;

RETURN(balance);

END;

(3)历程与函数的区分

函数能够前往一个值给挪用情况;而历程不克不及,历程只能经由过程前往参数(带“OUT”或“INOUT”)传归去数据。

<4>从SQLSERVER向ORACLE的迁徙计划

经由过程对照上述SQL语法的差别,在迁徙时必需注重以下几点:

1、关于有前往单值的MSSQL存储历程,在数据库移值最恶化换成ORALCE的函数;关于MSSQL有大批数据的处置而又不需前往值的存储历程转换成ORACLE的历程

2、在T-SQL中,输出、输入参数界说部分在“CREATE…”和“AS”之间,前后

没有括号;而在PL/SQL中必需有“(”和“)”与其他语句离隔。

3、在T-SQL中,声明部分变量时,后面要有DECLARE关头字;

而在PL/SQL中不必DECLARE关头字。

4、在T-SQL中,参数名的第一个字符必需是“@”,并切合标识符的划定;

而在PL/SQL中,参数名除切合标识符的划定外没有特别申明,T-SQL中,关于参数可其数据范例及其长度和精度;可是PL/SQL中除援用%TYPE和%ROWTYPE以外,不克不及在界说参数数据范例时给出长度和精度,以下:

CREATEORREPLACEPROCEDUREPROC_SELE_YS

(YSDMCHAR(6),GZNUMBER(14,4))

AS

BEGIN



END;

是毛病的,应以下界说

CREATEORREPLACEPROCEDUREPROC_SELE_YS

(YSDMCHAR,GZNUMBER)

AS

BEGIN



END;

大概

CREATEORREPLACEPROCEDUREPROC_SELE_YS

(YSDMYSDMB.YSDM%TYPE,GZYSDMB.GZ%TYPE)

AS

BEGIN



END;



5、关于T-SQL,游标声明在主体SQL语句中,即声明与利用语句同步;

而在PL/SQL中,游标声明在主体SQL语句之前,与部分变量声明同步。

6、关于T-SQL,在主体SQL语句顶用以下语句对部分变量赋值(初始值或

数据库表的字段值或表达式):

“SELECT部分变量名=所赋值(初始值或数据库表的字段值或表达式)”;

而在PL/SQL中,将初始值赋给部分变量时,用以下语句:

“部分变量名:=所赋值(初始值或表达式);”,

将检索出的字段值赋给部分变量时,用以下语句:

“SELECT数据库表的字段值INTO部分变量名…”。

7、在PL/SQL中,可使用%TYPE来界说部分变量的数据范例。申明以下:

比方,students表的first_name列具有范例VARCHAR2(20),基于这点,

我们能够依照下述体例声明一个变量:

V_FirstNameVARCHAR2(20);

可是假如改动了first_name列的数据范例则必需修正该声明语句,因而能够采

用%TYPE举行变量数据范例声明:

V_FirstNamestudents.first_name%TYPE;

如许,该变量在存储历程编译时将由体系主动断定其响应数据范例。

8、关于T-SQL,没有界说语句停止标记,而PL/SQL用“END<历程名>;”停止语句。

9、存储历程的挪用要注重:在MSSQLSERVER中的格局为“EXECProcedure_Name{arg1,arg2,…},但在ORACLE中间接援用历程名便可,如要实行存储历程DefaltNo,其参数为“9”,则实行时为Default(“9”)。

10、ORACLE数据库的存储历程不撑持用select子句间接前往一个数据集,要做到经由过程程发生一纪录集有两种计划:

计划一:接纳包和游标变量

第一步,创立一个包,界说一个游标变量

createpackagep_name
is
typecursor_nameisrefcursor;
end;

第二步,创立历程,可是基前往参数用包中的游标范例
createprocedureprocedure_name(sinoutp_name.cursor_name)is
begin
opensforselect*fromtable_name...;
end;

如许,经由过程存储历程就能够前往一个数据集了,但用到这类情形,历程的参数中只这前往了局的游标参数能够带关头字”OUT”,别的不克不及带”out”,不然,体系会呈现导常。

计划二:经由过程两头表,建一两头表,其表格的列为所需数据列再加上一个序列字段。历程的处置为将数据拔出到两头表中,同时经由过程

selectuserenv(‘sessionid’)fromdual;获得以后毗连会话的序号,将获得的序号值安排到序列字段中,同时存储历程前往毗连会话的序号,前台PB程序间接会见两头表,数据窗口在检索时经由过程序号参数可将所需的数据检索出来。
<六>触发器
<1>、SQLSERVER端语法申明

1、语法:

CREATETRIGGER[owner.]trigger_name

ON[owner.]table_name

FOR{INSERT,UPDATE,DELETE}

[WITHENCRYPTION]

AS

sql_statement[...n]

大概利用IFUPDATE子句:

CREATETRIGGER[owner.]trigger_name

ON[owner.]table_name

FOR{INSERT,UPDATE}

[WITHENCRYPTION]

AS

IFUPDATE(column_name)

[{AND|OR}UPDATE(column_name)…]

sql_statement[...n]



2、示例:

IFEXISTS(SELECT1FROMsysobjects

WHEREname=reminderANDtype=TR)

DROPTRIGGERreminder

GO



CREATETRIGGERemployee_insupd

ONemployee

FORINSERT,UPDATE

AS

/*Gettherangeoflevelforthisjobtypefromthejobstable.*/

DECLARE@min_lvltinyint,

@max_lvltinyint,

@emp_lvltinyint,

@job_idsmallint

SELECT@min_lvl=min_lvl,

@max_lvl=max_lvl,

@emp_lvl=i.job_lvl,

@job_id=i.job_id

FROMemployeee,jobsj,insertedi

WHEREe.emp_id=i.emp_idANDi.job=j.job_id

IF(@job_id=1)and(@emp_lvl10)

BEGIN

RAISERROR(Jobid1expectsthedefaultlevelof10.,16,1)

ROLLBACKTRANSACTION

END

ELSE

IFNOT(@emp_lvlBETWEEN@min_lvlAND@max_lvl)

BEGIN

RAISERROR(Thelevelforjob_id:%dshouldbebetween%dand%d.,

16,1,@job_id,@min_lvl,@max_lvl)

ROLLBACKTRANSACTION

END

GO



<2>、ORACLE端语法申明

1、语法:

CREATE[ORREPLACE]TRIGGERtrigger_name

{BEFORE|AFTER}triggering_eventONtable_name

[FOREACHROW]

[WHENtrigger_condition]

trigger_body;

2、利用申明与示例:

(1)、上语法中,trigger_event是对应于DML的三条语句INSERT、UPDATE、

DELETE;table_name是与触发器相干的表称号;FOREACHROW是可选

子句,当利用时,对每条响应即将引发触发器触发;condition是可选的

ORACLEBOOLEAN前提,当前提为真时触发器触发;trigger_body是触发

器触发时实行的PL/SQL块。



(2)、ORACLE触发器有以下两类:

1>语句级(Statement-level)触发器,在CREATETRIGGER语句中不

包括FOREACHROW子句。语句级触发器关于触发事务只能触发一次,

并且不克不及会见受触发器影响的每行的列值。一样平常用语句级触发器处置

有关引发触发器触发的SQL语句的信息——比方,由谁来实行和甚么时

间实行。

2>行级(Row-level)触发器,在CREATETRIGGER语句中

包括FOREACHROW子句。行级触发器可对受触发器影响的每行触

发,而且可以会见原列值和经由过程SQL语句处置的新列值。行级触发器的

典范使用是当必要晓得行的列值时,实行一条事件划定规矩。



(3)在触发器体内,行级触发器能够援用触发器触发时已存在的行的列值,这些

值倚赖于引发触发器触发的SQL语句。

1>关于INSERT语句,要被拔出的数值包括在new.column_name,这里的

column_name是表中的一列。

2>关于UPDATE语句,列的原值包括在old.column_name中,数据列的新

值在new.column_name中。

3>关于DELETE语句,将要删除的行的列值放在old.column_name中。

触发语句

:old

:new

INSERT

无界说——一切字段都是NULL

当该语句完成时将要拔出的数值

UPDATE

在更新之前的该行的原始取值

当该语句完成时将要更新的新值

DELETE

在删除行之前的该行的原始取值

不决义——一切字段都是NULL

4>在触发器主体中,在new和old后面的“:”是必须的。而在触发器的

WHEN子句中,:new和:old纪录也能够在WHEN子句的condition外部

援用,可是不必要利用冒号。比方,上面CheckCredits触发器的主体仅

当先生确当前成就凌驾20时才会被实行:

CREATEORREPLACETRIGGERCheckCredits

BEFOREINSERTORUPDATEOFcurrent_creditsONstudents

FOREACHROW

WHEN(new.current_credits>20)

BEGIN

/*Triggerbodygoeshere.*/

END;

但CheckCredits也能够按上面体例改写:

CREATEORREPLACETRIGGERCheckCredits

BEFOREINSERTORUPDATEOFcurrent_creditsONstudents

FOREACHROW

BEGIN

IF:new.current_credits>20THEN

/*Triggerbodygoeshere.*/

ENDIF;

END;

注重,WHEN子句仅能用于行级触发器,假如利用了它,那末触发器主体

仅仅对那些满意WHEN子句指定的前提的行举行处置。



(4)触发器的主体是一个PL/SQL块,在PL/SQL块中可使用的一切语句在触

发器主体中都是正当的,可是要遭到上面的限定:

1>触发器不克不及利用事件把持语句,包含COMMIT、ROLLBACK或

SAVEPOINT。ORACLE坚持这类限定的缘故原由是:假如触发器碰到毛病时,

由触发器招致的一切数据库变更均能被回滚(rollback)作废;但假如

触发器确认(commit)了对数据库举行的部分变更,ORACLE就不克不及完整

回滚(rollback)全部事件。

2>在触发器主体中挪用到的存储历程的完成语句里也不克不及利用事件把持语

句。

3>触发器主体不克不及声明任何LONG或LONGRAW变量。并且,:new和:old

不克不及指向界说触发器的表中的LONG或LONGRAW列。

4>当声明触发器的表中有外键束缚时,假如将界说触发器的表和必要作为

&n列举选择MySQL的理由的最困难的地方在于,如何对这些理由进行排序。MySQL学习教程这就如同我们经常争论的故事:先有鸡还是先有蛋?
admin 该用户已被删除
沙发
发表于 2015-1-20 17:29:15 | 只看该作者
发几份SQL课件,以飨阅者
精灵巫婆 该用户已被删除
板凳
发表于 2015-1-29 13:38:23 来自手机 | 只看该作者
如果处理少量数据,比如几百条记录的数据,我不知道这两种情况哪个效率更高,如果处理大量数据呢?比如有表中有20万条记录.
老尸 该用户已被删除
地板
发表于 2015-2-6 01:30:09 | 只看该作者
SP4包括用于以下SQLServer2000组件的程序包:Database组件(下载文件:SQL2000-KB884525-SP4-x86.EXE)更新SQLServer2000的32位Database组件,包括数据库引擎、复制、客户端连接组件及工具。有关其他信息,请参阅ReadmeSql2k32Sp4.htm。AnalysisServices组件(下载文件:SQL2000.AS-KB884525-SP4-x86.EXE)更新SQLServer2000的32位AnalysisServices。
金色的骷髅 该用户已被删除
5#
 楼主| 发表于 2015-3-4 10:13:26 | 只看该作者
如果,某一版本可以提供强大的并发响应,但是没有Oracle的相应版本稳定,或者价格较贵,那么,它就是不适合的。
深爱那片海 该用户已被删除
6#
发表于 2015-3-11 18:14:09 | 只看该作者
对于微软系列的东西除了一遍遍尝试还真没有太好的办法
再见西城 该用户已被删除
7#
发表于 2015-3-19 06:29:52 | 只看该作者
从底层原理到表层引用,书籍多的很。个人认为没有什么那本书好?这样的说法。主要看和个人的学习方法是否适合。
飘飘悠悠 该用户已被删除
8#
发表于 2015-3-27 10:39:38 | 只看该作者
个人感觉没有case直观。而且默认的第三字段(还可能更多)作为groupby字段很容易造成新手的错误。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-22 19:59

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表