Acceso a Bases de datos SQL Server...
Fecha: 04/May/98
Autor: Quique
Acceso a una Base
de datos SQL Server utilizando el metodo OpenConnection para
establecer una conexi�n con un origen de datos de un espacion de
trabajo ODBCDirect.
Ejecuta consultas de SQL directamente el Server, creando
procedimientos almacenados, tablas temporales y borrandolos antes
de cerrar la conexi�n.
El modulo es llamado desde un formulario, pero si se quiere se
pueden quitar todas las referencias al formulario y el modulo se
ejecutaria sin mensajes.
En este ejemplo creo una tabla en SQL Server y la traspaso a
ACCESS 97, pero se podria modificar para que imprimiera un
informe en CR, por ejemplo.
Sub Procedimiento_SQL(CdAnio As String) Dim wsODBC As Workspace, conODBC As Connection, bd As Database, rs As Recordset, qdfTemp As QueryDef, tdf As TableDef Dim SQL_1 As String, SQL_2 As String, MiSQL As String, i As Integer DoCmd.SetWarnings False ' Desactiva la presentaci�n de mensajes del sistema DoCmd.Hourglass True 'lleva a cabo la acci�n RelojDeArena Forms!T_SQL!Lit_Estado.Caption = "Conectando a Base de Datos" DoEvents Set wsODBC = CreateWorkspace("", <NOMBRE DE USUARIO>,<PASSWORD>, dbUseODBC) 'Crea un nuevo espacio de trabajo Workspace de ODBCDirect, al establecer dbUseODBC el motor de base de datos Microsoft Jet no se cargar� en memoria y toda actividad se producir� con el origen de datos ODBC identificado el en objeto Connection. Set conODBC = wsODBC.OpenConnection("NuevaConexion", dbDriverNoPrompt, True, "ODBC;DATABASE=<NOMBRE BASE DATOS>;UID=<NOMBRE USUARIO>;PWD=<PASSWORD>;DSN=<CREADO EN ODBC32>") ' Establece una conexi�n con origen de datos en un espacio de trabajo ODBCDirect. DbDriverNoPrompt utiliza la cadena de conexi�n proporcionada en <nombreBaseDatos> , si no se proporciona suficiente informacion produce un error en tiempo de ejecucion, cambiar a dbDriverPrompt si se desea que el administrador del controlador muestre el cuadro de dialogo. ' La siguiente sentencia prepara la sesion en el servidor para una consulta "dirty reads", que no se bloquee ninguna tabla de las que se usen. Set qdfTemp = conODBC.CreateQueryDef("") ' los objetos son siempre temporales en ODBCDirect With qdfTemp .Prepare = dbQUnprepare .SQL = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED" .ODBCTimeout = 120 .Execute End With 'Verificamos que no existe el procedimiento alamcenado en el servidor Set qdfTemp = conODBC.CreateQueryDef("") MiSQL = "if exists (select * from sysobjects where id = object_id('proced') and sysstat & 0xf = 4)" & _ " drop procedure proced" With qdfTemp .Prepare = dbQUnprepare .SQL = MiSQL .ODBCTimeout = 120 .Execute End With 'Verificamos que no existe la tabla auxiliar que creamos como almacenamiento temporal Set qdfTemp = conODBC.CreateQueryDef("") MiSQL = "if exists (select * from sysobjects where id = object_id('Tmp_ Dist') and sysstat & 0xf = 3)" & _ " drop table Tmp_Dist" With qdfTemp .Prepare = dbQUnprepare .SQL = MiSQL .ODBCTimeout = 120 .Execute End With ' Aqu� esta el procedimiento almacenado en cuestion. Se pasa como parametro el a�o, y se utilizan transaccciones con el fin de no bloquear la tempdb. Set qdfTemp = conODBC.CreateQueryDef("") SQL_1 = "CREATE PROCEDURE Proced (@CdAnio char(4)) AS " & _ "begin tran " & _ "SELECT anio_factura AS anio, mes_factura AS mes, id_cliente, id_producto AS id_producto, id_envase AS id_envase, " & _ "SUM(kgs) AS Kilos " & _ "INTO #tmp_sog " & _ "FROM Venta_Direc V " & _ "WHERE anio_factura = @CdAnio AND " & _ "GROUP BY anio_factura, mes_factura, id_cliente, id_producto, id_envase " & _ "if @@error != 0 " & _ "rollback " & _ "commit tran " SQL_2 = "begin tran " & _ "SELECT id_cliente AS id_Distribuidor, anio, mes, T.id_producto, id_envase, kilos " & _ "INTO Tmp_Dist " & _ "FROM #tmp_sog T, producto P, familia_nueva F, especialidad E, sublinea S " & _ "WHERE T.id_producto = P.id_producto AND " & _ "P.id_familia_nueva = F.id_familia_nueva AND " & _ "F.id_especialidad = E.id_especialidad AND " & _ "E.id_sublinea = S.id_sublinea AND " & _ "S.id_linea_nueva IN ('A','I','G','P','D') " & _ "ORDER BY id_Distribuidor, anio, mes, T.id_producto, id_envase " & _ " drop table #tmp_sog " & _ "if @@error != 0 " & _ "rollback " & _ "commit tran " MiSQL = SQL_1 + SQL_2 ' Pasa el procedimiento almacenado a SQL Server Forms!T_COMPRAS!Lit_Estado.Caption = "Procesando registros de Base de datos" DoEvents With qdfTemp .Prepare = dbQPrepare .SQL = MiSQL .ODBCTimeout = 120 .Execute End With 'Ojo. Aqu� se utiliza un formulario, desde el cual se llama al modulo. ' Aqu� es donde se ejecuta la consulta en el servidor MiSQL = "EXEC Proced '" & Forms!T_COMPRAS!CdAnio & "'" Set qdfTemp = conODBC.CreateQueryDef("") With qdfTemp .Prepare = dbQUnPrepare .SQL = MiSQL .ODBCTimeout = 240 .Execute End With Set qdfTemp = conODBC.CreateQueryDef("") MiSQL = "if exists (select * from sysobjects where id = object_id('Proced') and sysstat & 0xf = 4)" & _ " drop procedure Proced" With qdfTemp .Prepare = dbQUnprepare .SQL = MiSQL .ODBCTimeout = 120 .Execute End With Forms!T_COMPRAS!Lit_Estado.Caption = "Creando Tabla " DoEvents Set bd = CurrentDb() bd.TableDefs.Refresh ' Elimina la tabla auxiliar si existe en ACCESS For i = (bd.TableDefs.Count) - 1 To 0 Step -1 If bd.TableDefs(i).Name = "T_COMPRAS" Then bd.TableDefs.Delete "T_COMPRAS" End If Next i ' Traspasa la tabla de SQL Server a la base de datos local en ACCESS 97 DoCmd.TransferDatabase acTable, "Bases de datos ODBC", _ "ODBC;DATABASE=<nombre de base de datos>;UID=<nombre de usuario>;PWD=<password>;DSN=<Creado en ODBC32>", _ acTable, "Tmp_Dist", "T_COMPRAS" bd.TableDefs.Refresh ' Borra la tabla auxiliar del servidor Set qdfTemp = conODBC.CreateQueryDef("") MiSQL = "if exists (select * from sysobjects where id = object_id('Tmp_ Dist') and sysstat & 0xf = 3)" & _ " drop table Tmp_ Dist" With qdfTemp .Prepare = dbQUnprepare .SQL = MiSQL .ODBCTimeout = 120 .Execute End With 'Cierre de conexiones ODBC conODBC.Close : Set conODBC = nothing wsODBC.Close : Set wsODBC = nothing Set bd = Nothing Forms!T_COMPRAS!Lit_Estado.Caption = "Proceso finalizado" DoEvents DoCmd.SetWarnings True DoCmd.Hourglass False Forms!T_COMPRAS!Salir.SetFocus End Sub