我有两个或更多数据库连接到一个SQLite数据库连接。每个数据库由3个表组成。为了更好地访问搜索/过滤,我在所有表和数据库上创建了一个巨大的临时表,如下所示:
"CREATE TEMPORARY TABLE temp_table AS "
"SELECT * FROM pb.name_table "
"LEFT JOIN pb.phone_table ON (pb.name_table.id=pb.phone_table.id) " \
"LEFT JOIN pb.email_table ON (pb.name_table.id=pb.email_table.id) " \
"UNION SELECT * FROM name_table " \<br>
"LEFT JOIN phone_table ON (name_table.id=phone_table.id) " \
"LEFT JOIN email_table ON (name_table.id=email_table.id);";
如果表中的内容发生了变化,我必须重新创建临时表。
随着数据量的增加,创建临时表需要一些时间,但由于我对表有持续的读访问权,我的想法如下:
现在的问题是:创建临时表是对数据库的写访问权限,它也会自动阻止所有读取线程。
有谁知道如何处理这个问题?我在重新创建临时表时需要读访问权。
答案 0 :(得分:0)
只要所有线程都是同一程序的一部分,您就可以控制所有数据库连接。 因此,您可以在完全独立的数据库中编写数据,并且ATTACH很快就可以了。
答案 1 :(得分:0)
非常感谢您的回答。我更改了我的代码并发现我需要在工作线程中使用新的数据库连接(sqlite3_open)来阻止其他线程。也无法在附加的“临时数据库”中创建TEMPORARY TABLE,因为创建临时表不允许使用限定符(例如:x.temp_table),因此我必须创建一个真正的表,其中消耗了大量内存我们的flash文件系统(不允许)。
可是等等!我有个主意
(2小时后)
我做的!我打开一个空数据库并将相关数据库附加到连接。我在空数据库中创建了一个临时表,它在flash中不占用内存,因为它是临时的
当我必须创建一个新表时,我打开另一个空数据库并将相关数据库附加到连接。操作完成后,我切换旧连接和新连接。代码如下:
#include <iostream>
#include "dbAccess.h"
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
bool inProgress = true;
DWORD WINAPI createTempTableThread(void *param);
int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
cout << "*";
return 0;
}
int main(void)
{
sqlite3* db = NULL;
HANDLE hThreadHandle = NULL;
CdbAccess *dba = new CdbAccess();
int i = 0;
db = dba->dbaConnect();
dba->dbaSetDatabase(db);
cout << "INFO: Creating initial temporary table. " << endl;
sqlite3_exec(dba->dbaGetDatabase(), "CREATE TEMPORARY TABLE temp_table AS " \
"SELECT * FROM pb.name_table " \
"LEFT JOIN pb.phone_table ON (pb.name_table.id=pb.phone_table.id) " \
"LEFT JOIN pb.email_table ON (pb.name_table.id=pb.email_table.id) " \
"UNION SELECT * FROM intern.name_table " \
"LEFT JOIN intern.phone_table ON (intern.name_table.id=intern.phone_table.id) " \
"LEFT JOIN intern.email_table ON (intern.name_table.id=email_intern.table.id);", NULL, NULL, NULL);
cout << "INFO: Creating initial temporary table finished. " << endl;
while(1)
{
hThreadHandle = CreateThread(0, 0, createTempTableThread, dba, 0, 0);
while(inProgress)
{
sqlite3_exec(dba->dbaGetDatabase(), "SELECT * FROM name_table WHERE id LIKE 1;", callback, NULL, NULL);
}
for(i = 0; i < 5; i++)
{
sqlite3_exec(dba->dbaGetDatabase(), "SELECT * FROM name_table WHERE id LIKE 2;", callback, NULL, NULL);
}
inProgress = true;
CloseHandle(hThreadHandle);
}
dba->dbaDisconnect();
return 0;
}
CdbAccess::CdbAccess()
{
hSemaphore = CreateSemaphore(NULL, 1, 1, 0);
}
CdbAccess::~CdbAccess()
{
}
sqlite3 *CdbAccess::dbaConnect()
{
sqlite3 *db;
static int num = 1;
int err = SQLITE_OK;
string attach = "ATTACH DATABASE \"";
string internal = "cbInternal.db";
if(num == 1)
{
cout << endl << "INFO: cbTemp1.db";
err = sqlite3_open("cbTemp1.db", &db);
num = 2;
}
else
{
cout << endl << "INFO: cbTemp2.db";
err = sqlite3_open("cbTemp2.db", &db);
num = 1;
}
if(err == SQLITE_OK)
{
cout << endl << "INFO: Temp database opened.";
err = sqlite3_exec(db, "ATTACH DATABASE \"cbInternal.db\" AS intern;", NULL, NULL, NULL);
if(err == SQLITE_OK)
{
cout << endl << "INFO: Internal database attached.";
err = sqlite3_exec(db, "ATTACH DATABASE \"0123456789.db\" AS pb;", NULL, NULL, NULL);
if(err == SQLITE_OK)
{
cout << endl << "INFO: Phone book attached.";
}
else
{
cout << endl << "ERROR: Attaching phone book: " << sqlite3_errmsg(db);
}
}
else
{
cout << endl << "ERROR: Attaching internal database: " << sqlite3_errmsg(db);
}
}
else
{
cout << endl << "ERROR: Opening database: " << sqlite3_errmsg(db);
}
return db;
}
int CdbAccess::dbaDisconnect(void)
{
int err = SQLITE_OK;
err = sqlite3_exec(db, "DETACH DATABASE pb;", NULL, NULL, NULL);
if(err == SQLITE_OK)
{
cout << endl << "INFO: Phone book detached.";
err = sqlite3_exec(db, "DETACH DATABASE intern;", NULL, NULL, NULL);
if(err == SQLITE_OK)
{
cout << endl << "INFO: Internal database detached.";
err = sqlite3_close(db);
if(err == SQLITE_OK)
{
cout << endl << "INFO: Database connection closed.";
}
else
{
cout << endl << "ERROR: Could not close database: " << sqlite3_errmsg(db);
}
}
else
{
cout << endl << "ERROR: Could not detach internal database: " << sqlite3_errmsg(db);
}
}
else
{
cout << endl << "ERROR: Could not detach phone book: " << sqlite3_errmsg(db);
}
return err;
}
sqlite3* CdbAccess::dbaGetDatabase(void)
{
return db;
}
void CdbAccess::dbaSetDatabase(sqlite3 * sqldb)
{
db = sqldb;
}
int CdbAccess::dbaGetTempTableAccess(void)
{
cout << endl << "INFO: Access requested.";
WaitForSingleObject(hSemaphore, INFINITE);
return 0;
}
int CdbAccess::dbaReleaseTempTableAccess(void)
{
cout << endl << "INFO: Access released.";
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
DWORD WINAPI createTempTableThread(void *param)
{
int err = SQLITE_OK;
CdbAccess *d = (CdbAccess *)param;
sqlite3 *db;
cout << endl << "INFO: createTempTable: IN";
inProgress = true; // global variable for test porpose only
db = d->dbaConnect();
if(db != NULL)
{
cout << endl << "Thread: INFO: Creating temporary table. ";
err = sqlite3_exec(db, "CREATE TEMPORARY TABLE temp_table AS " \
"SELECT * FROM pb.name_table " \
"LEFT JOIN pb.phone_table ON (pb.name_table.id=pb.phone_table.id) " \
"LEFT JOIN pb.email_table ON (pb.name_table.id=pb.email_table.id) " \
"UNION SELECT * FROM intern.name_table " \
"LEFT JOIN intern.phone_table ON (intern.name_table.id=intern.phone_table.id) " \
"LEFT JOIN intern.email_table ON (intern.name_table.id=intern.email_table.id);", NULL, NULL, NULL);
}
if(err != SQLITE_OK)
{
cout << endl << "Thread: ERROR: Creating temporary table: " << sqlite3_errmsg(db);
}
else
{
cout << endl << "Thread: INFO: Creating temporary table finished. ";
}
d->dbaSetDatabase(db);
inProgress = false; // global variable for test porpose only
cout << endl << "Thread: INFO: createTempTable: OUT";
return 0;
}