|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
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学习教程这就如同我们经常争论的故事:先有鸡还是先有蛋? |
|