ξσ Dicky's Blog σξ

朋友多了,寂寞卻沒少,朋友沒有了你,得到了天下最高的技術又能如何?人類的全部才能無非是時間和耐心的混合物.---巴尔扎克

dicky GuID:AppleBBS
932978次访问,排名27好友0人,关注者1
Hello.
AppleBBS的文章
原创 774 篇
翻译 2 篇
转载 54 篇
评论 483 篇
ξσ Dicky σξ的公告
Welcome To My Blog~~Thank U~Wish U Have A Good Time Here~~

Name:Dicky QQ:25941
首页 留言
My QQ:25941,点击这里给偶留言! MSN Online Status Indicator



最近评论
zhouxz1026:不错!
蜂胶
蜂蜜
guxia6:喜欢最后一个
qiaogang2003:学习~
mobiledn:唉,买房真是痛苦啊,我还有恐吓电话呢,今天吉凶未卜
VBAdvisor:这专家真是扯淡。一个健康,正常的一岁半宝宝不肯吃饭大都是因为他(她)在长牙齿,不是很舒服。
文章分类
收藏
相册
My Photo
Others
BBS
ORACLE技术中国用户讨论组
ξσ青苹果论坛σξ(RSS)
Blog
"小灰"的专栏(RSS)
【平凡生活】
CALLCALL'S BLOG(RSS)
CN-Bruce's Blog(RSS)
Goaler Article
Guo's BLOG(RSS)
JAVA之路(RSS)
Jenny's Blog(RSS)
Lovevivi's Blog(RSS)
Netsky's BLOG(RSS)
PuterJam's Blog(RSS)
YuL's Blog(RSS)
ξσ Dicky's Blog σξ(RSS)
中国丫头(RSS)
偶就是天才(RSS)
博客中国(RSS)
嘟嘟老窝(RSS)
平行之恋的BLOG(RSS)
开心不凡之人生有感(RSS)
智在居士草堂(RSS)
椰树下的海
网上地标
花差花差(RSS)
Download
9Down
E维下载
Koders
一起下载网
中国无忧站长
中国活动通信
中文软件资讯站
光点下载
多多软件站
浩瀚软件站
源码中国
華軍軟件園
软件588下载站
Hack & Crack
CrackTeam
KeyGen
Serials & keys
华夏黑客同盟
Movie
22Kan.Com
www.tt21.com
七夕免费电影
好东西免费电影
百看娱乐网
Music
Jx263音乐试听网
今生缘娱乐网
好听音乐网
我爱音乐网
水晶音乐网
百分百音乐网
蓝牙音乐网
要听音乐网
音乐听厅
音乐视听2000
黑胶碟音乐网
Other
200.NET邮件服务器
3126
56.Com
Dicky's Map
Dicky的网摘
E-Mail Icon Generator
GMail
GmailHardDrive.com
Google AdSense
IP Search
MapBar
MSN Web Messenger
QQ任我挂
QQ挂机平台
WEB版图像处理工具
上海城市交通
上海电子地图
上海移动通信
中国工商银行
中国电子简历网
全球最大中国企业库
大众点评网
太平洋电脑网
实用查询
宣传易广告媒体
我摘·网摘·网络书签
我爱打折
搜房按揭综合服务中心
红袖添香
金山词霸在线搜索
Technology
(蓝丽程序员网络
51windows™.Net(RSS)
Eric Liu(RSS)
E路阳光
JoyCode
MSDN Home Page
MSDN 中文网站
MSDN中文网站
New Technol Union(RSS)
专注于.Net
中国WEB开发者网络
中国XML论坛
从零开始
博客园
孟子E章
无忧脚本
横批:不服不行
环球网络
网管之家
蓝色理想
迷失网络
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 从SQL Server 向Oracle 8迁移的技术实现方案收藏

新一篇: Windows中打开和关闭FSO文件读写权限的方法 | 旧一篇: 行业应用软件项目经理三步曲

 不知道从哪里得到这个文档,有用就放上来了 -gwb

 

数据库端SQL语法的迁移

以下为常用的SQL语法迁移,包括数据类型、ID列向SEQUENCE迁移、表(主键、外键、CHECK、UNIQUE、DEFAULT、INDEX)、游标、存储过程、函数、触发器、常用SQL语法与函数几个方面,考虑SQL SERVER的实际情况,没有涉及ORACLE特有的PACKAGE、EXCEPTION等。在以下的描述中,将SQL SERVER的TRANSACT-SQL简称为T-SQL。在ORACLE中,其语法集称为PL/SQL。

 

<一> 数据类型的迁移

    <1>、ORACLE端语法说明

在ORACLE中,分析其数据类型,大致可分为数字、字符、日期时间和特殊四大类。其中,数字类型有NUMBER;字符类型有CHAR与VARCHAR2;日期时间类型只有DATE一种;除此之外,LONG、RAW、LONG RAW、BLOB、CLOB和BFILE等数据类型都可视为特殊数据类型。

 

    <2>、SQL SERVER端语法说明

在SQL SERVER中,参照上面对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、BINARY VARING等数据类型都可视为特殊数据类型。

 

<3>、从SQL SERVER向ORACLE的迁移方案

比较ORACLE与SQL SERVER在数据类型上的不同,当从SQL SERVER向ORACLE迁移时,可以做如下调整:

 

SQL SERVER

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>、SQL SERVER端语法说明

在SQL SERVER中,可以将数据库中的某一字段定义为IDENTITY列以做主键识别,如:

jlbh        numeric(12,0)        identity(1,1)        /*记录编号字段*/

CONSTRAINT  PK_tbl_example  PRIMARY KEY  nonclustered (jlbh)  /*主键约束*/

在这里,jlbh是一个ID列,在向具有该列的表插入记录时,系统将从1开始以1的步长自动对jlbh的值进行维护。

 

    <2>、ORACLE端语法说明

但在ORACLE中,没有这样的ID列定义,而是采用另一种方法,即创建SEQUENCE。

如:

/*--1、创建各使用地区编码表--*/

drop table LT_AREA;

create table LT_AREA

(

area_id    number(5,0)      NOT NULL,   /*地区编码*/

area_name    varchar2(20)     NOT NULL,   /*地区名称*/

constraint PK_LT_AREA PRIMARY KEY(area_id)

 );

 

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

drop sequence SEQ_LT_AREA;

create sequence SEQ_LT_AREA increment by 1    /*该SEQUENCE以1的步长递增*/

 start with 1 maxvalue 99999;                /*从1开始,最大增长到99999*/

 

/*--3、实际操作时引用SEQUENCE的下一个值--*/

insert into LT_AREA(area_id, area_name) values(SEQ_LT_AREA.NEXTVAL, '深圳');

insert into LT_AREA(area_id, area_name) values(SEQ_LT_AREA.NEXTVAL, '广州');

insert into LT_AREA(area_id, area_name) values(SEQ_LT_AREA.NEXTVAL, '北京');

 

/*--4、新插入连续三条记录后,下一条语句运行后,‘上海’地区的area_id为4--*/

insert into LT_AREA(area_id, area_name) values(SEQ_LT_AREA.NEXTVAL, '上海');

 

   <3>、从SQL SERVER向ORACLE的迁移方案

 

根据以上分析,当从SQL SERVER向ORACLE迁移时,可以做如下调整:

1、去掉建表语句中有关ID列的identity声明关键字;

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

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

实际上,处理以上情况在ORACLE中采用的方法为对有自动增长字段的表增加一插入前触发器(具体资料见后“触发器”一节),如下:

CREATE OR REPLACE TRIGGER GenaerateAreaID

BEFORE INSERT ON LT_AREA

FOR EACH ROW

    Select SEQ_LT_AREA.NEXTVAL INTO :NEW.ID

    FROM DUAL;

BEGIN

END GenaerateAreaID;

GenaerateAreaID实际上修改了伪记录:new的area_id值。 :new最有用的一个特性----当该语句真正被执行时,:new中的存储内容就会被使用。所以系统每次都能自动生成新的号码。

<三> 表(主键、外键、CHECK、UNIQUE、DEFAULT、INDEX)

    <1>、SQL SERVER端语法说明

有如下SQL SERVER语句:

/* ------------------------ 创建employee 表------------------------ */

IF EXISTS(SELECT 1 FROM SYSOBJECTS WHERE NAME = ‘employee’

          AND TYPE = ‘U’)

    DROP TABLE employee

GO

 

CREATE TABLE employee

(

emp_id   empid    /*empid为用户自定义数据类型*/

/*创建自命名主键约束*/

    CONSTRAINT PK_employee PRIMARY KEY NONCLUSTERED

/*创建自命名CHECK约束*/

    CONSTRAINT CK_emp_id CHECK (emp_id LIKE

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

                     emp_id LIKE '[A-Z]-[A-Z][1-9][0-9][0-9][0-9][0-9][FM]'),

    /* CHECK约束说明:Each employee ID consists of three characters that

    represent the employee's initials, followed by a five

    digit number ranging from 10000 to 99999 and then the

    employee's gender (M or F). A (hyphen) - is acceptable

    for the middle initial. */

fname     varchar(20)      NOT NULL,

minit     char(1)         NULL,

lname     varchar(30)      NOT NULL,

 

ss_id     varchar(9)        UNIQUE,    /*创建唯一性约束*/

 

job_id    smallint            NOT NULL

    DEFAULT 1,            /*设定DEFAULT值*/

job_lvl tinyint

   DEFAULT 10,            /*设定DEFAULT值*/

    /* Entry job_lvl for new hires. */

pub_id   char(4)         NOT NULL

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

    REFERENCES publishers(pub_id),  /*创建系统命名外键约束*/

    /* By default, the Parent Company Publisher is the company

    to whom each employee reports. */

hire_date        datetime       NOT NULL

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

    /* By default, the current system date will be entered. */

CONSTRAINT FK_employee_job FOREIGN KEY (job_id)

    REFERENCES jobs(job_id)        /*创建自命名外键约束*/

)

GO

   

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

IF EXISTS (SELECT 1 FROM sysindexes

               WHERE name = 'emp_pub_id_ind')

DROP INDEX employee. emp_pub_id_ind

GO

 

CREATE INDEX emp_pub_id_ind

    ON employee(pub_id)

GO

 

    <2>、ORACLE端语法说明

在ORACLE端的语法如下:

/* ---------------------- 创建employee 表---------------------- */

DROP TABLE employee;

 

CREATE TABLE employee

(

emp_id    varchar2(9)  /*根据用户自定义数据类型的定义调整为varchar2(9)*/

/*创建自命名主键约束*/

    CONSTRAINT PK_employee PRIMARY KEY NONCLUSTERED

/*创建自命名CHECK约束*/

    CONSTRAINT CK_emp_id CHECK (emp_id LIKE

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

                     emp_id LIKE '[A-Z]-[A-Z][1-9][0-9][0-9][0-9][0-9][FM]'),

    /* CHECK约束说明:Each employee ID consists of three characters that

    represent the employee's initials, followed by a five

    digit number ranging from 10000 to 99999 and then the

    employee's gender (M or F). A (hyphen) - is acceptable

    for the middle initial. */

fname     varchar2(20)     NOT NULL,

minit     varchar2(1)      NULL,

lname     varchar2(30)     NOT NULL,

 

ss_id     varchar2(9)      UNIQUE,    /*创建唯一性约束*/

 

job_id    number(5,0)      NOT NULL

    /*这里考虑了SMALLINT的长度,也可调整为number*/

    DEFAULT 1,            /*设定DEFAULT值*/

job_lvl     number(3,0)

    /*这里考虑了TINYINT的长度,也可调整为number*/

   DEFAULT 10,            /*设定DEFAULT值*/

    /* Entry job_lvl for new hires. */

pub_id  varchar2(4)        NOT NULL

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

    REFERENCES publishers(pub_id),  /*创建系统命名外键约束*/

    /* By default, the Parent Company Publisher is the company

    to whom each employee reports. */

hire_date        date            NOT NULL

    DEFAULT SYSDATE,        /*设定DEFAULT值*/

    /*这里,SQL SERVER的getdate()调整为ORACLE的SYSDATE*/

    /* By default, the current system date will be entered. */

CONSTRAINT FK_employee_job FOREIGN KEY (job_id)

    REFERENCES jobs(job_id)        /*创建自命名外键约束*/

);

   

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

DROP INDEX employee. emp_pub_id_ind;

CREATE INDEX emp_pub_id_ind ON employee(pub_id);

 

<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端语法说明

1DECLARE 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、游标中的标准循环与循环终止条件判断

   (
1FETCH 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

  

   (
3CLOSE 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循环

     (
1FETCH  authors_cursor  INTO  au_lname, au_fname ;

     (
2WHILE 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 ;

     (
3CLOSE authors_cursor ;

 

   
2> 用%NOTFOUND做循环判断条件的简单LOOPEND LOOP循环

     (
1OPEN 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 ;

     (
3CLOSE 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