前言
公司要搞國產化開發,資料庫選用達夢資料庫,達夢版本為dm8,php版本為7.2,前期在Windows進行開發。
資料庫從mysql遷移到達夢資料庫裡面,遷移方法和php的擴充套件安裝方法就不講了,這方面網上的資料還蠻多。
不過php連線達夢資料庫之後的使用操作的資料就比較少了,客服的技術大家都懂的,資料全靠翻檔案,簡單給大家提供一下我踩過的坑,方法都是直接運算元據庫,後續根據大家自己的喜好去封裝去吧。
簡單說明一下達夢的資料目錄,在達夢的安裝目錄下面的《doc》裡面主要是各種使用檔案,《drivers》裡面是各種語言的擴充套件,php的so擴充套件就是從這裡面取的,我這裡主要使用的是php_dm的擴充套件,pdo_dm的資料太少了我就沒怎麼研究。
範例化資料庫的時候有兩點需要提醒各位的,字元集和字串大小寫敏感記得提前設定好,不要給自己挖坑。
本人經歷就是mysql遷移過來的資料表名和欄位名都是小寫,結果在後面使用的時候各種坑,後來發現大小寫敏感去掉就可以了。
這裡就用官方的範例庫裡面的CITY這張表演示php7.2各種使用方法吧。
查詢
廢話不多說,先上程式碼
//連線資料庫 $link = dm_connect("localhost", "SYSDBA", "SYSDBA"); if(!$link){ var_dump(@dm_error()); var_dump(iconv("GBK","UTF-8",@dm_errormsg())); } dm_setoption($link,1,12345,1);//設定 dm 連線和語句的相關屬性,設定UTF8 $query = "select * from DMHR.CITY"; $result = dm_exec($link,$query); print " 查詢結果:</br>"; while ($line = dm_fetch_array($result)){ print_r($line); echo '<br>'; } /* 釋放資源 */ dm_free_result($result); /* 斷開連線 */ dm_close($link);
達夢的php官方擴充套件php5和php7的使用方法區別很大,php5裡面很多方法在php7裡面用不了,部分方法在php7裡面用其他方法替代了,網上的資料大部分都是php5的,在php7裡面完全用不了。
查詢語句出來的中文亂碼的問題就是一個天坑,查了半天檔案才試出來的這種方法,有其他更優雅的方法也歡迎教一下我,大家互相學習。
插入
//連線資料庫 $link = dm_connect("localhost", "SYSDBA", "SYSDBA"); if(!$link){ var_dump(@dm_error()); var_dump(iconv("GBK","UTF-8",@dm_errormsg())); } dm_setoption($link,1,12345,1);//設定 dm 連線和語句的相關屬性,設定UTF8 $query = "INSERT INTO DMHR.CITY (CITY_ID,CITY_NAME,REGION_ID) VALUES ('JL','吉林','1')"; $result = dm_exec($link,$query); if($result){ echo "插入成功"; //曲線查詢插入id /*$query = "SELECT @@IDENTITY as insert_id"; $result = dm_exec($link,$query); $line = dm_fetch_array($result); echo ',ID:'; print_r($line);*/ } /* 釋放資源 */ dm_free_result($result); /* 斷開連線 */ dm_close($link);
官方提供的dm_insert_id()這個函數貌似只用php5能用,php7沒有這個函數,只能通過曲線查詢自增的id值,當然演示的這張表沒有自增ID,同時SELECT @@IDENTITY as insert_id 這句是必定查詢成功的,就算插入失敗也會返回更前一次插入成功的自增ID,千萬不要用自增ID判斷語句是否插入成功。
更新
//連線資料庫 $link = dm_connect("localhost", "SYSDBA", "SYSDBA"); if(!$link){ var_dump(@dm_error()); var_dump(iconv("GBK","UTF-8",@dm_errormsg())); } dm_setoption($link,1,12345,1);//設定 dm 連線和語句的相關屬性,設定UTF8 $query = "UPDATE DMHR.CITY SET REGION_ID='2' WHERE CITY_ID='JL'"; $result = dm_exec($link,$query); if($result){ echo "更新成功"; } /* 釋放資源 */ dm_free_result($result); /* 斷開連線 */ dm_close($link);
更新就很簡單了
刪除
//連線資料庫 $link = dm_connect("localhost", "SYSDBA", "SYSDBA"); if(!$link){ var_dump(@dm_error()); var_dump(iconv("GBK","UTF-8",@dm_errormsg())); } dm_setoption($link,1,12345,1);//設定 dm 連線和語句的相關屬性,設定UTF8 $query = "DELETE FROM DMHR.CITY WHERE (CITY_ID='JL')"; $result = dm_exec($link,$query); if($result){ echo "刪除成功"; } /* 釋放資源 */ dm_free_result($result); /* 斷開連線 */ dm_close($link);
刪除也很簡單,沒什麼特別注意的地方
事務
根據官方檔案介紹:「DM 沒有提供顯式定義事務開始的語句,第一個可執行的 SQL 語句(除登入語句外)隱含事務的開始」,這是沒有定義事務開始方法的原因,不過當我們要從某一段程式開始事務的時候,可以使用dm_autocommit()函數將事務的自動提交關閉,在程式結束之後在將自動提交開啟
//連線資料庫 $link = dm_connect("localhost", "SYSDBA", "SYSDBA"); if(!$link){ var_dump(@dm_error()); var_dump(iconv("GBK","UTF-8",@dm_errormsg())); } dm_setoption($link,1,12345,1);//設定 dm 連線和語句的相關屬性,設定UTF8 $query = "INSERT INTO DMHR.CITY (CITY_ID,CITY_NAME,REGION_ID) VALUES ('JL','吉林','1')"; $result = dm_exec($link,$query); if($result){ echo "插入成功。"; } $result = dm_autocommit($link,false);//事務自動提交關閉 $query = "UPDATE DMHR.CITY SET CITY_NAME='遼寧' WHERE (CITY_ID='SY')"; $result = dm_exec($link,$query); if($result){ echo "更新成功,回滾。"; } dm_rollback($link);//回滾 //dm_commit($link);//提交 $result = dm_autocommit($link,true);//開啟事務自動提交,結束事務 /* 斷開連線 */ dm_close($link);
踩過的坑
一、在達夢資料庫中獲取時間戳格式的時間select DATEDIFF(s, '1970-01-01 00:00:00', GETUTCDATE());
二、如果之前使用的資料庫是mysql,時間格式 DATETIME 和 TIMESTAMP 這兩種型別後面的標度要注意一下,如果不是0的話時間精度會更長
三、有些欄位查詢出來的話會變成大寫,比如「count」
解決方法:將欄位用雙引號引上例:select count(1) as "count" from "DMHR"."CITY";
四、group by語句的使用很嚴格(或者說mysql的group by過於放鬆),select中除聚合函數之外出現的所有欄位必須要在group by裡面。
比方舉一個錯誤的例子:
select EMPLOYEE_NAME,JOB_ID from "DMHR"."EMPLOYEE" group by JOB_ID;
EMPLOYEE_NAME和欄位沒在group by 中,執行必定失敗
提供一種解決思路:
select * from "DMHR"."EMPLOYEE" where EMPLOYEE_ID in (select min(EMPLOYEE_ID) as minid from "DMHR"."EMPLOYEE" group by JOB_ID)
同樣select中如果有聚合函數之外的欄位,需要加入group by。錯誤的例子:
select min(EMPLOYEE_ID),EMPLOYEE_NAME,JOB_ID from "DMHR"."EMPLOYEE";
select中有min()函數外還有其他欄位,執行必定失敗。
如果一定要在其他很多欄位裡面加入聚合函數,提供一種思路:
select t1.EMPLOYEE_NAME,t1.JOB_ID,t2.minid from "DMHR"."EMPLOYEE" t1 left join ( select min(EMPLOYEE_ID) as minid,JOB_ID from "DMHR"."EMPLOYEE" group by JOB_ID ) t2 on t2.JOB_ID=t1.JOB_ID where t1.EMPLOYEE_ID in (select min(EMPLOYEE_ID) as minid from "DMHR"."EMPLOYEE" group by JOB_ID);
結語
目前踩過的坑就這些了,希望能夠幫助到大家。
對於其他問題還是要多翻閱官方檔案了。