【戾氣滿滿】Ubuntu 18.04使用QT通過FreeTDS+unixODBC連接MSSQL填坑記(含淚親測可用)


前言

照例廢話幾句,想玩下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();
}

最后

拒絕做垃圾程序員,從認真做起!!!別除了抄還是抄,一點腦子都不動,還是轉行吧,別給程序員丟臉了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM