ODBC is powerful and flexible but can seem scary at first glance. But its really not that bad when you get used to it. I created some simple wrapper functions I use to make ODBC as simple as a few lines of code.
Here is a simple example of using them: (note: the connection string can point to all kinds of databases like SQL servers, MS Access DB files, System DNS, etc)
See ODBC is not that scary is it? 
Note: To use the following code you will need PB 9 and the include files from Jose Roca found here:
For any questions please use this discussion thread:
http://www.powerbasic.com/support/pb...ad.php?t=41467
Here is the full example which includes the wrapper functions. Enjoy.
Here is a simple example of using them: (note: the connection string can point to all kinds of databases like SQL servers, MS Access DB files, System DNS, etc)
Code:
sConnectString = "Driver={Microsoft Access Driver (*.mdb)};DBQ=MyDB.mdb;" If DBconnect(sConnectString, hEnv, hConn, sError) then sSQL = "Select * FROM Table1 WHERE (((Table1.RecID)<100));" IF DBSQLSelect(hConn, sSQL, sHeader, sData, sError) THEN AddMyFile "MyReport.txt", sHeader AddMyFile "MyReport.txt", sData ELSE MSGBOX sError,,"Error on SELECT statement" END IF DBdisconnect hEnv, hConn 'disconnect from DB Else Msgbox sError,,"Error connecting" End if

Note: To use the following code you will need PB 9 and the include files from Jose Roca found here:
For any questions please use this discussion thread:
http://www.powerbasic.com/support/pb...ad.php?t=41467
Here is the full example which includes the wrapper functions. Enjoy.

Code:
'========================================================================== ' ODBC_DB_Example.bas by William Burns ' A simple example of using ODBC to connect to several different types of ' databases using the same functions. ' '========================================================================== '#DEBUG DISPLAY ON 'unrem this statement for debuging #COMPILE EXE #DIM ALL #IF NOT %DEF(%WINAPI) #INCLUDE "WIN32API.INC" #ENDIF 'the following 2 files can be found at http://www.jose.it-berater.org/smfforum/index.php?board=344.0 #INCLUDE "Sql.inc" 'API declares created by Jose Roca #INCLUDE "Sqlext.inc" 'API declares created by Jose Roca '========================================================================== ' Main Application Entry Point '========================================================================== FUNCTION PBMAIN() #REGISTER NONE 'registered vars can cause problems on some DB functions LOCAL iUpdated AS LONG LOCAL hEnv AS DWORD LOCAL hConn AS DWORD LOCAL sError AS STRING LOCAL sHeader AS STRING LOCAL sData AS STRING LOCAL sConnectString AS STRING LOCAL sSQL AS STRING sConnectString = "Driver={Microsoft Access Driver (*.mdb)};DBQ=ScanResults.mdb;" 'other examples: 'MS Access DB example string "Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\DataFolder\MyAccess.mdb;" 'SQL server example1 = "DRIVER=SQL Server;DATABASE=MyDBname;Server=MyDBServerNameOrIp;UID=MyId;PWD=MyPass;" 'SQL server example2 = "Driver={SQL Native Client};Server=myServerAddress;Database=myDataBase; Trusted_Connection=yes;" 'PostgreSQL example string: "DRIVER={PostgreSQL};DATABASE=MyDBname;Server=MyDBservername;UID=MyId;PWD=MyPass;" IF DBconnect(sConnectString, hEnv, hConn, sError) THEN 'example of sending an update SQL action statment (same works for INSERT, DROP, DELETE etc) sSQL = "UPDATE Table1 SET Table1.OSver='Windows 7' WHERE (((Table1.PC_Name) Like 'WORKPCA4%'));" IF DBSQLExec(hConn, sSQL, iUpdated, sError) THEN MSGBOX "Updated " & STR$(iUpdated) & " records.",,"UPDATE Worked" ELSE MSGBOX sError,,"Error on UPDATE statement" END IF 'example of a select statement returning the header row and all the data rows sSQL = "SELECT Table1.RecID, Table1.PC_Name, Table1.OSver FROM Table1 WHERE (((Table1.RecID)<10)) ORDER BY Table1.PC_Name;" IF DBSQLSelect(hConn, sSQL, sHeader, sData, sError) THEN AddMyFile "MyReport.txt", sHeader AddMyFile "MyReport.txt", sData ELSE MSGBOX sError,,"Error on SELECT statement" END IF DBdisconnect hEnv, hConn 'disconnect from DB MSGBOX "Done",,"Done" ELSE MSGBOX sError,,"Error connecting" END IF END FUNCTION '========================================================================== '========================================================================== ' This is just to make saving to a file easier '========================================================================== SUB AddMyFile(BYVAL sFileName AS STRING, BYVAL sText AS STRING) LOCAL iFile AS LONG TRY iFile = FREEFILE OPEN sFileName FOR APPEND AS iFile PRINT #iFile, sText CLOSE iFile CATCH CLOSE iFile END TRY END SUB '========================================================================== 'Here are some of my wrapper functions used: '========================================================================== ' DBaddErr() - Pulls error information about SQL '========================================================================== FUNCTION DBaddErr(hStmt AS DWORD, sError AS STRING) AS LONG #REGISTER NONE 'registered vars can cause problems on some DB functions LOCAL iLenRet AS INTEGER LOCAL iRecNum AS INTEGER LOCAL iErr AS LONG LOCAL zState AS ASCIIZ * %MAX_PATH LOCAL zMsg AS ASCIIZ * %MAX_PATH iRecNum = 1 CALL SQLGetDiagRec(%SQL_HANDLE_STMT, hStmt, iRecNum,zState,iErr,zMsg,%MAX_PATH,iLenRet) sError = sError + "Error " + FORMAT$(iErr) + " " + TRIM$(zState) + " " + TRIM$(zMsg) END FUNCTION '========================================================================== ' DBconnect() - Connect to the database '========================================================================== FUNCTION DBconnect(sDB_connect_string AS STRING, hEnv AS DWORD, hConn AS DWORD, sError AS STRING) AS LONG #REGISTER NONE 'registered vars can cause problems on some DB functions LOCAL iBytes AS INTEGER LOCAL zConnect AS ASCIIZ * 1000 LOCAL zOut AS ASCIIZ * 400 IF SQLAllocHandle(%SQL_HANDLE_ENV,%SQL_NULL_HANDLE,hEnv) => %SQL_SUCCESS THEN ' ret= %SQL_SUCCESS(0) %SQL_SUCCESS_WITH_INFO(1) %SQL_ERROR(-1) %SQL_INVALID_HANDLE(-2) IF SQLSetEnvAttr(hEnv,%SQL_ATTR_ODBC_VERSION,BYVAL %SQL_OV_ODBC3,%SQL_IS_INTEGER) => %SQL_SUCCESS THEN IF SQLAllocHandle(%SQL_HANDLE_DBC,hEnv,hConn) => %SQL_SUCCESS THEN zConnect = sDB_connect_string IF SQLDriverConnect(hConn, 0, zConnect, LEN(zConnect), zOut, 400, iBytes, %SQL_DRIVER_NOPROMPT) => %SQL_SUCCESS THEN FUNCTION = %TRUE ELSE sError = sError + "Function DBconnect -SQLDriverConnect() failed." + $CRLF CALL SQLFreeHandle(%SQL_HANDLE_DBC,hConn) CALL SQLFreeHandle(%SQL_HANDLE_ENV,hEnv) hConn = 0 hEnv = 0 END IF ELSE sError = sError + "Function DBconnect - SQLAllocHandle(%SQL_HANDLE_DBC) failed." + $CRLF CALL SQLFreeHandle(%SQL_HANDLE_ENV,hEnv) hEnv = 0 END IF ELSE sError = sError + "Function DBconnect - SQLSetEnvAttr() failed." + $CRLF CALL SQLFreeHandle(%SQL_HANDLE_ENV,hEnv) hEnv = 0 END IF ELSE sError = sError + "Function DBconnect - SQLAllocHandle(%SQL_HANDLE_ENV) failed." + $CRLF END IF END FUNCTION '========================================================================== ' DBdisconnect() - disconnect and free handles '========================================================================== SUB DBdisconnect(hEnv AS DWORD, hConn AS DWORD) #REGISTER NONE CALL SQLDisconnect(hConn) CALL SQLFreeHandle(%SQL_HANDLE_DBC, hConn) CALL SQLFreeHandle(%SQL_HANDLE_ENV, hEnv) hEnv = 0 hConn = 0 END SUB '========================================================================== 'Run a INSERT, UPDATE or DELETE SQL query '========================================================================== FUNCTION DBSQLExec(hConn AS DWORD, BYVAL sSQL AS STRING, iUpdated AS LONG, sError AS STRING) AS LONG #REGISTER NONE 'registered vars seem to mess up some database items LOCAL iRet AS LONG LOCAL hStmt AS DWORD LOCAL zQuery AS ASCIIZ * 2000 iUpdated = 0 zQuery = UCASE$(sSQL) IF SQLAllocHandle(%SQL_HANDLE_STMT, hConn, hStmt) => %SQL_SUCCESS THEN iRet = SQLExecDirect(hStmt,zQuery,%SQL_NTS) IF iRet < %SQL_SUCCESS THEN sError = sError + " DBSQLExec() Error SQLExecuteDirect - " DBaddErr(hStmt, sError) ELSE IF SQLRowCount(hStmt, iRet) => %SQL_SUCCESS THEN iUpdated = iRet END IF FUNCTION = %TRUE 'worked END IF CALL SQLFreeHandle(%SQL_HANDLE_STMT, hStmt) ELSE sError = sError + " DBSQLExec() Error SQLAllocHandle." END IF END FUNCTION '========================================================================== '========================================================================== 'Run a SQL Select query ' sHeader will return a tab delimited header ' sData will return tab delimited rows (each row seperated by CrLf '========================================================================== FUNCTION DBSQLSelect(hConn AS DWORD, BYVAL sSQL AS STRING, sHeader AS STRING, sData AS STRING, sError AS STRING) AS LONG #REGISTER NONE 'registered vars seem to mess up some database items LOCAL iRet AS LONG LOCAL iCount AS LONG LOCAL iNumCols AS INTEGER LOCAL iLen AS INTEGER LOCAL iCol AS LONG LOCAL iSize AS LONG LOCAL hStmt AS DWORD LOCAL zBuff AS ASCIIZ * 265 LOCAL zQuery AS ASCIIZ * 2000 sHeader = "" sData = "" zQuery = UCASE$(sSQL) IF SQLAllocHandle(%SQL_HANDLE_STMT, hConn, hStmt) => %SQL_SUCCESS THEN iRet = SQLExecDirect(hStmt,zQuery,%SQL_NTS) IF iRet < %SQL_SUCCESS THEN sError = sError + " DBSQLSelect() SQLExecuteDirect - " DBaddErr(hStmt, sError) ELSE 'first get the number of columns in the result set CALL SQLNumResultCols(hStmt, iNumCols) IF iNumCols THEN 'now get the field names for the column headers in our report FOR iCount = 1 TO iNumCols iRet = SQLColAttribute(hStmt, iCount, %SQL_DESC_LABEL, BYVAL VARPTR(zBuff), BYVAL 265, iLen, BYVAL %NULL) IF (iRet = %SQL_SUCCESS) OR (iRet = %SQL_SUCCESS_WITH_INFO) THEN sHeader = sHeader & TRIM$(LEFT$(zBuff, iLen)) & $TAB END IF NEXT iCount 'now lets read each line from the result set DO 'loop to read each row iRet = SQLFetch(hStmt) 'fetch a new row of data IF (iRet = %SQL_SUCCESS) OR (iRet = %SQL_SUCCESS_WITH_INFO) THEN FOR iCol = 1 TO iNumCols 'loop to read each column in each row iRet = SQLGetData(hStmt, iCol, %SQL_C_CHAR, BYVAL VARPTR(zBuff), BYVAL 265, iSize) IF (iRet = %SQL_SUCCESS) OR (iRet = %SQL_SUCCESS_WITH_INFO) THEN sData = sData & TRIM$(LEFT$(zBuff, iSize)) & $TAB ELSEIF iRet = %SQL_NO_DATA THEN 'done so exit EXIT LOOP ELSE sError = sError + " DBSQLSelect() Error " & STR$(iRet) & " reading - SQLGetData - " DBaddErr(hStmt, sError) EXIT LOOP END IF NEXT iCol sData = TRIM$(sData, $TAB) & $CRLF 'add the row to our return buffer ELSEIF iRet = %SQL_NO_DATA THEN IF sData = "" THEN sError = sError + " DBSQLSelect() No Data returned for SQL: " & sSQL EXIT LOOP ELSE sError = sError + " DBSQLSelect() Error " & STR$(iRet) & " reading - SQLFetch - " DBaddErr(hStmt, sError) EXIT LOOP END IF LOOP sData = TRIM$(sData, ANY CHR$(9,10,13)) 'remove last CrLf IF LEN(sData) THEN FUNCTION = %TRUE ELSE sError = sError + " DBSQLSelect() Num cols = 0 - " DBaddErr(hStmt, sError) END IF END IF CALL SQLFreeHandle(%SQL_HANDLE_STMT, hStmt) ELSE sError = sError + " DBSQLSelect() Error SQLAllocHandle." END IF END FUNCTION