关于使用参数化查询的单行查询结果

时间:2010-07-09 17:56:29

标签: c sqlite

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()

1 个答案:

答案 0 :(得分:1)

我是advocate of preventing SQL injection,但我认为这样做应该是安全的:

sql = sqlite3_mprintf("SELECT ... WHERE id=%d;", atoi(id));

这通过idatoi()字符串解释为整数,因此没有SQL注入的可能性。

至于获取单行或单个标量,我会编写一个包装函数来执行SQL并简单地返回内容。您可能必须使用全局将内容从回调函数传输到包装函数。