2012-01-24 53 views
2

我只用C++的sqlite3庫玩了幾天,但它給我帶來了很大的挫折感。C++ sqlite3綁定參數

我想定義一個參數化的CREATE TABLE,稍後將參數綁定到它。它看起來是這樣的:

const char[] CREATE_SQL = 
    "CRAETE TABLE t1 (" 
    " name VARCHAR(:NAME_LEN)" 
    " other VARCHAR(:OTHER_LEN)" 
    ");"; 

的想法是,在不同的文件中(在.cpp這個頭文件),我就可以將這些參數與綁定:

int index = sqlite3_bind_parameter_index(stmt, ":NAME_LEN"); 
sqlite3_bind_int(stmt, index, _DB_FIELD_SIZE_NAME); 

其中_DB_FIELD_SIZE_NAME也在其他地方定義。

我不想使用sprintf()%d代替:NAME_LEN:OTHER_LENCREATE_SQL,因爲我可能會改變參數的順序或添加新的和我想保持綁定明確。

現在,對於問題:我的準備不會返回SQLITE_OK,但會導致sqlite3_stmt的空指針。下面是我有:

sqlite3_stmt *stmt; 
const char *pStmt = 0; 
if(SQLITE_OK != sqlite3_prepare_v2(*db, CREATE_SQL, -1, &stmt, &pStmt)) 
    // throws exception with the sqlite3_errmsg(*db) text 

所以,我得到的錯誤是這樣的:

near ":NAME_LEN": syntax error 

我在做什麼錯?我確信數據庫連接打開OK。

+2

你有一個錯字:「CRAETE」 - >「CREATE」。這*可能是錯的。 – zwol

回答

0

爲了不回答你的問題,sqlite沒有嚴格的文本列大小。它爲了兼容性而接受VARCHAR類型,但其行爲沒有差異。

你永遠與此等價的東西結束:

const char *sql = 
    "CREATE TABLE t1 (" 
    " name TEXT" 
    " ,other TEXT" 
    ");"; 

要回答你的問題,我不相信你被允許這樣做。 Sqlite的替代機制僅適用於通常被視爲值參數的內容。

例如,您通常會在INSERTUPDATE聲明中看到的內容。

const char *sql = "INSERT INTO foo (a,b) VALUES (?1,?);"; 

我不記得,如果你能在CREATE聲明缺省參數做他們的所有,也許?有段時間了。

我發現boost::format比我嘗試更改非價值參數時嘗試創建更清晰的代碼的可能性要小得多。

#include <boost/format.hpp> 

// ... 

int instance_id = 42; 
const char *sql = "CREATE TABLE type_%1% (a,b);"; 
boost::str(boost::format(sql) % instance_id); 

我肯定會鼓勵你避免做非價值參數替代,除非你絕對到。這是一個維護麻煩和容易出錯。

+0

啊,我明白了。你是對的,我只是沒有意識到'TEXT'字段都是一樣的。 謝謝! – StokedOver9k