2

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

4

1 回答 1

2

我在 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;
}
于 2012-10-09T10:27:30.763 回答