下面例子顯示了如何建立利用Sql++建立一個連接,執行查詢操作,返回一個結果集,並且打印.
1 #include <iostream> 2 #include <mysql++.h> 3 #include <errno.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 7 using namespace std; 8 9 int main() 10 { 11 mysqlpp::Connection conn(false); 12 //connect to the database 13 if(conn.connect("mysql_cpp_data", "127.0.0.1", "comoon", "")) 14 { 15 //execute a query 16 mysqlpp::Query query = conn.query("select * from stock"); 17 //get query result in a storeResult 18 mysqlpp::StoreQueryResult res = query.store(); 19 if(res) 20 { 21 for(size_t i = 0; i < res.num_rows(); i++) 22 { 23 cout << setw(20) << res[i]["item"] << 24 setw(10) << res[i]["num"] << 25 setw(10) << res[i]["weight"] << 26 setw(10) << res[i]["price"] << 27 setw(10) << res[i]["sdate"] << 28 endl; 29 } 30 } 31 else 32 { 33 perror("Failed to get data!"); 34 exit(EXIT_FAILURE); 35 } 36 } 37 else 38 { 39 perror("Connect Failed"); 40 exit(EXIT_FAILURE); 41 } 42 return 0; 43 }
異常
默認情況下,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;
連接選項
MySQL有大量的選項來控制你連接數據庫的方式,以及連接的行為.
打開多重查詢選項,並且建立連接
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()輪詢檢測連接是否關閉,如果關閉,就重新連接