最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

Thinkphp与Oracle之间的各种问题

来源:懂视网 责编:小采 时间:2020-11-09 13:02:06
文档

Thinkphp与Oracle之间的各种问题

Thinkphp与Oracle之间的各种问题:Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。 首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是
推荐度:
导读Thinkphp与Oracle之间的各种问题:Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。 首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是

Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。 首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是

Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。

首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是,利用Oracle中的MERGE INTO来实现这一点。

public function insert($data, $options = array(), $replace = false)
{
 if (!$replace) {
 return parent::insert($data, $options, $replace);
 }
 $values = $fields = array();
 $this->model = $options['model'];
 $sql_merge = 'MERGE INTO ' . $this->parseTable($options['table']) .
 ' using (select 1 from dual) ' .
 ' ON (' . $this->parseValue($data[$options['marge_key']]) . ' is not null and ' . $this->parseValue($data[$options['marge_key']]) . ' = ' . $options['marge_key'] . ')';
 //insert
 foreach ($data as $key => $val) {
 //主键值为空时,不插入主键
 if ($this->parseKey($key) == $this->parseKey($options['marge_key'])
 && $val == null
 ) {
 } elseif (is_array($val) && 'exp' == $val[0]) {
 $fields[] = $this->parseKey($key);
 $values[] = $val[1];
 } elseif (is_scalar($val) || is_null(($val))) { // 过滤非标量数据
 $fields[] = $this->parseKey($key);
 if (C('DB_BIND_PARAM') && 0 !== strpos($val, ':')) {
 $name = md5($key);
 $values[] = ':' . $name;
 $this->bindParam($name, $val);
 } else {
 $values[] = $this->parseValue($val);
 }
 }
 }
 $sql_insert = 'INSERT (' . implode(',', $fields) . ') VALUES (' . implode(',', $values) . ')';
 //update
 if (isset($data[$this->parseKey($options['marge_key'])])
 || $data[$this->parseKey($options['marge_key'])] == null
 ) {
 unset($data[$this->parseKey($options['marge_key'])]);
 }
 $sql_update = 'UPDATE '
 . $this->parseSet($data)
 . $this->parseWhere(!empty($options['where']) ? $options['where'] : '')
 . $this->parseOrder(!empty($options['order']) ? $options['order'] : '')
 . $this->parseLimit(!empty($options['limit']) ? $options['limit'] : '');
 $sql = $sql_merge . ' WHEN MATCHED THEN ' . $sql_update . ' WHEN NOT MATCHED THEN ' . $sql_insert;
 return $this->execute($sql, $this->parseBind(!empty($options['bind']) ? $options['bind'] : array()));
}

不支持事务是Thinkphp连接Oracle时的另一个问题,框架作者似乎已经做过适配,但是应该是没有测试,留下一堆bug。DbOracle.class.php中已经有了startTrans,commit,rollback等,稍作修改即可。

Thinkphp对数据库的所有操作最终都是汇集到query或execute上来执行,但这两个函数里放了一句$this->mode = OCI_COMMIT_ON_SUCCESS;活生生的把事务扼杀了,所以,这里先把两个函数里的这句注释掉。

然后,惊人得发现execute()中调用oci_execute时根本没有传入mode!前面辛辛苦苦改mode又是何苦,果断加上oci_execute($stmt, $this->mode)。

接下来才是让事务生效的重头戏。在事务的几个开关函数中加入对mode的修改,在startTrans()中,将mode设为OCI_DEFAULT,commit和rollback中将将mode设为改回OCI_COMMIT_ON_SUCCESS。这三个函数大概就是这样子的:

/**
 * 启动事务
 * @access public
 * @return void
 */
 public function startTrans() {
 $this->initConnect(true);
 if ( !$this->_linkID ) return false;
 //数据rollback 支持
 if ($this->transTimes == 0) {
 $this->mode = OCI_DEFAULT;
 }
 $this->transTimes++;
 return ;
}
/**
 * 用于非自动提交状态下面的查询提交
 * @access public
 * @return boolen
 */
public function commit(){
 if ($this->transTimes > 0) {
 $result = oci_commit($this->_linkID);
 if(!$result){
 $this->error();
 return false;
 }
 $this->mode = OCI_COMMIT_ON_SUCCESS;//陈宣亦 2014.11.09 14:07
 $this->transTimes = 0;
 }
 return true;
}
/**
 * 事务回滚
 * @access public
 * @return boolen
 */
 public function rollback(){
 if ($this->transTimes > 0) {
 $result = oci_rollback($this->_linkID);
 if(!$result){
 $this->error();
 return false;
 }
 $this->mode = OCI_COMMIT_ON_SUCCESS;//陈宣亦 2014.11.09 14:07
 $this->transTimes = 0;
 }
 return true;
}

还有一个头疼的问题就是日期类型转换,我还在寻找一种便捷的方法来解决这个问题。以后再补充上来吧。

文档

Thinkphp与Oracle之间的各种问题

Thinkphp与Oracle之间的各种问题:Thinkphp对Oracle的支持简直弱爆,只做到了基本的操作,就连事务都不支持。今天来手动改一改DbOracle.class.php,让它稍微好用一些吧。 首先是insert。原来的insert应该没有什么问题,但实际项目中更多的是需要在插入的时候遇到已存在的记录则进行更新。于是
推荐度:
标签: php 的所有 问题
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top