从输入表单数据库查询

时间:2012-12-22 22:05:07

标签: c database informix

在我的C程序中,我收到的输入格式为

     "name,age,salary|Richard,35,10000"

现在我想从此输入框架插入和更新查询。

我正在使用strtok_rstrtok来实现此目的。

但我的问题是,在插入或更新时,我必须在varchar数据类型周围使用双引号,如“Richard”。

输入没有固定的模式,它可以是任何顺序。

  • 我是否每次都要检查每列的数据类型?

  • 有更好的方法吗?

我使用的数据库是Informix。我使用的是ESQL / C,它是带有嵌入式SQL扩展的旧C。

1 个答案:

答案 0 :(得分:1)

处理此问题的最佳方法是通过主机变量,这意味着您不需要围绕值进行引用。 Informix非常适合将字符串转换为其他类型;你遇到麻烦的唯一类型就是blob - BYTE,TEXT,BLOB,CLOB。

此代码仅已编译;它还没有被执行。各种return语句是错误返回,除了最后一个。我们可以辩论在不释放准备好的陈述的情况下返回是否正确;很容易争辩说它不是。几乎可以肯定,有几个例程是由这个怪物构建的。

#include "sqlca.h"
#include "sqlda.h"
#include "sqltypes.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>

extern int insert_record(char *line, const char *tabname);

int insert_record(char *line, const char *tabname)
{
    /* Analyze line */
    char *pipe = strchr(line, '|');
    char *comma = line;
    int c_count = 0;
    int v_count = 0;
    while ((comma = strchr(comma, ',')) != 0 && comma < pipe)
        c_count++;
    comma = pipe;
    while ((comma = strchr(comma, ',')) != 0)
        v_count++;
    if (v_count != c_count)
        return(-1);
    char *names[c_count];
    char *value[c_count];
    char *np = line;
    char *vp = pipe+1;
    for (int i = 0; i < c_count; i++)
    {
        names[i] = np;
        value[i] = vp;
        char *sep = strchr(np, ',');
        assert(sep != 0);
        if (sep > pipe)
            sep = pipe;
        *sep = '\0';
        np = sep + 1;
        sep = strchr(vp, ',');
        if (sep != 0)
        {
            *sep = '\0';
            vp = sep + 1;
        }
    }

    /* Create SQL statement with placeholders */
    /* names[i] contains column name for entry i; value[i] contains the value */
    $ char buffer[4096];
    char *sql = buffer;
    int len = sizeof(buffer) - 1;
    int num = snprintf(sql, len, "insert into %s", tabname);
    if (num <= 0 || num >= len)
        return(-2);
    if (num <= 0 || num >= len)
        return(-2);
    sql += num;
    len -= num;
    pad = "(";
    for (int i = 0; i < c_count; i++)
    {
        num = snprintf(sql, len, "%s%s", pad, "?");
        if (num <= 0 || num >= len)
            return(-2);
        sql += num;
        len -= num;
    }
    num = snprintf(sql, len, ")");
    if (num <= 0 || num >= len)
        return(-2);

    $ PREPARE p_insert FROM :buffer;
    if (sqlca.sqlcode != 0)
        return(sqlca.sqlcode);

    /* Create sqlda to describe strings */
    ifx_sqlda_t data;
    ifx_sqlvar_t columns[c_count];
    $ struct sqlda *udesc = &data;
    data.sqld = c_count;
    data.sqlvar = columns;
    data.desc_name[0] = '\0';
    data.desc_occ = 0;
    data.reserved = 0;
    data.desc_next = 0;
    for (int i = 0; i < c_count; i++)
    {
        columns[i].sqltype       = SQLVCHAR;
        columns[i].sqllen        = strlen(value[i]);
        columns[i].sqldata       = value[i];
        columns[i].sqlind        = 0;
        columns[i].sqlname       = names[i];
        columns[i].sqlformat     = 0;
        columns[i].sqlitype      = 0;
        columns[i].sqlilen       = 0;
        columns[i].sqlidata      = 0;
        columns[i].sqlxid        = 0;
        columns[i].sqltypename   = 0;
        columns[i].sqltypelen    = 0;
        columns[i].sqlownerlen   = 0;
        columns[i].sqlsourcetype = 0;
        columns[i].sqlownername  = 0;
        columns[i].sqlsourceid   = 0;
        columns[i].sqlilongdata  = 0;
        columns[i].sqlflags      = 0;
        columns[i].sqlreserved   = 0;
    }

    /* Execute the SQL and clean up */
    $ EXECUTE p_insert USING DESCRIPTOR udesc;
    if (sqlca.sqlcode != 0)
        return(sqlca.sqlcode);
    $ FREE p_insert;
    if (sqlca.sqlcode != 0)
        return(sqlca.sqlcode);
    return(0);
}