之前在弄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>\d{2})-(?<m>\d{1,2})
\s*-(?<y>\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 ";