Pregunta: | 16989 - USO DE ODBC DESDE BUILDER C++ |
Autor: | Pedro Miguel González |
Si alguien tiene experiencia en el uso de ODBC desde Builder le agradecería que me explique un poco su funcionamiento y las funciones a utilizar, o en su defecto, alguna dirección de internet en donde buscar.
Matizando un poco más la pregunta, lo que necesito es acceder mediante ODBC pero sin utilizar el BDE de Borland. Esto es así porque pienso que ODBC está más extendido (se encuentra ya instalado en la mayoría de máquinas) y da menos problemas. Esto lo digo porque me he encontrado en situaciones en las que un programa que está funcionando perfectamente de pronto deja de hacerlo porque han instalado otro programa que usa una versión anterior del BDE y sustituye a la actual. Esto puede ocurrir por varias razones: 1. Se trata de una versión antigua que no comprueba si hay un BDE más reciente. 2. hay programadores que instalan el BDE 'a pelo' y no utilizan el instalador de Borland o similar, con lo que se olvidan de comprobar la existencia de otras versiones. Agradecería algún comentario sobre este particular. Un saludo y gracias de antemano. |
Respuesta: | Fernando Gómez |
Pedro,
efectívamente, es mejor emplear ODBC, aunque si tienes acceso a MFC, será mejor que emplees CDatabase y CRecordset, que agrupan la mayoría de las funciones que necesitas para manejar una base de datos. El API de ODBC es muy complejo y extenso. Te enlistaré algunas de las funciones más comunes, y su utilización. Para mayor información, dirígete a www.msdn.microsoft.com/data Como todo en Windows, necesitas llevar un control a través de HRESULTs. Hay esencialmente tres tipos de HRESULTs en ODBC: HENV para el ambiente (environment) de trabajo, HDBC para la conexión (database connection) y HSTMT para las sentencias (statements) a ejecutar. En ese orden, debes instanciar los manejadores. Digamos, por ejemplo, que quiero hacer todos los pasos para ejecutar una sentencia SQL. Primero, debo instanciar los manejadores: #include <sql.h> #include <sqlext.h> // ... HENV henv; HDBC hdbc; HSTMT hstmt; /* todas las funciones regresan SQL_SUCCESS o SQL_SUCCESS_WITH_INFO si fueron exitosas. Suponemos, en este ejemplo, que todo va bien */ SQLAllocEnv(&henv); SQLAllocConnect(henv, &hdbc); SQLAllocStmt(hdbc, &hstmt); El siguiente paso, es conectarte a algún ODBC, digamos, MiOdbc. La función que se emplea es SQLDriverConnect, pero es lo suficientemente grande y laboriosa (en la explicación de sus parámetros) como para no mostrarla aquí. Sin embargo, te comento que, en la cadena de conexión, incluyes todos los datos del driver y la base de datos, el usuario y password de la misma. Yo, generalmente, sólo empleo una cadena como la que sigue: wsprintf(szCnnIn, _T("DSN=%s; UID=%s; PWD=%s"), szDsn, szDbUid, szDbPwd); Nunca he tenido que ir más allá de esto. Una vez que te conectaste y tienes listo tu HSTMT, creas tu query SQL y lo ejecutas a través de SQLExecDirect. Si no te interesan los resultados que regrese tu query (como cuando ejecutas un Insert, un Update o un Stored Procedure), hasta aquí termina, generalmente tu labor. En caso contrario, necesitarás emplear las funciones SQLFetch para moverte entre los registros que regresó tu query y SQLGetData para obtener los datos. A esta última, le pasas como parámetros el tipo de dato que coincide con el campo de tu base de datos (digamos, SQL_C_TCHAR) y el número de columnas, así como el HSTMT correspondiente. Quizás también quieras manipular las columnas de tu resultado. Para ello, se emplea SQLBind. Esta función es muy usada, sobre todo, con Stored procedures que te regresan algún resultado. Aunque estas son las funciones mínimas que requieres para manipular tus datos, también hay otras de uso común como SQLPrepareData y SQLExecute. Cuando termines, no se te olvide cerrar tus instancias: SQLFreeStmt(hstmt, SQL_DROP); SQLFreeConnect(hdbc); SQLFreeEnv(henv, SQL_DROP); Esto lo debes hacer en ESTE orden. Acuérdate que los manejadores citados están jerarquizados y, como habrás concluido, son interdependientes. Ahora, la vida es más fácil con MFC. Lo único que tienes qué hacer: CDatabase* pDBase = new CDatabase(); pDBase->OpenEx(_T("DSN=TuDsn; UID=TuUID; PWD=TuPwd;")); CRecordset obRst(pDBase); y empleas CRecordset::Open para ejecutar un query que regrese datos, MoveNext, MovePrevious, Move, IsEOF, IsBOF para manipular tus datos, y GetFieldValue para obtener los valores de tu query. Si no esperas obtener algún dato de retorno, empleas CDatabase::ExecuteSQL. NOTA: cuando termines de emplear tu CRecordset, el destructor de éste verifica que la base de datos siga abierta. Por lo tanto, no puedes cerrar la base de datos antes de que CRecordset llame a su destructor. Espero haberos sido de ayuda. Un saludo. - Est solarus oth mithas - |