BLOB을 사용하여 SQLite 데이터베이스에 개체를 삽입합니다. 삽입 후 "SQLite Database Browser"를 사용하여 데이터베이스를 탐색 할 때 "TASK_HEAD"행이 "Empty"이지만 "SELECT"문장으로 데이터를 가져올 수 있습니다. 그러나 방금 삽입 한 개체를 파괴하면 "pHead"포인터가 "id"멤버의 내용이 "铪 铪 铪 铪 is"인 주소를 가리키고 올바른 데이터를 더 이상 얻을 수 없습니다铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 铪 " 디버그 모드에서 VS2008에서 읽을 때. 여기 BLOB 데이터를 SQLite 데이터베이스에 성공적으로 삽입했으나 삽입 된 데이터를 가져올 수 없습니다.
은 예입니다 : 처음에 나는 그것이 sqlite3_bind_blob에 전달 바이트의 문제가 될 거라고 생각// user-defined data type
typedef std::string TASK_ID;
struct TASK_HEAD
{
TASK_ID id;
std::string userData;
int Size()
{
return (id.size() + userData.size()) * sizeof(TCHAR);
}
};
// when TEST_INSIDE is defined, pHead is invalid; but if undef it, I can get the "head" I just inserted
// and if the blob data is a string (when USING_STRING is defined), I can get the string inserted into the db even though the "test" string has been destroyed
void CDBWriter::WriteTestData()
{
// open db
sqlite3* db = NULL;
int nRet = sqlite3_open(DATABASE_NAME.c_str(), &db);
if (nRet != SQLITE_OK)
{
return;
}
if (db != NULL)
{
// create a table
std::string cmdCreate("CREATE TABLE IF NOT EXISTS testTable (id TEXT NOT NULL, TASK_HEAD BLOB, PRIMARY KEY(id));");
char* errMsg = NULL;
nRet = sqlite3_exec(db , cmdCreate.c_str() , 0 , 0 , &errMsg);
if(errMsg != NULL)
{
sqlite3_free(errMsg);
errMsg = NULL;
return;
}
//#define USING_STRING
#define TEST_INSIDE
#ifndef TEST_INSIDE
TASK_HEAD head;
#endif // TEST_INSIDE
// insert blob data
const TASK_ID newID(NewGUID()); // NewGUID returns string like this: "5811307F-7AA7-4C44-831F-774FC5832627"
string query = "INSERT OR REPLACE INTO testTable (id, TASK_HEAD) VALUES ('";
query += newID;
query += "', ?1);";
sqlite3_stmt* res = NULL;
nRet = sqlite3_prepare_v2(db, query.c_str(), query.length(), &res, 0);
{
#ifdef TEST_INSIDE
TASK_HEAD head;
#endif // TEST_INSIDE
head.id = newID;
#ifdef USING_STRING
std::string test("ewsjoafijdoaijeofsafsd");
nRet = sqlite3_bind_blob (res, 1, test.c_str(), test.size(), SQLITE_TRANSIENT);
#else
int nsizeHead = sizeof(head);
int nSizeHeadSt = sizeof(TASK_HEAD);
int sizeString = sizeof(std::string);
size_t nLen = newID.size();
//nRet = sqlite3_bind_blob (res, 1, &head, sizeof(head), SQLITE_TRANSIENT);
nRet = sqlite3_bind_blob (res, 1, &head, head.Size(), SQLITE_TRANSIENT);
#endif // USING_STRING
if (SQLITE_OK == nRet)
{
nRet = sqlite3_step(res);
}
if (nRet != SQLITE_OK && nRet != SQLITE_DONE)
{
return;
}
}
// get all columns in the database
query = "SELECT * FROM testTable;";
nRet = sqlite3_prepare_v2 (db, query.c_str(), query.length(), &res, 0);
if (SQLITE_OK == nRet)
{
while (SQLITE_ROW == sqlite3_step(res))
{
#ifdef USING_STRING
const char* pHead = (const char*)sqlite3_column_blob(res, 1);
#else
const TASK_HEAD *pHead = (const TASK_HEAD*)sqlite3_column_blob(res, 1);
#endif // USING_STRING
continue;
}
}
sqlite3_finalize(res);
sqlite3_close(db);
}
}
, 그래서 당신은 여기에서 볼 수 있듯이 나는 바보 같은 방법으로 객체의 바이트를 얻을 (TASK_HEAD의 size() 함수). 그러나 그것은 도움이되지 않습니다. 그런 다음 SQLITE_TRANSIENT 대신 SQLITE_STATIC을 사용하려고했지만 여전히 작동하지 않습니다. 무엇이 잘못 되었나요?
Ps : db에 객체를 삽입하는 것은 좋지 않은 해결책이며, 왜 db에 삽입 된 데이터를 다시 읽을 수 없는지 알고 싶습니다.
대단히 감사합니다! 그것은 많은 도움이됩니다.BTW, BLOB 데이터에 대한 소개가 추가되었습니다 (포인터와 동적 버퍼로 빌드 할 수없는 이유는 무엇입니까?). – YoungLearner
http://en.wikipedia.org/wiki/Serialization –
감사합니다. 도움이됩니다. – YoungLearner