Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 关于带参数化查询的单行查询结果_C_Sqlite - Fatal编程技术网

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