C 关于带参数化查询的单行查询结果
例如,我在程序中有几个地方只获取一行(有时甚至是一行中的一列)C 关于带参数化查询的单行查询结果,c,sqlite,C,Sqlite,例如,我在程序中有几个地方只获取一行(有时甚至是一行中的一列) SELECT id,title,posted FROM posts WHERE id=4; 因为这只会返回一行(除非我不喜欢数据库的东西,并且不知何故设法获得了重复的ID),所以我觉得用整个sqlite3\u prepare\u v2(…),sqlite3\u bind\u int(…),sqlite3\u step(…),sqlite3\u finalize(…)的方法来获取这一行太过分了 我知道这可以通过sqlite3\u e
SELECT id,title,posted FROM posts WHERE id=4;
因为这只会返回一行(除非我不喜欢数据库的东西,并且不知何故设法获得了重复的ID),所以我觉得用整个sqlite3\u prepare\u v2(…)
,sqlite3\u bind\u int(…)
,sqlite3\u step(…)
,sqlite3\u finalize(…)
的方法来获取这一行太过分了
我知道这可以通过sqlite3\u exec(…)
完成,并使用回调函数处理返回1的结果代码>,以中止进一步执行,但这在我的情况下不起作用,因为我的查询如下所示:
SELECT id,title,posted FROM posts WHERE id=?;
您不能使用sqlite3\u exec(…)
进行参数化查询。通过某种printf(…)
插入ID在这里也不安全
这就是我现在正在做的
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]);
}
}
在我的例子中,这只是返回“5”。不多也不少。特别是在这里,整个prepare、bind、step、finalize过程真的有些过分,但我必须这样做,因为我的查询看起来像
SELECT MIN(id) FROM posts WHERE id > ?;
例如,获取当前ID之后的下一个ID。当当前ID为“4”时,它只返回“5”
总而言之:有没有一种快速的方法可以从SELECT
语句中获取单行结果,而无需显式循环,直到从sqlite3\u step()
接收到SQLITE\u DONE
,以及如何获取单行、单列值(基本上是skalar),而无需再次执行整个过程,包括调用sqlite\u column…?我是一个,但我认为这样做应该是安全的:
sql = sqlite3_mprintf("SELECT ... WHERE id=%d;", atoi(id));
这将通过atoi()
将id
字符串解释为整数,因此不存在SQL注入的可能性
至于获取一行或一个标量,我将编写一个包装器函数来执行SQL并简单地返回内容。您可能必须使用全局函数将内容从回调函数传输到包装函数。为什么不在此处插入sprintf安全的id?如果没有其他内容。。。我会重新考虑这一点,使所有的SQL管理都在一个函数中完成,这样当我实际使用它时,它是一个单行调用。@不,它是一个CGI脚本,ID是通过URL提供的。虽然我可以通过简单地将ID转换为实际数字而不是将其保留为字符串来实现这一点,但我迟早会再次面临这些问题:)我认为这是实现这一点的最佳方法。顺便说一句,请阅读有关SQL注入的详细信息。现在我又多疑了(你不需要偏执,你只需要有条不紊,确保你已经使用过滤、引用或参数化处理了每一个不安全的输入。
sql = sqlite3_mprintf("SELECT ... WHERE id=%d;", atoi(id));