mysql数据库转移到oracle的经历
简单说明一下情况,系统原本是LAMP的。现在要添加对oracle的支持,原来的mysql也同样支持(通过配置选择数据库类型)。
第一步,表结构转移到oracle,并掌握转移的方法(方便给有二开的老客户转移);
第二步,表中数据转移到oracle,主要掌握转移方法,因为初始库基本是空的数据;
第三步,在产品中用pdo跑通oracle(幸运的是本产品已经用的是pdo,只是没有开通extension=php_pdo_oci.dll);
第四步,测试全产品,debug。
现进展到第一步,生成符合oracle语法的create table脚本。
虽然只是第一步,便困难重重。
1、字段类型的对应。
| mysql | oracle |
|
longblob blob |
BLOB,但是对BLOB不太了解 |
|
longtext mediumtext |
没有text类型,是不是应该用LONG?但是oracle的一个表中不能出现两个LONG的字段。所以暂用VARCHAR2(2000)对应。 |
| timestamp | 暂用TIMESTAMP对应,但是oracle认识的timestamp是这样的:"insert into JJJ values (14, '天ss天','18-8月-2016 10.42.12')";你写2016-8-18 10:42:12是无法写入oracle的。 |
| datetime,类似于timestamp的格式 | oracle的DATE类型,只认识'14-6月 -16',不认识'14-6月 -16 10:9:8',不认识2016-06-09。,所以暂用TIMESTAMP对应 |
| date,mysql的date类型如:2016-06-09 | oracle的DATE类型,只认识'14-6月 -16',不认识'14-6月 -16 10:9:8',不认识2016-06-09。 |
| enum('3','2','1','0') | oracle没有枚举型,暂用VARCHAR2(10)对应。其中10这个长度看情况调节。 |
|
zerofill 比如int(11) unsigned zerofill zerofill,用0补充左边不足的位数。int(11)就要补足11位。比如00000000001。 |
暂用NUMBER(11)对应。 |
| float、decimal、double | 比如"double(x,y)" => "NUMBER(x,y)",但需要验证可行性。 |
| decimal(10,0) | decimal后面0位小数?暂用NUMBER(10,2) |
| varchar(0) | 0代表啥?没有长度。oracle不充许0长度的字段。暂用VARCHAR2(1)对应。 |
| varchar(5000) | oracle最大VARCHAR2(4000),4001都不行。暂用VARCHAR2(4000)对应。 |
2、表名和字段名的长度,oracle不能超过30,mysql无这个限制。
建表时,若超出,oracle会报错 ORA-00972 identifier is too long
这种表有:
'icrm_refunds_trade_resend_goods',
'jingdong_qqg_trade',
'jingdong_trade',
'jumei_trade',
'openshop_refunds_trade_resend_goods',
'taobao_inventory_authorize_distributor',
'taobao_inventory_authorize_goods'
这些表中有的是表名过长,有的是字段名过长。
3、字段默认值问题。
MySQL创建表时,如果某字段定义为NOT NULL,并且没有明确定义default值,则insert时可以不填该字段,mysql会自动给它填一个0或者空串或者其他符合该字段类型的空值。当然如果该字段有明确defaut值,则会填入这个default值。
而oracle,创建表时,如果某字段定义为NOT NULL,并且没有明确定义default值,则insert时必需在sql语句中写值,否则报错。
当然如果该字段有明确的default值,则可以在insert中不填该字段的值。
这样,项目中的insert就有可能在oracle下跑不通。
Mysql的字段默认值有四种:
未定义、自定义的值(包括空串''和'0')、CURRENT_TIMESTAMP、0000-00-00 00:00:00
select COLUMN_DEFAULT from information_schema.columns的值,对于未定义的字段,得到NULL;就算这个字段是not null的,也是NULL。
| Mysql的默认值(COLUMN_DEFAULT) | oracle默认值 |
| NULL | 不写default语句 |
| 自定义的值(包括空串''和'0') | 写相应的default语句 |
| CURRENT_TIMESTAMP | 暂时不写default语句 |
| 0000-00-00 00:00:00 | 暂时不写default语句 |
4、索引问题。
oracle中的索引名不能重复,而mysql可以。
如果重复,报错:ORA-00955: name is already used by an existing object。
5、自增字段问题。
百度“oracle实现自增字段”查了半天,都是基本类似的方法。
(1)sequence + trigger 组合使用。这样每个表都要有一个 sequence + trigger。有人会认为过多使用触发器来实现Oracle字段自增,容易造成死锁或者阻塞。
(2)只用sequence,需要修改系统框架的底层insert的实现,要显示地调用序列。
两种方法该用哪一种?
6、表空间问题。
问了一下同事,说oracle最多支持32G的数据库。而我们系统经常会超过这个数。
7、oracle的sql中不能用分号结尾,而mysql可以;oracle的sql中不能出现`(按键1的左边),但mysql中经常用它来括住表名。
8、拼接oracle的创建表的sql时,有一个双引号的问题。
oracle支持的sql语法中,
表名和字段名,可以加双引号,也可以不加双引号,但不能加单引号;
字段的值如果字符串型,必需加单引号,但不能加双引号;
字段的值如果是数字,可以不加单引号,也可以加单引号,但一定不能加双引号。
比如:$sql = 'select * from zzJkb where "type" = "23"'; //其中type是NUMBER型的。
执行它会报错:General error: 904 OCIStmtExecute: ORA-00904: "23": 标识符无效 (ext\pdo_oci\oci_statement.c:148)
$sql = 'select * from zzJkb where "type" = 23'; 或者$sql = 'select * from zzJkb where "type" = \'23\'';就正确。
对于表名和字段名,加与不加双引号,oracle理解是有区别的。
$sql = "select * from zzJkb where code = 'abc'"; //这个表名zzJkb,如果不加双引号,oracle统统识别成大写,也就是ZZJKB。字段code识别为CODE。
$sql = "select name from zzJkb"; //name 和 zzJkb,统统识别成大写。如果oracle中只有小写的zzJkb表名,或者只有小写的name字段,则匹配不成功。
$sql = 'select "name" from "zzjkb"' ; //name和zzjkb,都识别成双引号中一模一样的大小写形式,不会统一转成大写。如果你oracle表中name字段是大写的或者NaMe,就匹配不成功。
/*
oracle中的表名和字段名,都是大小写敏感的。你可以在里面创建ZZJKB,同时创建ZZjkb或者zzJKB。
因为系统里mysql的sql语句,一般不区分大小写,比如mysql库里有一张zzjkb全小写的表名,
$sql = "select * from zzjKB"; //mysql中可以执行成功。
如果一个mysql表中的字段名,有大小写混合的情况,那么select * 出来的结果数组的key是照搬过来,也是大小写混合。
但是oracle表select *的结果数组中,其key全都是小写,不管实际库中的字段是不是大写,得到的key全都是小写。
这样,就不允许一个表的字段名中,出现大小写混合,要统一成全小写。否则就会出现程序中得到的key不一致的情况,在mysql和oracle下表现不一致。
可能$onecolumn['Id']在使用mysql时可用,那么在使用oracle时就不可用。
而我们程序中拼sql时,对于字段或表名,一般是不加双引号的(因为一开始支持的是mysql),这样,在使用oracle时,会被识别成大写。
结论就是:
1、oracle创建的表名字段名,统统要大写。(为的是支持系统程序代码中的sql,因为代码中的sql对于表名字段名是不加双引号的,oracle会把这些sql中的表名字段名识别成全大写)
1.5、拼接oracle的建表sql时,不能出现user这个关键字,会报错,比如
CREATE TABLE beibei_trade (
ttid NUMBER(38) DEFAULT '0' NOT NULL ,
user VARCHAR2(255) DEFAULT '' NULL ,
)
报错:ORA-00904: : invalid identifier
只能将这种oracle认定的关键字,改为双引号括起,比如"user"或者"USER"。
同样,在程序的代码中拼接sql语句,如果user不带双引号,oracle也会认为它是关键字,不会到表中去匹配user字段的值,搜出的东西永远是空的。
所以,在程序代码中,也需要注意有没有写user这种字段,需要给它加上双引号。
2、mysql的表名和字段名,统统要小写。(因为select出的字段,在使用oracle时得到的key全是小写的,而mysql下得到的key是大小写区分的)
3、代码中,所有的sql语句,表名字段名要全部改成小写。
4、mysql中字段的值,在sql中是不区分大小写的,比如如果mysql表中实际值为CHU,那么where name = 'Chu' 或者 where name = 'CHU'都可以匹配成功。
这样,对于使用oracle的系统,匹配就更加严格,搜索或者筛选出的结果可能会更少。
5、oracle有可能报错的地方:
现代码中,对于表名或字段名,可能会用飘号`将其括起来,oracle不识别会报错;
现代码中,sql语句可能出现用双引号括住字段值(mysql中双引号或单引号都可以括住字段值),而oracle中字段值一定不能用双引号,只能用单引号。
现代码中,sql语句可能会以分号结尾(符合mysql语法),oracle不充许代码中以分号结尾,所以目前的程序代码中需要注意,有没有以分号结束的sql语句;
现代码中,sql语句中可能出现user这种oracle的关键字,需要加上双引号。比如
select "USER" from beibei_trade3 where USER= 'user' //搜不出东西,因为where后的USER缺少双引号,oracle不会认为它是字段名。
select "USER" from beibei_trade3 where "USER"= 'user' //可以搜出结果。
现代码中,insert语句,对于mysql,values后面可以不写全所有字段,插入时mysql会自动插入默认值;但是oracle不行,报ORA-00947: not enough values,除非
你在values前面加上明确的字段名。
比如beibei_trade3表有四个字段:ttid,shop_id,name,lastchanged,
insert into beibei_trade3 values ('', '', 'user')//oracle报错not enough values,mysql正确。就怕代码中出现这种情况。
insert into beibei_trade3 (ttid,shop_id,name) values ('', '', 'user') //oracle正确,mysql正确。
*/
对当前系统的mysql表做的改动:
1、表ckycdmx中有两个索引sku_id和sku_dj,它两的字段一模一样,oracle不通过。
删除sku_id这个索引。
2、表YIHAODIAN_ITEMS中,index_tid和tid,两个索引的字段一模一样,oracle不通过。
删除tid这个索引。
3、有些表的索引名包含中文,taobao_refunds_trade和taobao_promotion(可能别的表也包含中文索引名称,但索引名没超过30个字符,所以没检查出)
修改索引名称去掉中文。
4、四个下划线打头的表名,去掉下划线。
5、在mysql下,包含seq的表名(104张,除去seq_dj_date,它不是序列表。也就是103张表),实际上是序列表。

seq_dj_date这个表,为了不混淆,改名为:dj_date。
在oracle下,这103张表,不需要建。而是用与表名相同的序列代替。比如seq_bonus表,在oracle下实际上没有该表,但是有SEQ_BONUS这个序列。
在oracle下,也会有DJ_DATE表。
6、region表在mysql下,region_id是主键自增字段。要把该字段搞成不要自增。
因为在oracle下,如果某字段自增,会导致插入数据时,该自段不接受传入的值,而始终使用自增值。region的值是从平台上拉取的,实际上我们希望入库的值是如下:

而在oracle中,入库的值为:

7、jingdong_trade表,
这几个以consignee_info_开头的字段,有的超过30字符,在oracle中过长,所以去除前面的consignee_info_。
8、


9、taobao_trade表,修改字段:num_iid类型由int(11) ---> varchar2(50)。该字段是“商品数字编号”,淘宝现在下载下来的这个字段已超过10位。
oracle的 一些特性:
| oracle创建表时,字段默认是null的,如果你不明确表明NOT NULL还是NULL,则默认是NULL的。 | |
|
oracle在向一个字段写入空串时,不会写入空串,而会写入null,这点跟mysql不同。 不管你是在sql中明确写明空串'',还是该字段的default值是空串,只要写入空串,oracle都会自动转成null写入表中。 |
timestamp
mysql数据库转移到oracle的经历的更多相关文章
- MYSQL数据库迁移到ORACLE数据库
一.环境和需求1.环境 MySQL数据库服务器: OS version:Linux 5.3 for 64 bit mysql Server version: 5.0.45 Oracle数据库服务器: ...
- 在mysql数据库中创建oracle scott用户的四个表及插入初始化数据
在mysql数据库中创建oracle scott用户的四个表及插入初始化数据 /* 功能:创建 scott 数据库中的 dept 表 */ create table dept( deptno int ...
- 在mysql数据库中创建Oracle数据库中的scott用户表
在mysql数据库中创建Oracle数据库中的scott用户表 作者:Eric 微信:loveoracle11g create table DEPT ( DEPTNO int(2) not null, ...
- mysql数据库迁移到oracle数据库后 如何删除相同的数据
mysql数据库迁移到oracle数据库后 如何删除相同的数据 首先搞清楚有多少数据是重复的 select pid from product group by pid having count(pid ...
- 将MySQL数据库转移到SqlServer2008数据库
由于工作需要用到了将MySQL数据库转成SqlServer数据库,查了一些资料发现将SqlServer数据库转成MySQL数据库的文章很多,但是反过来的就很少了.下面就将自己的方法分享给大家. 这里用 ...
- mysql数据库转成oracle踩过的坑
1.使用count这种组函数,那么必须配合group by使用,获取的字段要么出现在组函数内要么出现在group by中2.oracle使用union不仅要字段名一致并且数据类型也要一致3.REGEX ...
- 记一次处理mysql数据库无故锁表的经历
某日,生产环境上的用户表突然无故锁表,原以为只是偶发的bug.所以第一时间想到的解决方案简单粗暴:重启数据库(service mysqld restart).问题得以解决. 10min后,该表再次锁表 ...
- mysql数据库导入到oracle数据库
首先,写一个cmd脚本 xx.cmd sqlldr username/password control=xx.ctl errors=10000000 direct=y 再写一个bat脚本xx.bat ...
- MySQL数据库学习: 01 —— 数据库的概述
壹 概述 一 了解SQL 1.1 数据库基础 1.1.1 什么是数据库 数据库(database)保存有组织的数据的容器(通常是一个文件或一组文件). 易混淆:人们常常用“数据库”这个词语来代表他们使 ...
随机推荐
- WatiN自动化测试
简介 WatiN - Watir的.NET版: http://watin.sourceforge.net/ Welcome at the WatiN (pronounced as What-in) w ...
- 聊一聊Android的消息机制
聊一聊Android的消息机制 侯 亮 1概述 在Android平台上,主要用到两种通信机制,即Binder机制和消息机制,前者用于跨进程通信,后者用于进程内部通信. 从技术实现上来说,消息机制还是比 ...
- JAVA连接各种数据库详解
Java数据库连接(JDBC)由一组用 Java 编程语言编写的类和接口组成.JDBC 为工具/数据库开发人员提供了一个标准的 API,使他们能够用纯Java API 来编写数据库应用程序.然而各个开 ...
- python学习之os.walk()
os.walk(top,topdown = True,onerror = None,followlinks = False) 参数 top -- 根目录下的每一个文件夹(包含它自己), 产生3-元组 ...
- 接口测试脚本之Jsoup解析HTML
第一次接触jsoup还是在处理收货地址的时候,当时在写一个下单流程,需要省市区id以及详细门牌号等等,因此同事介绍了jsoup,闲来无事,在此闲扯一番! 1.我们来看下,什么是jsoup,先来看看官方 ...
- windows下控制台程序更改图标和加载资源文件
1.在空项目的Resouce FIles中右击创建一个新的.rc文件. 2.选中这个.rc文件右击在界面中选择导入icon 3.选中icon,将icon的ID更改为IDC_MAINFRAME. 4.重 ...
- 怎样用Google APIs和Google的应用系统进行集成(5)----怎样把Google Tasks的JSON Schema转换成XML的Schema(XSD)?
前面说了一些Google API的介绍,可是在实际的开发其中,我们可能须要把Google RESTful API返回的JSON数据转换成XML数据输入到第三方系统,这在企业应用集成里面很的常见. 那么 ...
- Qt类反射机制
前言 如何通过类名动态的创建对象(类反射),对于Java开发者来说一点也不陌生,当然Qt也提供了一个元对象系统(The Meta-Object System),通过这个系统我们可以动态的在运行时获 ...
- lnmp集成开发环境安装pdo_dblib扩展
php连接mssql,获取的结果中文乱码,pdo_dblib扩展使用的是apt-get install php5-sybase方法安装的,尝试了修改freetds.conf php.ini 文件编码 ...
- 阿里云经典网络和专有 专有自己设置网络和私网IP
阿里云网络系列之经典网络和专有网络 驻云科技 2016-07-29 13:43:44 浏览45005 评论9 云栖社区 nginx 安全与风控 系统软件 编程语言 数据存储与数据库 系统研发与运维 ...