将数据从数组绑定到表列以批量复制到sql server

时间:2015-10-05 15:51:19

标签: c sql-server odbc

我想使用odbc在SQL Server中批量插入数组。我在c中写了一个非常简单的例子。

我的阵列:

SQLVARCHAR custIDs[] ={1,2,3,4};

并使用此语句尝试绑定此数组:

retcode =bcp_bind(hdbc1, (BYTE *)custIDs, 0, sizeof(DBINT), NULL,0, SQLINT4, 2);

在这一行中,我收到了关于access violation at position 0X004c0788

的例外情况

如何更改代码以解决此问题?

在这里你可以找到我的整个代码:

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <odbcss.h>
#include<tchar.h>
#include<iostream>

SQLHENV henv = SQL_NULL_HENV;
HDBC hdbc1 = SQL_NULL_HDBC, hdbc2 = SQL_NULL_HDBC;
SQLHSTMT hstmt2 = SQL_NULL_HSTMT;

void Cleanup() {
   if (hstmt2 != SQL_NULL_HSTMT)
      SQLFreeHandle(SQL_HANDLE_STMT, hstmt2);

   if (hdbc1 != SQL_NULL_HDBC) {
      SQLDisconnect(hdbc1);
      SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
   }

   if (hdbc2 != SQL_NULL_HDBC) {
      SQLDisconnect(hdbc2);
      SQLFreeHandle(SQL_HANDLE_DBC, hdbc2);
   }

   if (henv != SQL_NULL_HENV)
      SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
void HandleDiagnosticRecord (SQLHANDLE      hHandle,    
                             SQLSMALLINT    hType,  
                             RETCODE        RetCode)
{
    SQLSMALLINT iRec = 0;
    SQLINTEGER  iError;
    WCHAR       wszMessage[1000];
    WCHAR       wszState[SQL_SQLSTATE_SIZE+1];


    if (RetCode == SQL_INVALID_HANDLE)
    {
        fwprintf(stderr, L"Invalid handle!\n");
        return;
    }

    while (SQLGetDiagRec(hType,
                         hHandle,
                         ++iRec,
                         wszState,
                         &iError,
                         wszMessage,
                         (SQLSMALLINT)(sizeof(wszMessage) / sizeof(WCHAR)),
                         (SQLSMALLINT *)NULL) == SQL_SUCCESS)
    {
        // Hide data truncated..
        if (wcsncmp(wszState, L"01004", 5))
        {
            fwprintf(stderr, L"[%5.5s] %s (%d)\n", wszState, wszMessage, iError);
        }
    }


}

#define TRYODBC(h, ht, x)   {   RETCODE rc = x;\
                             if (rc != SQL_SUCCESS) \
                                { \
                                    HandleDiagnosticRecord (h, ht, rc); \
                                } \
                                if (rc == SQL_ERROR) \
                                { \
                                    fwprintf(stderr, L"Error in " L#x L"\n"); \
                                    Sleep(30000); \
                                }  \
                            }


void extract_error(
      char *fn,
      SQLHANDLE handle,
      SQLSMALLINT type)
  {
    SQLINTEGER i = 0;
    SQLINTEGER native;
    SQLWCHAR state[ 7 ];
    SQLWCHAR text[256];
    SQLSMALLINT len;
    SQLRETURN ret;
    fprintf(stderr,
            "\n"
            "The driver reported the following diagnostics whilst running "
            "%s\n\n",
            fn);

    do
    {
      ret = SQLGetDiagRec(type, handle, ++i, state, &native, text,
      sizeof(text), &len );
      if (SQL_SUCCEEDED(ret))
      printf("%s:%ld:%ld:%s\n", state, i, native, text);
    }
    while( ret == SQL_SUCCESS );
  }


int main() {
    try
    {
   RETCODE retcode;

   // BCP variables.
   char *terminator = "\0";

   // bcp_done takes a different format return code because it returns number of rows bulk copied
   // after the last bcp_batch call.
   DBINT cRowsDone = 0;

   // Set up separate return code for bcp_sendrow so it is not using the same retcode as SQLFetch.
   RETCODE SendRet;



   // Allocate the ODBC environment and save handle.
   retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLAllocHandle(Env) Failed\n\n");
      Cleanup();
      return(9);
   }

   // Notify ODBC that this is an ODBC 3.0 app.
   retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLSetEnvAttr(ODBC version) Failed\n\n");
      Cleanup();
      return(9);    
   }

   // Allocate ODBC connection handle, set bulk copy mode, and connect.
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLAllocHandle(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }

   retcode = SQLSetConnectAttr(hdbc1, SQL_COPT_SS_BCP, (void *)SQL_BCP_ON, SQL_IS_INTEGER);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLSetConnectAttr(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }

   // sample uses Integrated Security, create the SQL Server DSN using Windows NT authentication
   SQLWCHAR dsn[30] = L"mssqltest"; //Name DNS
   SQLWCHAR user[10] = L"di_test";
   SQLWCHAR pass[10] = L"di_test";
 //  SQLWCHAR tb[20]=L"information1";

   retcode = SQLConnectW(hdbc1, (SQLWCHAR *)dsn, SQL_NTS, (SQLWCHAR *) user, SQL_NTS, (SQLWCHAR *) pass, SQL_NTS);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
      printf("SQLConnect() Failed\n\n");
      Cleanup();
      return(9);
   }
    //  TRYODBC(hdbc1, SQL_HANDLE_DBC, retcode);
   // Initialize the bulk copy.



   retcode = bcp_initW(hdbc1,L"information1", NULL, L"C:\\error.txt", DB_IN);
   TRYODBC(hdbc1, SQL_HANDLE_DBC, retcode);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
      printf("bcp_init(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }

   //Define our array
   DBINT custIDs[] ={1,2,3,4};

   // Bind the program variables for the bulk copy.
   retcode =bcp_bind(hdbc1, (BYTE *)&custIDs, 0, sizeof(DBINT), NULL,0, SQLINT4, 2);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)  ) {
      printf("bcp_bind(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }

   // Could normally use strlen to calculate the bcp_bind cbTerm parameter, but this terminator 
   // is a null byte (\0), which gives strlen a value of 0. Explicitly give cbTerm a value of 1.
   retcode = bcp_bind(hdbc1,(LPCBYTE) custIDs, 2, SQL_VARLEN_DATA, NULL,0, SQL_C_NUMERIC, 3);
   if ( (retcode != SUCCEED) ) {
      printf("bcp_bind(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }


   if ( (SendRet = bcp_sendrow(hdbc1) ) != SUCCEED ) {
         printf("bcp_sendrow(hdbc1) Failed\n\n");
         Cleanup();
         return(9);
      }

   cRowsDone = bcp_done(hdbc1);
   if ( (cRowsDone == -1) ) {
      printf("bcp_done(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }



   printf("Number of rows bulk copied after last bcp_batch call = %d.\n", cRowsDone);

   // Cleanup.
   SQLFreeHandle(SQL_HANDLE_STMT, hstmt2);
   SQLDisconnect(hdbc1);
   SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
   SQLDisconnect(hdbc2);
   SQLFreeHandle(SQL_HANDLE_DBC, hdbc2);
   SQLFreeHandle(SQL_HANDLE_ENV, henv);
   }
   catch(int e)
   {
      std::wcout <<"An exception occured"<<" "<<e;
   }
   }

0 个答案:

没有答案