我正在实现一个接收任何SQL语句然后执行它的函数。
void dbExec(std::string str, bool vertical)
{
sqlite3 *db; // Create db object
char *zErrMsg = 0;
int rc;
const char *sql = str.c_str(); // Convert string to char
sqlite3_stmt *stmt = NULL; // SQL statement
/* Open Database */
rc = sqlite3_open("db/survey.db",&db);
if (rc)
{
fprintf(stderr, "DBOPEN_ERR: %s\n", sqlite3_errmsg(db));
}
/* Execute SQL statement */
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); // Prepare statement
if (rc != SQLITE_OK )
{ // Check error
fprintf(stderr, "DB error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
int cols = sqlite3_column_count(stmt); // Number of columns
const char *data = NULL; // data char pointer
if (vertical)
{
sqlite3_step( stmt );
for (int i = 0; i < cols; i++)
{
// Print column name and info
data = (const char*)sqlite3_column_text( stmt, i );
std::cout << std::setw(20) << sqlite3_column_name(stmt,i)
<< std::setw(30) << (data ? data : "[NULL]" );
printf("\n");
}
}
else
{
for (int i = 0; i < cols; i++)
{
// Print column name
std::cout << std::setw(15) << sqlite3_column_name(stmt,i);
}
printf("\n");
while ( sqlite3_step( stmt ) == SQLITE_ROW )
{
// print each row
for (int i = 0; i < cols; i++)
{
data = (const char*)sqlite3_column_text( stmt, i );
std::cout << std::setw(15) << (data ? data : "[NULL]" );
}
printf("\n");
}
}
/* Close Database */
sqlite3_close(db);
}
当str
参数为:
SELECT * FROM TABLE
它完美无缺。如果str
参数是:
INSERT INTO TABLE (COL1) VALUES(100)
它没有用。
但是,如果在函数内部我添加以下行:
str = "INSERT INTO TABLE (COL1) VALUES(100)";
它完美无缺。我尝试了很多东西,但我仍然无法弄清楚发生了什么......有什么想法吗?
谢谢!
编辑:
以这种方式调用函数dbExec
:
void addBorehole()
{
std::string statement;
statement = "INSERT INTO BOREHOLE (TOTAL_DEPTH) VALUES (45)";
dbExec(statement, false);
}
答案 0 :(得分:0)
您的问题是数据库正忙(SQLITE_BUSY
)。 documentation sais:
[...] SQLITE_BUSY表示与单独的数据库连接发生冲突,可能是在单独的进程中[...]
因此必须有一个阻止数据库的进程。 要获取阻止数据库的进程,您可以执行以下操作(从Stack Exchange网络复制)。
<强> Linux: 强>
$ fuser development.db
此命令将显示锁定文件的进程:
&GT; development.db:5430
刚刚杀死这个过程...
kill -9 5430
<强> Windows: 强>
PowerShell方法:
IF((Test-Path -Path $FileOrFolderPath) -eq $false) { Write-Warning "File or directory does not exist." } Else { $LockingProcess = CMD /C "openfiles /query /fo table | find /I ""$FileOrFolderPath""" Write-Host $LockingProcess }
更多详情How to find out which process is locking a file or folder in Windows
Windows的另一种方法是使用ProcessExplorer。
答案 1 :(得分:0)
好的,通过在关闭数据库之前编写以下行来解决问题:
sqlite3_finalize( stmt );
信息:https://sqlite.org/c3ref/close.html
如果数据库连接与未完成的准备相关联 语句或未完成的sqlite3_backup对象然后sqlite3_close() 将保持数据库连接打开并返回SQLITE_BUSY。
然而,当我在函数内部硬编码语句时,我仍然无法理解它的工作原理。
谢谢!