Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Problem with SQLColumns in ODBC API

Problem with SQLColumns in ODBC API

Scheduled Pinned Locked Moved C / C++ / MFC
databasejsonhelpquestion
5 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    insanely420
    wrote on last edited by
    #1

    Greetings I am writing an app to import data from an Access DB. I am fetching the information about columns of a table by using the following method - SQLCHAR colname[SIZE_128+1]={0}; SQLINTEGER colsize=0; SQLSMALLINT decimaldigit=0; // allocate. VERIFY ( (retcode = SQLAllocHandle ( SQL_HANDLE_STMT, sqlhdbc, &hstmt )) == SQL_SUCCESS ); retcode = SQLColumns ( hstmt, NULL, 0, NULL, 0, (SQLCHAR*)szTable, SQL_NTS, NULL, 0 ); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { /* Bind columns in result set to buffers */ SQLBindCol(hstmt, 4, SQL_C_CHAR, colname, SIZE_128, &size ); SQLBindCol(hstmt, 7, SQL_C_SLONG, &colsize, 0, &size ); SQLBindCol(hstmt, 9, SQL_C_SSHORT, &decimaldigit, 0, &decsize ); } while( TRUE ) { retcode = SQLFetch(hstmt); if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO ) { // do stuff } else { break; } } Now the problem is that even if a column is defined as DOUBLE in Access and has data like 2.345, 3.001, 0.0001 etc. The decimaldigit is always returned with value 0. Therefore I am not able to get the correct decimal point for the column. So instead of getting colsize = 15 and decimaldigit = 2, I am always getting colsize = 15 and decimaldigit = 0? Am I doing something wrong? Thanks in advance. Karam

    D 1 Reply Last reply
    0
    • I insanely420

      Greetings I am writing an app to import data from an Access DB. I am fetching the information about columns of a table by using the following method - SQLCHAR colname[SIZE_128+1]={0}; SQLINTEGER colsize=0; SQLSMALLINT decimaldigit=0; // allocate. VERIFY ( (retcode = SQLAllocHandle ( SQL_HANDLE_STMT, sqlhdbc, &hstmt )) == SQL_SUCCESS ); retcode = SQLColumns ( hstmt, NULL, 0, NULL, 0, (SQLCHAR*)szTable, SQL_NTS, NULL, 0 ); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { /* Bind columns in result set to buffers */ SQLBindCol(hstmt, 4, SQL_C_CHAR, colname, SIZE_128, &size ); SQLBindCol(hstmt, 7, SQL_C_SLONG, &colsize, 0, &size ); SQLBindCol(hstmt, 9, SQL_C_SSHORT, &decimaldigit, 0, &decsize ); } while( TRUE ) { retcode = SQLFetch(hstmt); if ( retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO ) { // do stuff } else { break; } } Now the problem is that even if a column is defined as DOUBLE in Access and has data like 2.345, 3.001, 0.0001 etc. The decimaldigit is always returned with value 0. Therefore I am not able to get the correct decimal point for the column. So instead of getting colsize = 15 and decimaldigit = 2, I am always getting colsize = 15 and decimaldigit = 0? Am I doing something wrong? Thanks in advance. Karam

      D Offline
      D Offline
      David Crow
      wrote on last edited by
      #2

      Perhaps you should have something like: SQL_C_DOUBLE decimaldigit; SQLBindCol(hstmt, 9, SQL_C_DOUBLE, &decimaldigit, 0, &decsize);

      I 1 Reply Last reply
      0
      • D David Crow

        Perhaps you should have something like: SQL_C_DOUBLE decimaldigit; SQLBindCol(hstmt, 9, SQL_C_DOUBLE, &decimaldigit, 0, &decsize);

        I Offline
        I Offline
        insanely420
        wrote on last edited by
        #3

        SQL_C_DOUBLE is defined as 8. So I used SQLDOUBLE decimaldigit; SQLBindCOl ( hstmt, 9, SQL_C_DOUBLE, &decimaldigit, 0, &decsize ); For the double column the decimaldigit value is 0.000000000 and decsize it is -1. I am confused. Even the MSDN docs tell me to use the function this way :confused:

        A 1 Reply Last reply
        0
        • I insanely420

          SQL_C_DOUBLE is defined as 8. So I used SQLDOUBLE decimaldigit; SQLBindCOl ( hstmt, 9, SQL_C_DOUBLE, &decimaldigit, 0, &decsize ); For the double column the decimaldigit value is 0.000000000 and decsize it is -1. I am confused. Even the MSDN docs tell me to use the function this way :confused:

          A Offline
          A Offline
          Anonymous
          wrote on last edited by
          #4

          I have never been a fan of SQLColumns.... usually I just do a 'select * from where 1=0' and use the following fcns to get metadata (sorry for the code bloat...): short DBStatement::GetColDBType(int iColumnNum) { short iStatus; char caDummy[2]; short iDummy; long lColType = -1; if (m_hStmtHdl) { ResetError(); iStatus = ::SQLColAttributes(m_hStmtHdl,(UWORD)iColumnNum,(UWORD)SQL_COLUMN_TYPE,(PTR)caDummy,(SWORD)1,(SWORD *)&iDummy,(SDWORD *)&lColType); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) { UpdateDBError(); lColType = -1; } } else NoActiveStatement(); return (short)lColType; } LPSTR DBStatement::GetColName(int iColumnNum) { short iStatus; long lDummy; short iDummy; InitDataBuffer(); if (m_hStmtHdl) { ResetError(); iStatus = ::SQLColAttributes(m_hStmtHdl,(UWORD)iColumnNum,(UWORD)SQL_COLUMN_NAME,(PTR)m_caDataBuf,(SWORD)1000,(SWORD *)&iDummy,(SDWORD *)&lDummy); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) { UpdateDBError(); m_caDataBuf[0] = 0; } } else NoActiveStatement(); return m_caDataBuf; } long DBStatement::GetColWidth(int iColumnNum) { short iStatus; char caDummy[2]; long lColWidth = -1; short iDummy; if (m_hStmtHdl) { ResetError(); iStatus = ::SQLColAttributes(m_hStmtHdl,(UWORD)iColumnNum,(UWORD)SQL_COLUMN_LENGTH,(PTR)caDummy,(SWORD)1,(SWORD *)&iDummy,(SDWORD *)&lColWidth); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) UpdateDBError(); } else NoActiveStatement(); return lColWidth; } int DBStatement::GetNumCols() { short iStatus; short iRetval = -1; if (m_hStmtHdl) { ResetError(); iStatus = ::SQLNumResultCols(m_hStmtHdl,(short *)&iRetval); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) UpdateDBError(); } else NoActiveStatement(); return (int)iRetval; }

          B 1 Reply Last reply
          0
          • A Anonymous

            I have never been a fan of SQLColumns.... usually I just do a 'select * from where 1=0' and use the following fcns to get metadata (sorry for the code bloat...): short DBStatement::GetColDBType(int iColumnNum) { short iStatus; char caDummy[2]; short iDummy; long lColType = -1; if (m_hStmtHdl) { ResetError(); iStatus = ::SQLColAttributes(m_hStmtHdl,(UWORD)iColumnNum,(UWORD)SQL_COLUMN_TYPE,(PTR)caDummy,(SWORD)1,(SWORD *)&iDummy,(SDWORD *)&lColType); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) { UpdateDBError(); lColType = -1; } } else NoActiveStatement(); return (short)lColType; } LPSTR DBStatement::GetColName(int iColumnNum) { short iStatus; long lDummy; short iDummy; InitDataBuffer(); if (m_hStmtHdl) { ResetError(); iStatus = ::SQLColAttributes(m_hStmtHdl,(UWORD)iColumnNum,(UWORD)SQL_COLUMN_NAME,(PTR)m_caDataBuf,(SWORD)1000,(SWORD *)&iDummy,(SDWORD *)&lDummy); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) { UpdateDBError(); m_caDataBuf[0] = 0; } } else NoActiveStatement(); return m_caDataBuf; } long DBStatement::GetColWidth(int iColumnNum) { short iStatus; char caDummy[2]; long lColWidth = -1; short iDummy; if (m_hStmtHdl) { ResetError(); iStatus = ::SQLColAttributes(m_hStmtHdl,(UWORD)iColumnNum,(UWORD)SQL_COLUMN_LENGTH,(PTR)caDummy,(SWORD)1,(SWORD *)&iDummy,(SDWORD *)&lColWidth); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) UpdateDBError(); } else NoActiveStatement(); return lColWidth; } int DBStatement::GetNumCols() { short iStatus; short iRetval = -1; if (m_hStmtHdl) { ResetError(); iStatus = ::SQLNumResultCols(m_hStmtHdl,(short *)&iRetval); if (iStatus != SQL_SUCCESS && iStatus != SQL_SUCCESS_WITH_INFO) UpdateDBError(); } else NoActiveStatement(); return (int)iRetval; }

            B Offline
            B Offline
            basementman
            wrote on last edited by
            #5

            The point being that you can develop a generic function to return your metadata using the SQLColAttributes ODBC call.

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups