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

ir al índice