前言
照例廢話幾句,想玩下QT,但是學習吧總得想點事情做啊,單純學習語法用法這些?反正我是學不下去的,腦袋一拍,就先學下怎么連接數據庫吧!然而萬萬沒想到,我這是給自己挖了一個深深的坑啊!
學習自然去官網教程咯,官網推薦使用unixODBC來連接,闊以,再一搜unixODBC,喲,這貨還不能單獨工作,需要和FreeTDS這個驅動配合才可以,那就開始整吧。那么問題來了,Linux下使用QT通過unixODBC+FreeTDS連接數據庫的教程一搜一大把,尤其是CSDN,首頁上基本全是CSDN的鏈接,為什么我要寫這篇隨筆呢,因為說句實話,CSDN上的這個方面的教程95%寫的都是弟弟,寫的根本不完整,按着去做根本用不了,很多關鍵的地方都省略了,不是少這個就是少那個,我一直覺得這是一種既想當bz,又想立牌坊的行為,想寫點技術博客吸引下眼球,又怕徒弟學會餓死師傅,虛偽!更坑的是90%的文章都是你抄我我抄你,且是無腦抄,無力吐槽。如果上面的話刺痛了你,那拜托你去根據自己寫的文章實踐一下能不能用吧~
最后,這個隨筆是基礎環境的配置,而不是具體的代碼(當然也有代碼,只是很簡單的代碼),所以如果環境配好了就不用看了~
正題
最初我是根據網上搜的教程,自己編譯和安裝unixODBC和FreeTDS的,這里面就涉及到第一個坑:需要先安裝unixODBC並且在編譯FreeTDS時要指定unixODBC的安裝路徑,否則安裝后沒有驅動so包(官網上寫的有,但是99%的教程都不會寫這個坑)。
安裝unixODBC
從官網下載后,根據源碼安裝三步驟(configure/make/make install)安裝即可,使用--prefix=/usr/local/unixODBC設置安裝的路徑,這個沒啥說的。
安裝FreeTDS
從官網下載,安裝依然是三步驟,但是如上所說,安裝時一定要指定unixODBC的安裝路徑,人家官網上(傳送門)寫的清清楚楚,如果要配合unixODBC使用,必須要使用--with-unixodbc參數,那些寫教程時沒有指明這個參數的CSDN“大神”們,請你們告訴我你們怎么找到你們下面寫的libtdsodbc.so這個包的?
所以根據以上的說法,最終編譯時使用的參數如下:
- --prefix=/usr/local/FreeTDS (指定安裝路徑)
- --with-unixodbc=/usr/local/unixODBC (指定unixODBC安裝路徑)
- --disable-libiconv (禁用編碼轉換,這個設置與否影響不大)
- --enable-krb5 (啟用kerberos驗證,如果你使用域賬號登錄的話)
如上設置,在安裝完的路徑/usr/local/FreeTDS/lib下,才會有libtdsodbc.so包.
安裝完畢后開始配置,默認配置文件在安裝目錄下的etc文件夾下,所以進入/usr/local/FreeTDS/etc下,修改FreeTDS.conf文件,添加如下配置:
這里我使用的是MSSQL 2016,TDS Version設置為7.0可以正常連接,但是這個我測試下來並不是特別關鍵,因為按照官網建議,如果是MSSQL 2016那應該是7.4,但是這設置為7.0也是可以正常連接的。究其原因,可能是FreeTDS可以自動選擇該值,具體看下圖:
可以看到,TDS Version是auto,所以這個值可能並不關鍵,當然如果你遇到了問題,或者是其它版本的MSSQL,可以參考官網的建議(傳送門)。
配置文件修改完畢后在/usr/local/FreeTDS/bin下有tsql執行文件,執行如下命令:
./tsql -S ms -U sa -P xxxxx(MSSQL登錄密碼)
如果安裝沒問題,這里就能正常連接了,進入FreeTDS的命令模式,如下圖:
選擇數據庫,使用sql語句即可查詢。如果能正常查詢,到這里FreeTDS的安裝算是結束了,輸入exit退出即可。
配置unixODBC
前面已經安裝過了,在安裝目錄下的bin文件夾下,有個isql執行文件,可以用於測試。
unixODBC的配置文件有兩個,在安裝目錄下的etc文件夾中,一個是odbc.ini,一個是odbcinst.ini,前者配置數據源,后者配置使用的數據庫驅動,
配置odbcinst.ini
比較關鍵的是Driver參數,指定使用的驅動程序,Trace設置是否記錄日志,TraceFile是日志文件存放路徑。
配置odbc.ini
- Driver:設置使用的驅動,對應odbcinst.ini中的驅動名字FreeTDS
- Servername:指的是服務器,這個很關鍵,這個其實就是前面FreeTDS配置文件中添加的數據源的名字。
- Database:要連接的數據庫名字
配置完畢,可以使用安裝目錄bin下的isql文件進行測試,執行如下命令:
bin/isql -v mssql sa xxxxx(數據庫密碼)
如果一切正常,可以進到unixODBC的交互窗口中,如下圖:
這里我遇到了兩個坑,耽誤了我好長時間,說起來都是淚。
坑一:isql需要指定賬密,配置文件中指定無效
最初依然是使用的CSDN上“大神”寫的,直接使用bin/isql -v mssql,結果總是報錯:
百思不得其解,最后查看FreeTDS的日志,發現是登錄數據庫時報錯了:
這個錯誤是FreeTDS嘗試使用Kerbores登錄數據庫,但是我編譯時沒有加—enable-krb5參數,所以提示這個問題,但是仔細一想也不對,應該使用賬密登錄啊,我根本沒有配域賬號,當然不能用域賬號登錄,於是我搜索能不能在配置文件中配置數據庫的賬密,根據unixODBC的配置(傳送門)說明,可以在odbc.ini中配置數據庫的登錄賬號和密碼,如下圖:
然而我配置完並沒什么卵用,還是報上面一樣的錯誤,最后發現必須在執行時把賬密當參數傳入才可以。
解決方案:在參數中指定用戶名和密碼
bin/isql -v mssql sa xxxx(數據庫密碼)
這個問題真是無力吐槽,浪費了我太多時間了。
坑二:找不到FreeTDS驅動,總是報錯
這個坑毫無借鑒意義。。。。錯誤說的是沒找到驅動,但我明明配置了啊,瘋狂搜了半天,發現是自己寫錯了。。。。
Driver寫成Drive你敢信?罵了半天原來自己才是那個SB- -
QT編譯ODBC驅動
unixODBC和FreeTDS安裝好后基礎的驅動算是好了,下面就是通過QT進行連接和處理數據了,不過QT也需要自己的sql驅動才可以與unixODBC進行交互,所以還要安裝QT的sql驅動。
安裝這里的坑也不淺,不過我也不知道是誰的鍋了。。。我最初安裝QT時才剛接觸Linux,是用Ubuntu的官方軟件源安裝的,安裝完是5.9.5版本,根據官網的教程(傳送門)去編譯ODBC驅動,先下載了對應版本的插件源碼(傳送門),根據教程走到這一步時:
發現走不動,會報錯,所以你說坑不坑?
最后怎么解決呢,繼續進到子目錄odbc,$QTDIR/qtbase/src/plugins/sqldrivers/odbc,在這里進行編譯,執行如下命令:
之后make,這里會報錯,少一堆的頭文件,這里原因就是上面說的,Ubuntu官方的軟件源中的安裝包沒有sql的相關頭文件,但是前面下載的源碼中都有,根據提示將頭文件逐個放到qt的安裝目錄下,少的還挺多,總之一個個挨個復制就行了,如果你是官網下載的源碼編譯安裝的或許沒這個問題。根據提示全部將缺少的頭文件復制進安裝目錄就可以編譯成功,之后執行make install,會將sql的驅動自動移動到qt的安裝目錄下,到此環境終於是配置成功,滿滿的都是淚啊!!!
當一切塵埃落定,偶然看到有人說使用unixODBC是個超級麻煩,超級難配置的選擇,原來我一下來就給自己定了個這么高的“小目標”啊。。。WTF!!!
代碼
當環境配置完畢,代碼就很簡單了,新建個qt的控制台程序,在pro文件中加入sql庫:
QT += sql
再在cpp中引入對應的頭文件即可,完整代碼如下:
#include <QCoreApplication> #include <QtSql/QSql> #include <QtSql/QSqlQuery> #include <QtSql/QSqlError> #include <QVariant> #include <QDebug> using namespace std; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); bool ok = QSqlDatabase::isDriverAvailable("QODBC3"); qDebug()<<ok<<endl; QSqlDatabase db=QSqlDatabase::addDatabase ("QODBC3"); db.setDatabaseName("mss"); db.setPort(1433); db.setUserName("sa"); db.setPassword("his%2019"); if(!db.open ()) { qDebug()<<"Database Open Error"<<endl; qDebug()<<db.lastError().text(); } else { QSqlQuery query=db.exec("SELECT TOP 5 * FROM doctor"); while(query.next()) { qDebug()<<(query.value(0).toString())<<endl; } } return a.exec(); }
最后
拒絕做垃圾程序員,從認真做起!!!別除了抄還是抄,一點腦子都不動,還是轉行吧,別給程序員丟臉了。