Soo,我在我的程序中有一些地方,我只需要获取一行(有时甚至是单行中的一列),例如
SELECT id,title,posted FROM posts WHERE id=4;
因为这只会返回一行(除非我吮吸数据库的东西,并以某种方式设法有重复的ID)我觉得整个sqlite3_prepare_v2(...)
,sqlite3_bind_int(...)
,{{1}是过分的},sqlite3_step(...)
只是为了获取单行。
我知道可以使用sqlite3_finalize(...)
并使用回调函数处理结果sqlite3_exec(...)
以中止进一步的执行,但这不适用于我的情况,因为我的查询看起来像这样:
return 1;
您无法使用SELECT id,title,posted FROM posts WHERE id=?;
进行参数化查询。通过某种sqlite3_exec(...)
插入ID也不安全。
所以,这就是我现在正在做的事情
printf(...)
我对此代码的问题是,我调用了char *sql;
sqlite3_stmt *stmt;
sql = sqlite3_mprintf(
"SELECT \
title, \
((julianday(posted) - 2440587.5) * 86400), \
text \
FROM \
%s \
WHERE id=?;",
POSTS_TABLE); /* printf safe here, POSTS_TABLE is a #define */
if (sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL) != SQLITE_OK)
show_sqlite_error(db);
else
{
sqlite3_bind_text(stmt, 1, id, strlen(id), SQLITE_TRANSIENT);
sqlite_code = sqlite3_step(stmt); /* This right here seems just ugly */
if (sqlite_code != SQLITE_ROW) /* especially this */
printf("<div id=\"error\">ERROR: No such ID in database</div>\n");
else
{
int i;
char time_string[25];
const unsigned char *title = sqlite3_column_text(stmt, 0);
time_t time = sqlite3_column_int(stmt, 1);
const unsigned char *text = sqlite3_column_text(stmt, 2);
strftime(time_string, 25, DATE_FORMAT, gmtime(&time));
printf("<h2 id=\"post_headline\">%s</h2>\n\n", title);
printf("<h3 id=\"post_time\">%s</h3>\n", time_string);
printf("<p id=\"post_body\">\n");
for (i = 0; i < strlen((char *)text); i++)
if (text[i] == '\n')
printf("<br />");
else
printf("%c", text[i]);
}
}
一次,如果返回了除sqlite3_step()
以外的所有内容时出错,显示返回SQLITE_ROW
时需要显示的内容,并调用最终确定而没有实际步入SQLITE_ROW
。虽然这(因为我被告知)不会对SQLITE_DONE
声明造成任何伤害,但它感觉丑陋和矫枉过正。
另一件事是只返回单个值的查询。
SELECT
在我的情况下,这只是返回“5”。不多也不少。特别是在这里,整个准备,绑定,步骤,最终确定方式真的太过分了,但我必须这样做,因为我的查询再次看起来像
SELECT MAX(id) FROM posts;
例如,获取当前ID之后的下一个ID。当前ID为“4”时,它只返回“5”。
总结一下:有没有一种快速方法可以从SELECT MIN(id) FROM posts WHERE id > ?;
语句中获取单行结果,而不会在SELECT
收到SQLITE_DONE
之前显式循环,如何获取单行,单列值(基本上是skalar),而不是一路走来,包括调用sqlite3_step()
?
答案 0 :(得分:1)
我是advocate of preventing SQL injection,但我认为这样做应该是安全的:
sql = sqlite3_mprintf("SELECT ... WHERE id=%d;", atoi(id));
这通过id
将atoi()
字符串解释为整数,因此没有SQL注入的可能性。
至于获取单行或单个标量,我会编写一个包装函数来执行SQL并简单地返回内容。您可能必须使用全局将内容从回调函数传输到包装函数。