之前在弄php yii框架 连接 oracle,我把在这个过程中遇到的一些问题,来给大家分享一下,希望对大家能有所帮助
在连接数据库的时候是引用了 oci8Pdo 这个包 在yii中文社区里可以下载到
'db' => array(
'class' =>'ext.oci8Pdo.OciDbConnection',
'connectionString' => 'oci:dbname=127.0.0.1:1521/orcl;charset=AL32UTF8;',
'emulatePrepare' => true,
'username' => 'system',
'password' => 'tiger',
'enableProfiling' => true,
'enableParamLogging' => true,
),
这是在php项目里config目录main.php 中需要添加的数据库连接配置信息 oracle用户名和密码可根据你们自己的来改
Mysql 与Oralce语句的调整
一 .查找时语句调整
1.表中属性的字段
Mysql 中是小写oracle中是大写形式
处理:
if(CUtils::isOracledb()){
$this->mixDate = $data[0]["STARTDATE"];
$this->maxDate = $data[0]["ENDDATE"];
}else{
$this->mixDate = $data[0]["startDate"];
$this->maxDate = $data[0]["endDate"];
}
2.日期格式
Mysql 中查找的日期2015-7-10 oracle中的日期10-7月15
处理:
if($name == "created_at" || $name == "updated_at"){
preg_match('/(?\d{2})-(?\d{1,2})
\s*-(?\d{2})/',$value,$m);
$value=date('Y-m-d',strtotime($m['y'].'-'.$m['m']
.'-'.$m['d']));
$record->_attributes[$name]=$value;
}else{
$record->_attributes[$name]=$value;
}
3.sql语句表名带引号
Mysql 中表名有引号oracle中表名是没有引号
if(CUtils::isOracledb()){
$dbCommand = Yii::app ()->db->createCommand ( "SELECT count(*) as userCount,user_status FROM " . Yii::app ()->params ['tablePrefix'] . "users group by user_status" );
}else{
$dbCommand = Yii::app ()->db->createCommand ( "SELECT count(*) as userCount,user_status FROM `" . Yii::app ()->params ['tablePrefix'] . "users` group by user_status" );
}
4.分页
Mysql 分页可以用limit oracle 11g以下的版本没有这个属性
处理:
if(CUtils::isOracledb()){
$sql .= " and is_deleted=0 and mime_type like 'audio%'
and id between ".$start." and ".$limit." ORDER BY {$this->getOrder()} ";
}else{
$sql .= " and is_deleted=0 and mime_type like 'audio%' ORDER BY {$this->getOrder()} limit ".$start.", ".$limit;
}
5.多表联合查询
Mysql 联合查询指向表名时会用as oracle中不用as
处理:
SELECT o.*,ou.role_id as role_id FROM simiyun_organizations as o left outer join simiyun_organization_users as ou on ou.group_id = o.id
改为
SELECT o.*,ou.role_id as role_id FROM simiyun_organizations o left outer join simiyun_organization_users ou on ou.group_id = o.id
if(CUtils::isOracledb()){
$sql_str .= "SELECT u.user_name,sum(f.file_size) as numbers FROM ".Yii::app()->params['tablePrefix']."users u left outer join ".Yii::app()->params['tablePrefix']."files f on f.user_id=u.id group BY u.user_name ORDER BY numbers desc ";
}else{
$sql_str = "SELECT u.user_name,sum(f.file_size) as number FROM ".Yii::app()->params['tablePrefix']."users u, ".Yii::app()>params['tablePrefix']."files f WHERE f.user_id=u.id group BY u.id ORDER BY number desc";
}
6.关键字
Mysql 中有些属性的名称会跟oracle中的一下关键字冲突
Oracle 中有1063个定义的关键字 在表名及属性名中是不能被用到的(add , and , asc ,number ...)
处理:
if(CUtils::isOracledb()){
$sql_str .= "SELECT u.user_name,sum(f.file_size) as numbers FROM " ...
}else{
$sql_str = "SELECT u.user_name,sum(f.file_size) as number FROM " ...}
7.小写中含有大写字母
Php 中有字段含有大写字母
Oracle查找的字段要么转全大写,要么转全小写
处理:
if(CUtils::isOracledb()){
$item = array_change_key_case($item);
if ($item ["user_status"] == 1) {
$enabledUserCount = $item ["usercount"];
} else {
$disbledUserCount = $item ["usercount"];
}
}else{
if ($item ["user_status"] == 1) {
$enabledUserCount = $item ["userCount"];
} else {
$disbledUserCount = $item ["userCount"];
}
}
二.插入时语句调整
1.在每个表对应的models的验证规则中要加入id自增长
public function rules()
{
return array(
array("id",'default','value'=>new CDbExpression('(select max(id)+1 from '.self::tableName().')'),'setOnEmpty'=>false,'on'=>'insert'),
2.往表里添加日期时,使用oracle的日期格式
public function beforeSave()
{
if(CUtils::isOracledb()){
$data = new CDbExpression('SYSDATE');
}else{
$data = date("Y-m-d H:i:s",time());
}
3.直接拼装的sql语句,没有经过model的验证规则,id不能自增长,sql里的日期也没有转换
$sql = "insert into " . COrgAdapter::getInstance()->tablePrefix() .
"events(user_id,action,user_device_id,";
....
$sql .= "now(),now()";
$db_manager = MDbManager::getInstance ();
$result = $db_manager->insertDb ( $sql );
调整:
在oracle数据库中为每个表新建一个自增长的序列eg:sq_files
$sql .= "(sq_files.nextval,";
$sql .= "{$user_id},";
....
if(CUtils::isOracledb()){
$sql .= new CDbExpression('SYSDATE').",".new CDbExpression('SYSDATE').",";
$sql .= "0,0,0,0)";
}else{
$sql .= "now(),now())";
}
4.默认值
Php 中插入一条数据时,如果某个含有默认值字段的没有给值,数据插入后会自动填充上默认值
Oracle 如果某个含有默认值字段的没有给值,数据插入后不会自动填充,会为空,除非在 插入语句中,加上该字段,并且在value那里有加上defualt,才会自动填充数据
eg: insert into bb(id,user_name,tel,deluserid) values(sq_bb.nextval,'李四',1599420,default);
5.数据库字段类型的调整
Mysql 表中有text类型的字段(字符串超过255个字节时使用)
Oracle 中没有这个类型,在转表的时候会把text类型转成BLOB类型,BLOB类型的数据insert存储时很不方便,需要单独的将含有text类型的表的text类型转成varchar2类型(可以存储4000个字符32767个 字节)
6.插入数据库时,对varchar类型的值引起来的时候,单和双引号没有统一
Mysql 中只要是varchar字段,插入数据时对应值单双引号都可以用
Oracle 中插入数据时,varchar对应值只能用单引号
$sql .= "{$action},";
$sql .= "{$user_device_id},";
$sql .= "\"{$path}\",";
$sql .= "'{$context}',";
$sql .= "'{$event_uuid}',";
values (sq_events.nextval,1,3,1,"/1/list.js",'a:5:{s:4:"hash";s:40:"a511b9d
调整:
在sql语句组装时,只可用单引号来包裹varchar类型
三.修改语句调整
1.时间调整
$sql .= "SET meta_value = '$meta_value', updated_at = now() ";
调整为:
$sql .= "SET meta_value = '$meta_value', updated_at =SYSDATE ";