專用SQL結構(SSQLS) 特性可以讓你很輕易的定義用來匹配SQL表的C++結構.最通俗的理解:對於SQL表中的每一個字段,SSQLS結構都有一個變量與之對應.但是,MySQL++內部也會使用SSQLS的其他方法,操作符來提供簡潔的功能.
要定義SSQLSes,需要使用定義在ssqls.h中的宏,這也是MySQL++唯一沒有自動加入mysql++.h的頭文件.
sql_create
假如你有如下SQL表
CREATE TABLE stock ( item CHAR(30) NOT NULL, num BIGINT NOT NULL, weight DOUBLE NOT NULL, price DECIMAL(6,2) NOT NULL, sdate DATE NOT NULL, description MEDIUMTEXT NULL)
你可以定義一個對應的C++結構如下
sql_create_6(stock, 1, 6, mysqlpp::sql_char, item, mysqlpp::sql_bigint, num, mysqlpp::sql_double, weight, mysqlpp::sql_decimal, price, mysqlpp::sql_date, sdate, mysqlpp::Null<mysqlpp::sql_mediumtext>, description)
stock結構聲明有着相同名字的數據成員對應SQL的每一列,同時該結構還包含一些成員函數,操作符以及隱藏數據成員.
sql_create_#
call調用中,字段名稱前面的是C++數據類型.
有時候你必須使用MySQL++的特殊數據類型來對應數據結構,考慮description字段的類型,MySQL++的 sql_mediumtext類型就是std::string的一個等價.
通常結構如下:
sql_create_#(NAME, COMPCOUNT, SETCOUNT, TYPE1, ITEM1, ... TYPE#, ITEM#)
“#”是變量的數量,“NAME”是你希望創建的結構名稱,“TYPEx
”是變量類型,“ITEMx
”是變量名稱.
SSQLS對比和初始化
sql_create_#添加了一些成員函數和操作來支持SSQLS對象之間的比較,COMPCOUNT數量表示用來比較的字段的個數,上面例子中為1,意味着只比較item字段,將主鍵放到最前面並且指定比較個數,可以很好利用這一特性.sql_create_#創建的第二個參數是
SETCOUNT,如果非0,它將增加一個構建函數和一個set()成員函數,該函數接受指定參數來設置結構第N個字段的值.
sql_create_6(stock, 1, 2, mysqlpp::sql_char, item, mysqlpp::sql_bigint, num, mysqlpp::sql_double, weight, mysqlpp::sql_decimal, price, mysqlpp::sql_date, sdate, mysqlpp::Null<mysqlpp::sql_mediumtext>, description) stock foo("Hotdog", 52);
COMPCOUNT
和SETCOUNT
的值不可以相等,如果相等,會導致產生參數列表相同的兩個構建函數.
查詢數據
mysqlpp::Query query = conn.query("select item, description from stock"); vector<stock> res; query.storein(res); for(auto i = res.begin(); i != res.end(); i++) { cout << i->item << '\t' ; cout << i->description << endl; }
在定義了SSQLS結構后,可以直接將查詢結構放入相應容器,進行各種操作.
增加數據
//create a stock object stock new_row( "Hot dog", 100, 1.5, 130, mysqlpp::sql_date("2014-11-30"), mysqlpp::null ); //execute a query mysqlpp::Query query = conn.query(); query.insert(new_row); cout << "Query: " << query << endl; query.execute();
首先,創建一個要插入的SSQLS對象,然后,創建查詢對象,最后執行
批量插入也很容易,只要加一個循環即可
vector<stock> lots_of_stuff;
...populate the vector somehow...
query.insert(lots_of_stuff.begin(), lots_of_stuff.end()).execute();
MySQL對於SQL查詢長度有所限制,默認最大為1M.因此,使用insert批量插入時,容器中的查詢長度可能超過限制.
在這種情況下使用Query::insertfrom(),它是INSERT和execute()的組合.
mysqlpp::Query::MaxPacketInsertPolicy<> insert_policy(1000); query.insertfrom(stock_vector.begin(), stock_vector.end(), insert_policy);
它采用最大包策略,該例中指定一個查詢最大為1000,它會自動檢測查詢是否超過限制,然后分割執行查詢.
還有兩個策略類:MaxPacketInsertPolicy和RowCountInsertPolicy,它們都提供了在查詢長度在一定范圍類的策略方法,如果不適用,也可以研究下lib/insertpolicy.*,然后自己寫策略類.策略類本質都是些類模板.
修改數據
//execute a query mysqlpp::Query query = conn.query("select * from stock "); query << "where item = " << mysqlpp::quote << "abc"; //get query result in a storeResult mysqlpp::StoreQueryResult res = query.store(); if(res) { stock row = res[0]; stock orig_row = row; row.item = "hamburger"; query.update(orig_row, row); cout << "Query : " << query <<endl; query.execute(); }
首先取出要修改的記錄,然后修改相應字段,再用新字段代替原字段,執行替換操作.
用關聯容器來存放SSQLS
//execute a query mysqlpp::Query query = conn.query("select * from stock "); //get query result in a storeResult set<stock> res; query.storein(res); if(res.size()) { for(auto i = res.begin(); i != res.end(); ++i) { cout << i->item.c_str() << '\t' << i->num << '\t' << i->price << endl; } }
改變表名
默認情況下,數據庫表和SSQLS結構擁有相同的表名稱.你也可以用如下方法全局修改查詢中使用的表名.
stock::table("MyStockData");
也可以修改每個實例中的表名
stock s;
s.instance_table("AlternateTable");
在多個模塊中使用SSQLS
// File my_ssqls.h: #if !defined(EXPAND_MY_SSQLS_STATICS) # define MYSQLPP_SSQLS_NO_STATICS #endif sql_create_X(Y, Z....) // the SSQLS definition
// File foo.cpp, a mere user of the SSQLS: #include "my_ssqls.h"
// File my_ssqls.cpp, which owns the SSQLS: #define EXPAND_MY_SSQLS_STATICS #include "my_ssqls.h"
利用SSQLS的內部構件
sql_create宏為每個SSQLS定義了一些有用的方法,這些方法大多用於庫內部,以下偽碼展示了一些用法.
// Basic form template <class Manip> stock_value_list<Manip> value_list(cchar *d = ",", Manip m = mysqlpp::quote) const; template <class Manip> stock_field_list<Manip> field_list(cchar *d = ",", Manip m = mysqlpp::do_nothing) const; template <class Manip> stock_equal_list<Manip> equal_list(cchar *d = ",", cchar *e = " = ", Manip m = mysqlpp::quote) const; // Boolean argument form template <class Manip> stock_cus_value_list<Manip> value_list([cchar *d, [Manip m,] ] bool i1, bool i2 = false, ... , bool i5 = false) const; // List form template <class Manip> stock_cus_value_list<Manip> value_list([cchar *d, [Manip m,] ] stock_enum i1, stock_enum i2 = stock_NULL, ..., stock_enum i5 = stock_NULL) const; // Vector form template <class Manip> stock_cus_value_list<Manip> value_list([cchar *d, [Manip m,] ] vector<bool> *i) const; ...Plus the obvious equivalents for field_list() and equal_list()
下面例子演示通過查詢的一條記錄來構建一個查詢
在C++和SQL中使用不同的字段名稱
sql_create_complete_5(stock, 1, 5, mysqlpp::sql_char, m_sItem, "item", mysqlpp::sql_bigint, m_nNum, "num", mysqlpp::sql_double, m_fWeight, "weight", mysqlpp::sql_decimal, m_fPrice, "price", mysqlpp::sql_date, m_Date, "sdate")
繼承自一個SSQLS
sql_create_2( Base, 1, 2, mysqlpp::sql_varchar, a, mysqlpp::sql_int, b ); class Derived : public Base { public: // default constructor[14] Derived() : Base() { } // for-comparison constructor[15] Derived(const mysqlpp::sql_varchar& _a) : Base(_a) { } // full creation constructor Derived(const mysqlpp::sql_varchar& _a, const mysqlpp::sql_int& _b) : Base(_a, _b) { } // population constructor[16] Derived(const mysqlpp::Row& row) : Base(row) { } // functionality added to the SSQLS through inheritance bool do_something_interesting(int data); };