c++ - ODBC 写入 blob 示例 Oracle C++

标签 c++ oracle insert odbc blob

您能给我一个使用 ODBC API 在 Oracle 数据库中插入 blob 的 C++ 示例吗?这是我第一次使用 BLOB 类型,所以它对我来说很抽象。我在网上查了很多资料,现在脑子里一片困惑。一个例子确实会对我有帮助。

最佳答案

我有一个简短的 C 示例。通过 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;
}

关于c++ - ODBC 写入 blob 示例 Oracle C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12781553/

相关文章:

java - 需要 JAVA 和 Oracle 支持的日期格式

sql - Oracle MERGE 死锁

php - 我在将输入和 foreach 循环中的所有数据插入 mysql 时遇到问题(只有一个数据进入 mysql)

c++ - 插入以设置为 "Fixed"大小循环

c++ - 将 boost::shared_ptr 转换为实际类

java - JDBC 以 block 的形式检索 Oracle 数据

c++ - 非类型模板参数中的C++类类型:推导指南失败

java - PreparedStatement如果Error则继续插入

c++ - 打印一个 unicode 拉丁字母 (utf8)

c++ - 为什么带有逻辑与运算符和递增运算符的 C++ 程序给出的输出与预期的不同?