1. 程式人生 > >Mysql++學習(三)------舉個栗子

Mysql++學習(三)------舉個栗子

下面例子顯示瞭如何建立利用Sql++建立一個連線,執行查詢操作,返回一個結果集,並且列印.

#include <iostream>
#include <mysql++.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

int main()
{
    mysqlpp::Connection conn(false);
    //connect to the database
    if(conn.connect("mysql_cpp_data", "127.0.0.1", "comoon", ""))
    {
        //execute a query
        mysqlpp::Query query = conn.query("select * from stock");
        //get query result in a storeResult
        mysqlpp::StoreQueryResult res = query.store();
        if(res)
        {
            for(size_t i = 0; i < res.num_rows(); i++)
            {
                cout << setw(20) << res[i]["item"] <<
                        setw(10) << res[i]["num"] <<
                        setw(10) << res[i]["weight"] <<
                        setw(10) << res[i]["price"] <<
                        setw(10) << res[i]["sdate"] <<
                        endl;
            }
        }
        else
        {
            perror("Failed to get data!");
            exit(EXIT_FAILURE);
        }
    }
    else
    {
        perror("Connect Failed");
        exit(EXIT_FAILURE);
    }
    return 0;
}

異常

預設情況下,MySql++使用異常來通知錯誤,通過給connection的構建函式傳遞引數,來確定是否要開啟異常處理,前面例子中使用false來關閉了異常,在一個正常程式中建議開啟異常處理。

所有MySql++的常規異常,都繼承自類Exception.而該類繼承自標準C++的std::exception類.所以,僅僅通過捕獲std::exception,就可以捕獲和處理一切異常。不過,還是建議對於具體的異常採用捕獲程式碼塊。

 當異常處理被關閉的時候,MySql++通過返回錯誤程式碼,或者嘗試失敗的物件,或設定物件的錯誤標識來通知錯誤。繼承自OptionalExcetions介面的物件允許你關閉異常,當一個OptionalExcetions衍生類建立了也繼承自該介面的物件時,它也會傳遞異常標識。因為一切都源於connection物件,所以,在開始的時候關閉connection上的異常就會關閉所有OptionalExcetions。

也可以在一個程式碼塊中關閉異常處理,你可以在程式碼開始地方建立一個NoExceptions物件,來防止程式碼塊丟擲異常。當它被建立之後,它會記錄下傳遞過來的異常標識,在程式碼執行結束後,它將恢復異常標識到之前的狀態。

mysqlpp::Connection con; // default ctor, so exceptions enabled

{
  mysqlpp::NoExceptions ne(con);
  if (!con.select_db("a_db_that_might_not_exist_yet")) {
    // Our DB doesn’t exist yet, so create and select it here; no need
    // to push handling of this case way off in an exception handler.
  }
}

查詢操作

MySql++支援三種查詢: Query::execute()Query::store()和 Query::use()

execute()用於不返回資料的查詢.例如執行CREATE INDEX,你並沒有從伺服器獲取資料,程式將返回一個SimpleResult物件,以及一個標識執行成功與否的標識,該物件還包含命令執行所影響的行數,如果只要成功與否的標識,可以使用Query::exec(),其返回結果為bool.

如果你的查詢需要從伺服器拉資料,那麼可以簡單使用store().它將返回一個StoreQueryResult物件,該物件包含整個結果集,這將非常簡單,因為StoreQueryResult 繼承自std::vector<mysqlpp::Row>,它包含STL的各種操作.

如果你想將返回的結果集存在一個非vector的標準容器中,你可以使用Query::storein().

store*()查詢可能很方便,但是,將整個結果集全部儲存在記憶體中,代價可能會很大.事實上,MySql資料庫伺服器將資料壓縮儲存在硬碟上,但是返回給客戶端的是文字形式.對於很大的返回結果集,最好使用use()查詢.它返回一個UseQueryResult.該物件類似StoreQueryResult,但是不提供隨機訪問的特性.use查詢會讓伺服器一次返回結果集的一行,進分行處理.

if (mysqlpp::UseQueryResult res = query.use()) {
            // Display header
            cout.setf(ios::left);
            cout << setw(31) << "Item" <<
                    setw(10) << "Num" <<
                    setw(10) << "Weight" <<
                    setw(10) << "Price" <<
                    "Date" << endl << endl;

            // Get each row in result set, and print its contents
            while (mysqlpp::Row row = res.fetch_row()) {
                cout << setw(30) << row["item"] << ' ' <<
                        setw(9) << row["num"] << ' ' <<
                        setw(9) << row["weight"] << ' ' <<
                        setw(9) << row["price"] << ' ' <<
                        setw(9) << row["sdate"] <<
                        endl;
            }

條件結果行處理

有時候,你需要從伺服器拉一些並不需要的資料,然後在記憶體中過濾.使用Query::store_if().

// Define a functor for testing primality.
struct is_prime
{
    bool operator()(const stock& s)
    {
        if ((s.num == 2) || (s.num == 3)) {
            return true;    // 2 and 3 are trivial cases
        }
        else if ((s.num < 2) || ((s.num % 2) == 0)) {
            return false;   // can't be prime if < 2 or even
        }
        else {
            // The only possibility left is that it's divisible by an
            // odd number that's less than or equal to its square root.
            for (int i = 3; i <= sqrt(double(s.num)); i += 2) {
                if ((s.num % i) == 0) {
                    return false;
                }
            }
            return true;
        }
    }
};

......


// Collect the stock items with prime quantities
std::vector<stock> results;
mysqlpp::Query query = con.query();
query.store_if(results, stock(), is_prime());

為結果集中每一行執行程式碼

SQL不只是一個數據庫查詢語言.現代的資料庫引擎可以在伺服器端做一些資料的運算,但是這並不是最好的選擇.如果你需要混合程式碼和查詢,MySQL++提供了 Query::for_each()機制.

// Define a functor to collect statistics about the stock table
class gather_stock_stats
{
public:
    gather_stock_stats() :
    items_(0),
    weight_(0),
    cost_(0)
    {
    }

    void operator()(const stock& s)
    {
        items_  += s.num;
        weight_ += (s.num * s.weight);
        cost_   += (s.num * s.price.data);
    }
    
private:
    mysqlpp::sql_bigint items_;
    mysqlpp::sql_double weight_, cost_;

    friend std::ostream& operator<<(std::ostream& os,
            const gather_stock_stats& ss);
};


// Dump the contents of gather_stock_stats to a stream in human-readable
// form.
std::ostream&
operator<<(std::ostream& os, const gather_stock_stats& ss)
{
    os << ss.items_ << " items " <<
            "weighing " << ss.weight_ << " stone and " <<
            "costing " << ss.cost_ << " cowrie shells";
    return os;
}

 // Gather and display the stats for the entire stock table
mysqlpp::Query query = con.query();
std::cout << "There are " << query.for_each(stock(),
gather_stock_stats()) << '.' << std::endl;

Connection con;
con.set_option(new MultiStatementsOption(true));

// Connect to the database
if (!con.connect(mysqlpp::examples::db_name, cmdline.server(),
cmdline.user(), cmdline.pass())) {
return 1;
}

執行多重查詢

// Set up query with multiple queries.
Query query = con.query();
query << "DROP TABLE IF EXISTS test_table; " <<
    "CREATE TABLE test_table(id INT); " <<
    "INSERT INTO test_table VALUE S(10); " <<
    "UPDATE test_table SET id=20 WHERE  id=10; " <<
     "SELECT * FROM test_table; " <<
     "DROP TABLE test_table";
 cout << "Multi-query: " << endl << query << endl;

連線超時處理

MySQL連線在長時間閒置後會被MySQL關閉,預設是8小時.

一種處理連線超時的方式,是配置MySQL,重新設定其連線超時時間.

第二種方式可以採用ReconnectOption,在MySQL連線斷開後會進行自動重連

第三種方式是使用Connection::ping()輪詢檢測連線是否關閉,如果關閉,就重新連線