【问题标题】:How can I set a variable placeholder inside a String in C如何在 C 中的字符串内设置变量占位符
【发布时间】:2018-04-25 07:51:38
【问题描述】:

如何在 C 中的字符串中设置变量占位符?

例如,从变量 int id = 1234 设置 ID

sql = "INSERT INTO REV_ENTITY (ID, NAME, AGE, ADDRESS, SALARY)" \
          "VALUES (99, 'John Doe', 25, 'Rich-Mond ', 65000.00 );";

更新

我想要一个包含变量值的最终字符串。

按照建议,这不起作用:

sql = "INSERT INTO REV_ENTITY (ID,NAME,AGE,ADDRESS,SALARY)" \  
    "VALUES (%d, 'REV', 25, 'Rich-Mond ', 65000.00 );";  

rc = sqlite3_exec(db, printf(sql, 999), callback, 0, &zErrMsg);  

我想要在 Java 中这样的东西:

String string = String.format("A string %s", aVariable);

【问题讨论】:

  • snprintf?或者使用特定于数据库的 API 变量绑定(几乎所有数据库 API 都有)?
  • 也许您想查看printf及其兄弟。
  • 看看SQLite prepared statements。准备一个语句然后绑定参数。在运行时构建自己的 sql 是一个坏主意,可能会导致 SQL 注入漏洞。
  • 可能与this question重复。
  • 不完全是(关于 mysql)。之前使用过 sqlite 的人不能在这里写一个 good 答案吗? ;)

标签: c string variables sqlite


【解决方案1】:

除了另一个答案中提到的snprintf,您还可以使用 sqlite3 API 中的char *sqlite3_mprintf(const char*,...) 函数。它使用 sqlite printf 内置函数并使用 sqlite3_malloc64() 为字符串分配内存。如果一切顺利,则返回指向字符串的指针,否则返回NULL

int id = 999;
char *sql;
sql = sqlite3_mprintf("INSERT INTO REV_ENTITY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (%d, 'REV', 25, 'Rich-Mond ', 65000.00 )", id);
if (sql != NULL) {
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if (rc != SQLITE3_OK)
        /* Do some error handling. */
    sqlite3_free(sql);
}

printf 函数系列不同,如果格式与参数不相关,sqlite3_mprintf 没有权限报告。所以,如果碰巧你使用 GCC 编译器,添加以下代码会很有用:

extern char *sqlite3_mprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));

cmets 中推荐的另一个解决方案是使用 sqlite3 的准备、步骤和完成功能:

int id = 999;
sqlite3_stmt *stmt = NULL;
char *sql = "INSERT INTO REV_ENTITY (ID,NAME,AGE,ADDRESS,SALARY) " \
            " VALUES (?, 'REV', 25, 'Rich-Mond ', 65000.00 )";
sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);
/* Bind id. */
sqlite3_bind_int(stmt, 1, id);
if (sqlite3_step(stmt) == SQLITE_DONE) {
    printf("Insertion success\n");
} else {
    fprintf(stderr, "Insertion error\n");
}
/* Finalize and destroy statement. */
sqlite3_finalize(stmt);

【讨论】:

    【解决方案2】:

    使用snprintf,伪代码如下:

    int idValue = 1234;
    snprintf(buffer, bufferLength, "insert bla bla VALUES (%d, 'John Doe', 25, 'Rich-Mond ', 65000.00 )", idValue);
    sqli_execute(buffer);
    

    在你的情况下,它看起来像:

    //initialize sql variable before sprintfing into it
    snprintf(sql, maximumSqlBufferLength "INSERT INTO REV_ENTITY (ID, NAME, AGE, ADDRESS, SALARY) VALUES (%d, 'John Doe', 25, 'Rich-Mond ', 65000.00 );", id);
    

    【讨论】:

    • 一般来说避免sprintf,首选snprintf以避免缓冲区溢出。
    • 我不知道 sqlite API,但我强烈认为它具有参数化/准备好的语句。在这种情况下,您的回答是非常糟糕的建议。
    • @FelixPalmen 这正是 OP 所要求的 - 他没有要求参数化查询,同样通过他给出的示例,我可以假设他想要在字符串中的给定位置插入变量值的方法跨度>
    • 刚刚google了一下:sqlite.org/c3ref/bind_blob.html --- 从不如果你有一个体面的API来绑定参数,就使用你自己的“sql string building”。 SQL 注入指日可待!
    • 一个好的答案应该给出好的建议。这是个坏建议,恕我直言。 OPs java 代码当然也一样糟糕。
    猜你喜欢
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多