【问题标题】:ODBC write blob example Oracle C++ODBC 写入 blob 示例 Oracle C++
【发布时间】:2012-09-28 16:38:48
【问题描述】:

您能给我一个使用 ODBC API 在 Oracle 数据库中插入 blob 的 C++ 示例吗?这是我第一次使用BLOB 类型,所以它对我来说是抽象的。我对互联网进行了很多研究,现在我脑子里一片混乱。一个例子对我很有帮助。

【问题讨论】:

    标签: c++ oracle insert odbc blob


    【解决方案1】:

    我在 C 中有一个简短的(ish)示例。通过 ODBC 插入 blob 的基本原则是:

    SQLPrepare("insert into mytable (mycolumne) values(?)");
    SQLBindParameter(1, other_args, indicator SQL_LEN_DATA_AT_EXEC(size));
    SQLExecute will return SQL_NEED_DATA
      call SQLParamData to find which parameter data is required for
      call SQLPutData as much as you like in chunks to insert data
      call SQLParamData again to find the next parameter requiring data
    

    在此处的示例代码中,您必须编写自己的 do_a_error() 函数,但它只调用 SQLGetDiagRec。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #if defined (WIN32)
    # include <windows.h>
    # include <io.h>
    #else
    # include <unistd.h>
    #endif
    
    #include <stdio.h>
    #include <sql.h>
    #include <sqlext.h>
    
    #include "helper.h" /* contained do_a_error() defn etc - you won't have this header */
    
    #ifdef WIN32
    # define F_OK 0
    # define W_OK 2
    # define R_OK 4
    # define access _access                          /* file check */
    #endif
    
    static SQLUINTEGER      array_row_counts;
    static SQLUINTEGER      array_selects;
    static SQLUINTEGER      static_ca1;
    static SQLUINTEGER      static_ca2;
    
    unsigned int            debug=0;
    const char              fixed_data_source[] = "example";
    
    #define TEST_FILE "easycd.jpg"
    #define DISPLAY_GIF "/usr/X11/bin/xv"
    
    static short insert_into_table(
        SQLHDBC *hdbc,
        typeinfo_t typeinfo);
    
    
    /************************************************************************/
    /*                                                                      */
    /*  main                                                                */
    /*  ====                                                                */
    /*                                                                      */
    /************************************************************************/
    int main(int argc, char *argv[], char *envp[])
    {
        SQLHENV         henv;                   /* environment handle */
        SQLHDBC         hdbc;                   /* database handle */
        char            *data_source_name;      /* chosen datasource */
        SQLRETURN       ret;                    /* function return status */
        char            in_connection_string[512]; /* SQLDriverConnect string */
        char            out_connection_string[512]; /* returned connection string */
        SQLSMALLINT     out_connection_string_len; /* ... and length */
        unsigned int        i;                      /* loop variable */
        typeinfo_t          typeinfo[100];          /* data type information */
        int                 type_element = -1;
        SQLINTEGER          max_column_size = 0;    /* largest column */
    
        /*
         *  Get the datasource name.
         */
        if (argc > 1)
        {
            for (i = 1; i < argc; i++)
            {
                if (!strcmp (argv[i], "-d")) debug = 1;
            }
            if (((argc > 2) && debug) ||
                ((argc > 1) && !debug))
                data_source_name = argv[argc - 1];
        }
        else
        {
            data_source_name = fixed_data_source;
        }
        sprintf(in_connection_string, "DSN=%s;", data_source_name);
    
        /*
         *  Allocate and set up the environment and connection.
         */
        if (SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv) != SQL_SUCCESS)
        {
            fprintf(stderr, "** Failed to allocate environment **\n");
            exit(1);
        }
        if (SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
                          (SQLPOINTER)SQL_OV_ODBC3, 0) != SQL_SUCCESS)
        {
            do_a_error(SQL_HANDLE_ENV, henv, "SQLSetEnvAttr");
            SQLFreeHandle(SQL_HANDLE_ENV, henv);
            exit(2);
        }
        if (SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc) != SQL_SUCCESS)
        {
            do_a_error(SQL_HANDLE_ENV, henv, "SQLAllocHandle");
            SQLFreeHandle(SQL_HANDLE_ENV, henv);
            exit(3);
        }
    
        ret = SQLDriverConnect(hdbc, NULL,
                               (SQLCHAR *)in_connection_string, SQL_NTS,
                               (SQLCHAR *)out_connection_string,
                               sizeof(out_connection_string),
                               &out_connection_string_len, SQL_DRIVER_COMPLETE);
        if (!SQL_SUCCEEDED(ret))
        {
            do_a_error(SQL_HANDLE_DBC, hdbc, "SQLDriverConnect");
            SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
            SQLFreeHandle(SQL_HANDLE_ENV, henv);
            exit(4);
        }
        if (out_connection_string_len > sizeof(out_connection_string))
        {
            out_connection_string[sizeof(out_connection_string) - 1] = '\0';
        }
        else
        {
            out_connection_string[out_connection_string_len] ='\0';
        }
        printf("%s\n", out_connection_string);
        if (ret == SQL_SUCCESS_WITH_INFO)
        {
            do_a_error(SQL_HANDLE_DBC, hdbc, "SQLDriverConnect");
        }
        /*
         *  Get a list of the types supported.
         */
        memset(typeinfo, '\0', sizeof(typeinfo));
        do_get_info(hdbc, &array_row_counts, &array_selects,
                    &static_ca1, &static_ca2);
    
        if (!SQL_SUCCEEDED(do_type_info(hdbc, typeinfo)))
        {
            SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
            SQLFreeHandle(SQL_HANDLE_ENV, henv);
            exit(5);
        }
        /*
         *  Find a type big enough for our gif image.
         */
        for (i = 0; strlen(typeinfo[i].type_name); i++)
        {
            if ((typeinfo[i].column_size > max_column_size) &&
                (max_column_size != SQL_NO_TOTAL))
            {
                max_column_size = typeinfo[i].column_size;
                type_element = i;
            }
            else
            {
                if (typeinfo[i].column_size == SQL_NO_TOTAL)
                {
                    if (max_column_size != SQL_NO_TOTAL)
                    {
                        max_column_size = SQL_NO_TOTAL;
                        type_element = i;
                    }
                }
            }
        }
        if (type_element < 0) abort();
        if (debug)
            printf("\t Biggest type is %s at %ld in size, requiring \"%s\"\n",
                   typeinfo[type_element].type_name,
                   typeinfo[type_element].column_size,
                   typeinfo[type_element].create_params);
    
        /*
         *  Delete existing table and create a new one.
         */
        ret = do_create_table(hdbc, "\"blob\"", CREATE_TABLE_BIGCOL,
                              typeinfo[type_element].column_size,
                              typeinfo[type_element].type_name,
                              typeinfo[type_element].create_params);
        if (!SQL_SUCCEEDED(ret))
        {
            SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
            SQLFreeHandle(SQL_HANDLE_ENV, henv);
            exit(4);
        }
    
        insert_into_table(hdbc, typeinfo[type_element]);
    
        SQLDisconnect(hdbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
        SQLFreeHandle(SQL_HANDLE_ENV, henv);
    
        return 0;
    
    }
    
    
    /************************************************************************/
    /*                                                                      */
    /*  insert_into_table                                                   */
    /*  =================                                                   */
    /*                                                                      */
    /************************************************************************/
    static short insert_into_table(
        SQLHDBC *hdbc,
        typeinfo_t typeinfo)
    {
        SQLINTEGER      len_ind[2];             /* parameter lengths */
        SQLINTEGER      p1;                     /* first parameter array */
        SQLCHAR         p2[50000];              /* second parameter array */
        SQLINTEGER          row_counts;             /* rows affected */
        SQLRETURN       ret;                    /* function status return */
        unsigned int        row;                    /* current row */
        SQLHSTMT            hstmt;                  /* statement handle */
        char                qbuf[1024];             /* query buffer */
        FILE                *fp;                    /* test file file ptr */
        size_t              readb;                  /* bytes read from test file */
        size_t              writeb;                 /* bytes written to test file */
        SQLINTEGER          retrieved;              /* data retrieved from GetData */
        unsigned int        pos;                    /* position in GetData buffer */
    
        printf("---------- insert_into_table ----------\n");
        printf("-- Creating rows with BIG column data --\n");
    
        if (access(TEST_FILE, R_OK))
        {
            fprintf(stderr, "Can't find test binary %s\n", TEST_FILE);
            return SQL_ERROR;
        }
        if (!(fp = fopen(TEST_FILE, "rb")))
        {
            fprintf(stderr, "Failed to open %s for reading\n", TEST_FILE);
            return SQL_ERROR;
        }
        clearerr(fp);
        readb = fread(p2, 1, sizeof(p2), fp);
        if ((readb == 0) || ferror(fp))
        {
            fprintf(stderr, "Failed to read data from %s\n", TEST_FILE);
            return SQL_ERROR;
        }
        if (readb >= sizeof(p2))
        {
            fprintf(stderr, "%s is too big a file\n", TEST_FILE);
            return SQL_ERROR;
        }
        fclose(fp);
    
        if (SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt) != SQL_SUCCESS)
        {
            do_a_error(SQL_HANDLE_DBC, hdbc, "SQLAllocHandle");
            return SQL_ERROR;
        }
        /*
         *  Delete all the rows.
         */
        sprintf(qbuf, "delete from \"blob\"");
        printf("\"%s\"\n", qbuf);
        ret = SQLExecDirect(hstmt, (SQLCHAR *)qbuf, SQL_NTS);
        if (ret != SQL_SUCCESS)
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLExecDirect");
    
        /*
         *  Create the rows.
         */
        sprintf(qbuf, "insert into \"blob\" (a,b) values(?,?)");
        printf("\"%s\"\n", qbuf);
        if (SQLPrepare(hstmt, (SQLCHAR *)qbuf, SQL_NTS) != SQL_SUCCESS)
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLPrepare");
            return SQL_ERROR;
        }
    
        /*
         *  Bind Parameters
         */
        ret = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
                               5, 0, &p1, 0, &len_ind[0]);
        if (!SQL_SUCCEEDED(ret))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLBindParameter");
            return ret;
        }
        ret = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
                               typeinfo.sql_data_type,
                               sizeof(p2), 0, (SQLPOINTER)2, 0,
                               &len_ind[1]);
        if (!SQL_SUCCEEDED(ret))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLBindParameter");
            return ret;
        }
        printf("\tInserting rows into table\n");
        for (row = 0; row < 1; row++)
        {
            /* a */
            p1 = row;
            len_ind[0] = sizeof(p1);
    
            /* b */
            len_ind[1] = SQL_LEN_DATA_AT_EXEC(readb);
    
            ret = SQLExecute(hstmt);
            if (ret == SQL_NEED_DATA)
            {
                SQLPOINTER  val;
    
                ret = SQLParamData(hstmt, &val);
                if (ret != SQL_NEED_DATA)
                {
                    fprintf(stderr,
                            "** SQLParamData returned %d, "
                            "expected SQL_NEED_DATA **\n", ret);
                    do_a_error(SQL_HANDLE_STMT, hstmt, "SQLParamData");
                    return SQL_ERROR;
                }
                if (val != (SQLPOINTER)2)
                {
                    fprintf(stderr,
                            "** SQLParamData said it required data for parameter "
                            "marker %p, and we expected 2 **\n", val);
                    return SQL_ERROR;
                }
                ret = SQLPutData(hstmt, p2, readb);
                if (!SQL_SUCCEEDED(ret))
                {
                    do_a_error(SQL_HANDLE_STMT, hstmt, "SQLPutData");
                    return SQL_ERROR;
                }
                ret = SQLParamData(hstmt, &val);
                if (!SQL_SUCCEEDED(ret))
                {
                    fprintf(stderr,
                            "** Second SQLParamData returned %d, "
                            "We though all data was sent **\n", ret);
                    do_a_error(SQL_HANDLE_STMT, hstmt, "SQLParamData");
                    return SQL_ERROR;
                }
            }
            else if (!SQL_SUCCEEDED(ret))
            {
                fprintf(stderr,
                        "** Driver returned a successful state for SQLExecute "
                        "buf there were data-at-exec parameters **\n");
                do_a_error(SQL_HANDLE_STMT, hstmt, "SQLExecute");
                return SQL_ERROR;
            }
            else
            {
                do_a_error(SQL_HANDLE_STMT, hstmt, "SQLExecute");
            }
            if (!SQL_SUCCEEDED(SQLRowCount(hstmt, &row_counts)))
            {
                do_a_error(SQL_HANDLE_STMT, hstmt, "SQLRowCount");
            }
            if (row_counts != 1)
            {
                fprintf(stderr, "** RowCount=%ld, expected 1 **\n", row_counts);
            }
    
            printf(".");
            fflush(stdout);
        }
        printf("\n");
    
        /*
         *  Now get it back to check we sent it OK.
         */
        memset(p2, '\0', sizeof(p2));
        sprintf(qbuf, "select * from \"blob\"");
        if (!SQL_SUCCEEDED(ret = SQLPrepare(hstmt, (SQLCHAR *)qbuf, SQL_NTS)))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLPrepare");
            return SQL_ERROR;
        }
        if (!SQL_SUCCEEDED(ret = SQLExecute(hstmt)))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLExecute");
        }
        if (!SQL_SUCCEEDED(ret = SQLFetch(hstmt)))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLFetch");
        }
        pos = 0;
        while(SQL_SUCCEEDED(ret = SQLGetData(hstmt, 2, SQL_C_BINARY,
                                             &p2[pos], sizeof(p2), &retrieved)))
        {
            if (retrieved == SQL_NO_TOTAL) abort();
            if (retrieved == SQL_NULL_DATA) abort();
            pos += retrieved;
        }
        if (ret != SQL_NO_DATA)
        {
            fprintf(stderr,
                    "** SQLGetData finished with a status other than SQL_NO_DATA **\n");
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLGetData");
            return SQL_ERROR;
        }
        if (!SQL_SUCCEEDED(SQLCloseCursor(hstmt)))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLCloseCursor");
        }
    
        if (!(fp = fopen("out.jpg", "w")))
        {
            fprintf(stderr, "** Failed to open out.jpg for writing **\n");
            return SQL_ERROR;
        }
        writeb = fwrite(p2, 1, pos, fp);
        if (writeb != pos)
        {
            fprintf(stderr, "** Failed to write out.jpg **\n");
            return SQL_ERROR;
        }
        fclose(fp);
        system(DISPLAY_GIF" out.jpg");
    
        printf("\tResetting parameters\n");
        if (!SQL_SUCCEEDED(SQLFreeStmt(hstmt, SQL_RESET_PARAMS)))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLFreeStmt");
        }
    
        printf("\tClosing statement\n");
        if (!SQL_SUCCEEDED(SQLFreeStmt(hstmt, SQL_CLOSE)))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLFreeStmt");
        }
    
        printf("\tDropping Statement\n");
        ret = SQLFreeStmt(hstmt, SQL_DROP);
        if (!SQL_SUCCEEDED(ret))
        {
            do_a_error(SQL_HANDLE_STMT, hstmt, "SQLFreeStmt");
        }
    
        return ret;
    }
    

    【讨论】:

    • 嘿,谢谢你的回复。这真的很有帮助。我写了一个写 blob 函数,没有错误 SQLGetDiagRec 返回没有错误,但它没有做它的工作。它使 blob 字段为空,仅填充 blob 名称字段。我可以发布代码并获得您的意见吗?再次感谢。再见。
    • 你确定你已经 a) 检查了所有 ODBC 调用的返回 b) 告诉 Oracle 参数是一个 blob,c) 称为 SQLPutData?您可以发布代码,但重要的一点是您的 SQLExecute 是否返回 SQL_NEED_DATA 以及 SQLParamData 告诉您它需要什么参数 - 我从代码中看不到这些东西。通过调试或 printfs 等仔细检查是否正在调用 SQLPutData。您可以在 ODBC 管理器中启用 API 调用的 ODBC 跟踪。
    • 我检查了所有函数返回,我使用的是 SQLExecDirect,它返回 99,SQL_NEED_DATA,我使用 SQLParamData 返回 99,然后是 SQLPutData。我相信这是它应该返回的。但它只在表中插入名称字段,二进制数据,blob 列保持为空。应该如何告诉 oracle 参数是 blob,使用 SQLBindParameter ?我有一段时间遇到这个问题,我重写了代码,问题仍然存在。感谢您的帮助。
    • 我不确定它为什么不插入 blob - 它显然从您的描述中插入了一行。您确定 SQLParamData 返回您在第 8 个参数中传递给 SQLBindParameter 的数字 - 请参阅我的示例。您为 blob 绑定什么类型 - 我在上面的示例中使用了 SQL_BINARY。你怎么知道 blob 没有正确插入?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    • 2019-11-19
    • 2019-11-06
    • 1970-01-01
    • 2018-08-13
    相关资源
    最近更新 更多