从SQL SERVER 向ORACLE 8迁移的技术实现方案(2)
<3>、从SQL SERVER向ORACLE的迁移方案
比较这两段SQL代码,可以看出,在创建表及其主键、外键、CHECK、UNIQUE、DEFAULT、INDEX时,SQL SERVER 与ORACLE的语法大致相同,但时迁移时要注意以下情况:
(1) Oracle定义表字段的default属性要紧跟字段类型之后,如下:
Create table MZ_Ghxx
( ghlxh number primay key ,
rq date default sysdate not null,
….
)
而不能写成
Create table MZ_Ghxx
( ghlxh number primay key ,
rq date not null default sysdate,
….
)
(2)T-SQL定义表结构时,如果涉及到用默认时间和默认修改人员,全部修改如下:
ZHXGRQ DATE DEFAULT SYSDATE NULL,
ZHXGR CHAR(8) DEFAULT ‘FUTIAN’ NULL,
(3)如表有identity定段,要先将其记录下来,建完表之后,马上建相应的序列和表触发器,并作为记录。
<四> 游标
<1>、SQL SERVER端语法说明
1、DECLARE CURSOR语句
语法:
DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR
FOR select_statement
[FOR {READ ONLY | UPDATE [OF column_list ]}]
例:
DECLARE authors_cursor CURSOR FOR
SELECT au_lname, au_fname
FROM authors
WHERE au_lname LIKE ‘B%’
ORDER BY au_lname, au_fname
2、OPEN语句
语法:
OPEN cursor_name
例:
OPEN authors_cursor
3、FETCH语句
语法:
FETCH
[ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE n | RELATIVE n ]
FROM cursor_name
[INTO @variable_name1, @variable_name2,… ]
例:
FETCH NEXT FROM authors_cursor
INTO @au_lname, @au_fname
4、CLOSE语句
语法:
CLOSE cursor_name
例:
CLOSE authors_cursor
5、DEALLOCATE语句
语法:
DEALLOCATE cursor_name
例:
DEALLOCATE authors_cursor
6、游标中的标准循环与循环终止条件判断
(1)FETCH NEXT FROM authors_cursor INTO @au_lname, @au_fname
(2)-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN
-- Concatenate and display the current values in the variables.
PRINT "Author: " + @au_fname + " " + @au_lname
-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM authors_cursor INTO @au_lname, @au_fname
END
(3)CLOSE authors_cursor
7、隐式游标
MSSqlServer中对于数据操纵语句受影响的行数,有一个全局的变量:@@rowcount,其实它是一个隐式的游标,它记载了上条数据操纵语句所影响的行数,当@@rowcount小于1时,表时,上次没有找到相关的记录,如下:
Update students set lastname = ‘John’ where student_id = ‘301’
If @@rowcount < 1 then
Insert into students values (‘301’,’stdiv’,’john’,’996-03-02’)
表示如果数据表中有学号为“301”的记录,则修改其名字为“John”,如果找不到相应的记录,则向数据库中插入一条“John”的记录
8、示例:
-- Declare the variables to store the values returned by FETCH.
DECLARE @au_lname varchar(40), @au_fname varchar(20)
DECLARE authors_cursor CURSOR FOR
SELECT au_lname, au_fname
FROM authors
WHERE au_lname LIKE ‘B%’
ORDER BY au_lname, au_fname
OPEN authors_cursor
-- Perform the first fetch and store the values in variables.
-- Note: The variables are in the same order as the columns
-- in the SELECT statement.
FETCH NEXT FROM authors_cursor INTO @au_lname, @au_fname
-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN
-- Concatenate and display the current values in the variables.
PRINT "Author: " + @au_fname + " " + @au_lname
-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM authors_cursor INTO @au_lname, @au_fname
END
CLOSE authors_cursor
DEALLOCATE authors_cursor
<2>、ORACLE端语法说明
1、 DECLARE CURSOR语句
语法:
CURSOR cursor_name IS select_statement;
例:
CURSOR authors_cursor IS
SELECT au_lname, au_fname
FROM authors
WHERE au_lname LIKE ‘B%’
ORDER BY au_lname, au_fname;
2、 OPEN语句
语法:
OPEN cursor_name
例:
OPEN authors_cursor;
3、 FETCH语句
语法:
FETCH cursor_name INTO variable_name1 [, variable_name2,… ] ;
例:
FETCH authors_cursor INTO au_lname, au_fname;
4、 CLOSE语句
语法:
CLOSE cursor_name
例:
CLOSE authors_cursor;
5、简单游标提取循环结构与循环终止条件判断
1> 用%FOUND做循环判断条件的WHILE循环
(1)FETCH authors_cursor INTO au_lname, au_fname ;
(2)WHILE authors_cursor%FOUND LOOP
-- Concatenate and display the current values in the variables.
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE( ‘Author: ‘ || au_fname || ‘ ‘ || au_lname) ;
FETCH authors_cursor INTO au_lname, au_fname ;
END LOOP ;
(3)CLOSE authors_cursor ;
2> 用%NOTFOUND做循环判断条件的简单LOOP...END LOOP循环
(1)OPEN authors_cursor;
(2)LOOP
FETCH authors_cursor INTO au_lname, au_fname ;
-- Exit loop when there are no more rows to fetch.
EXIT WHEN authors_cursor%NOTFOUND ;
-- Concatenate and display the current values in the variables.
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE( ‘Author: ‘ || au_fname || ‘ ‘ || au_lname) ;
END LOOP ;
(3)CLOSE authors_cursor ;
3>用游标式FOR循环,如下:
DECLARE
CURSOR c_HistoryStudents IS
SELECT id,first_name,last_name
FROM Students
WHERE major = ‘History’
BEGIN
FOR v_StudentData IN c_HistoryStudents LOOP
INSERT INTO registered_students
(student_id,first_name,last_name,department,course)
VALUES(v_StudentData.ID,v_StudentData.first_name, v_StudentData.last_name,’HIS’,301);
END LOOP;
COMMIT;
END;
首先,记录v_StudentData没有在块的声明部分进行声明,些变量的类型是c_HistoryStudents%ROWTYPE,v_StudentData的作用域仅限于此FOR循环本身;其实,c_HistoryStudents以隐含的方式被打开和提取数据,并被循环关闭。
6、隐式游标SQL%FOUND 与SQL%NOTFOUND
与MSSQL SERVER 一样,ORACLE也有隐式游标,它用于处理INSERT、DELETE和单行的SELECT..INTO语句。因为SQL游标是通过PL/SQL引擎打开和关闭的,所以OPEN、FETCH和CLOSE命令是无关的。但是游标属性可以被应用于SQL游标,如下:
BEGIN
UPDATE rooms
SET number_seats = 100
WHERE room_id = 9990;
--如果找不相应的记录,则插入新的记录
IF SQL%NOTFOUND THEN
INSERT INTO rooms(room_id,number_seats)
VALUES (9990,100)
END IF
END;
7、示例:
-- Declare the variables to store the values returned by FETCH.
-- Declare the CURSOR authors_cursor.
DECLARE
au_lname varchar2(40) ;
au_fname varchar2(20) ;
CURSOR authors_cursor IS
SELECT au_lname, au_fname
FROM authors
WHERE au_lname LIKE ‘B%’
ORDER BY au_lname, au_fname;
BEGIN
OPEN authors_cursor;
FETCH authors_cursor INTO au_lname, au_fname ;
WHILE authors_cursor%FOUND LOOP
-- Concatenate and display the current values in the variables.
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE( ‘Author: ‘ || au_fname || ‘ ‘ || au_lname) ;
FETCH authors_cursor INTO au_lname, au_fname ;
END LOOP ;
CLOSE authors_cursor ;
END ;
<3>、从SQL SERVER向ORACLE的迁移方案
比较上述SQL代码,在迁移过程中要做如下调整:
(1)T-SQL对CURSOR的声明在主体代码中,而PL/SQL中对CURSOR的声明与变
量声明同步,都要在主体代码(BEGIN关键字)之前声明,所以在迁移时要
将游标声明提前,MSSQL SERVER的Cursor定义后的参数省去;
(2)对CUOSOR操作的语法中PL/SQL没有T-SQL里DEALLOCATE CURSOR这一部分,
迁移时要将该部分语句删除。
(3)PL/SQL 与T-SQL对游标中的循环与循环终止条件判断的处理不太一样,根
据前面的讨论并参考后面对两种语法集进行控制语句对比分析部分的叙述,
建议将T-SQL中的游标提取循环调整为PL/SQL中的WHILE游标提取循环结
构,这样可保持循环的基本结构大致不变,同时在进行循环终止条件判断时
要注意将T-SQL中的对@@FETCH_STATUS全局变量的判断调整为对
CURSOR_NAME%FOUND语句进行判断。
(4)对于T-SQL,没有定义语句结束标志,而PL/SQL用“;”结束语句。
(5)对于原MSSQL SERVER类型的游标,如果游标取出的值没有参与运算的,全部采用FOR循环方式来替换;而对于取出的值还要进行其它运算的,可以采用直接在定义变量位置定义变量。
(6)MSSQL中对于同一游标重复定义几次的情况在ORACLE中可通过游标变量来解决.如下:
MSSQL SERVER 中:
Declare cur_ypdm cursor for
Select * from yp
Open cur_yp
Fetch cur_yp into @yp,@mc …
While @@fetch_status <> -1
Begin
If @@fetch_status <> -2
Begin
….
End
Fetch cur_yp into @yp,@mc …
End
Close cur_ypdm
Deallocate cur_ypdm
..
Declare cur_ypdm cursor for
Select * from yp where condition 1
Open cur_yp
Fetch cur_yp into @yp,@mc …
While @@fetch_status <> -1
Begin
If @@fetch_status <> -2
Begin
….
End
Fetch cur_yp into @yp,@mc …
End
Close cur_ypdm
Deallocate cur_ypdm
..
Declare cur_ypdm cursor for
Select * from yp where condition 2
Open cur_yp
Fetch cur_yp into @yp,@mc …
While @@fetch_status <> -1
Begin
If @@fetch_status <> -2
Begin
….
End
Fetch cur_yp into @yp,@mc …
End
Close cur_ypdm
Deallocate cur_ypdm
..