2009-07-12 19 views
7

Hola, acabo de aprender cómo poner mis declaraciones SQL en VBA (o al menos escribirlas), pero no tengo idea de cómo recuperar los datos.¿Cómo obtengo los datos de una consulta SQL en Microsoft Access VBA?

Tengo un par de formularios (formularios de gráficos) basados ​​en consultas contra las que ejecuto parámetros bastante regulares, simplemente alterando el marco temporal (como las 10 principales ventas del mes). Luego tengo procedimientos que transportan automáticamente el objeto gráfico a una presentación en PowerPoint. Así que tengo todas estas consultas precompiladas (como 63) y las formas de los gráficos para que coincidan (eh, sí ... 63 ... sé que esto es malo), y luego todas estas cosas configuradas en "abrir/cerrar "eventos desencadenando el siguiente (es como mi mejor intento de ser un hack ... o un dominó, lo que prefiera).

Así que estaba tratando de aprender a usar sentencias de SQL en VBA, para que eventualmente pueda hacer todo esto allí (aún necesito conservar todos los formularios de gráficos pero no sé porque obviamente me falta entendimiento)

Así que, aparte de la pregunta que hice en la parte superior, ¿alguien puede ofrecer consejos? gracias

+1

lo siento, siempre lo olvido .... Estoy usando Microsoft Access 2000 – Justin

+0

@Justin, si me ayudaron, siempre es bueno votar por las buenas personas que te ayudaron :) –

Respuesta

9

Está un poco anticuado, por lo que es posible que desee obtener un book on the subject. Pero, aquí hay un montón de access resources y algunos tutorials and examples también. Pero, básicamente ...

por comentario: Tome un vistazo a la recordset class. Contiene una colección llamada Campos que son las columnas que se devuelven de su consulta. Sin conocer el esquema, es difícil de decir, pero algo así como ...

rs.MoveFirst 
Do While Not rs.EOF 
    'do something like rs("SomeFieldName") 
    rs.MoveNext 
Loop 

Como dije, lo mejor es tomar un libro sobre este tema, tienen un montón de ejemplos.

+1

no todos los tipos de cursor devolverán el RecordCount. Es más seguro NO .EO ... –

+0

¡gracias y gracias por los sitios! – Justin

+0

El ejemplo de código es DAO y todos los tipos de conjuntos de registros devuelven un registro de al menos 1 si hay registros, por lo que no es necesario verificar EOF y BOF, como comprobar que RecordCount <> 0 sea suficiente. Si está transfiriendo su código a alguna otra interfaz de datos, su punto es relevante, pero ciertamente está completamente fuera de base en el presente ejemplo de código, que es claramente DAO. –

1

Aunque intrincado, su camino es más fácil que tratar de construir las declaraciones de SQL en VBA. Recuerde, guardar las consultas individualmente le permite manipularlas visualmente. Además, hay algunos beneficios de rendimiento.

Una mejor comprensión de SQL lo ayudaría a consolidar y simplificar sus consultas existentes (si es que necesitan ser simplificadas. Parece que están haciendo un gran trabajo, por lo que puede necesitar las 64 consultas de todos modos).

Dicho esto, es bastante fácil de ejecutar consultas SQL en el código:

Dim strSQL as String 
strSQL = "UPDATE Table MyTable SET fieldname = 1 WHERE fieldname = 0;" 
DoCmd.RunSQL strSQL 
+0

gracias. lo único sobre lo que estoy nervioso/confundido es con todos estos objetos en esta cosa, y cuando necesito volcarlo en la parte frontal/mde. Esta será la primera vez que lo hago, porque mi experiencia limitada con el acceso siempre se ha mantenido simplemente en un estado de fondo. – Justin

+0

Es bastante fácil separar las tablas de todo lo demás cuando llegue el momento, usando el divisor de bases de datos en Herramientas/Utilidades de la base de datos. –

2

Utilice una definición de consulta con parámetros e invocan desde VBA.
La consulta es más fácil de diseñar ... fácilmente comprobable ... y de fácil acceso desde VBA o un formulario.

dim qd as querydef 
set qd = currentdb.querydefs!myquerydef 

qd.parameters!parm1=val1 

....

ya sea qd.execute

o

dim rs as recordset 
set rs = qd.openrecordset() 

tu caso es distinto ...

+0

gracias. Voy a intentar – Justin

+0

BTW ... esto utiliza las bibliotecas DAO. Asegúrate de que en 'Referencias' hayas seleccionado DAO por encima de ADO. – CMB

+0

Una limitación es que no se puede parametrizar N en una sentencia TOP N SQL. –

2

Aquí es una función que se podría considerar refactorización para tomar en una cadena, y podrás volver a usar en cualquier parte de tu código.

Así que tienen una constante o construir una secuencia para su instrucción SQL, y el pop en su DESINFECTADO, NO SQL INYECTADO cadena como argumento :)

es decir

strSQL = "SELECT * FROM Customer WHERE ID = " & EnsureParamIsNotSQLInjection(customerID) 

... luego llamar al función/sub desde cualquier lugar que necesite para obtener un conjunto de registros/datos/ejecutar una declaración. Considere la posibilidad de crear un puñado de funciones/subprocesos de acceso a datos en los que simplemente puede ejecutar una instrucción UPDATE, o recuperar un único valor, o recuperar un conjunto de registros completo.

La clave aquí es tener todas estas funciones viviendo en un solo lugar y reutilizarlas por todos lados. Aquí hay una muestra en VBScript.

Sub DoStuff(strSQL) 

    Set adoCon = Server.CreateObject("ADODB.Connection") 


    strConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("db\Database.mdb") 
    'strConnString = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("db\Database.mdb") 

    adoCon.Open strConnString 

    Set rsMain = Server.CreateObject("ADODB.Recordset") 

    rsMain.Open strSQL, adoCon 

    Do While NOT rsMain.EOF 
     customerName = rsMain("CustomerName") 'silly example 
     RsMain.MoveNext 
    Loop 

    rsMain.Close 

    Set adoCon = Nothing 
End Sub 
+0

Sí, eso suena genial. no es una mala idea. Sé cómo llamar a una función pública en un sub (evento) de un formulario, pero ¿qué ocurre con las funciones ... funcionan de la misma manera? – Justin

+0

@pcampbell: ¿alguna razón por la que está usando una conexión odbc? No se beneficiará de muchos ADO como lo haría si usa una conexión OLE DB, p. "Provider = Microsoft.Jet.OLEDB.4.0; Data Source =" & Server.MapPath ("db \ Database.mdb") – onedaywhen

+0

... y no estoy seguro de qué es lo que este objeto 'Servidor' está utilizando para servir hasta objetos ADO (más habitual para usar el registro de la máquina local) y resolver la ruta a su archivo de base de datos. Considere la posibilidad de que la mayoría de la gente aquí no haga referencia al objeto Servidor y solo obtendrá los errores 'Objeto requerido' en estas líneas. – onedaywhen

1

Otra manera de hacer esto que parece que nadie ha mencionado es para unir la gráfica para un solo QueryDef salvado y después en tiempo de ejecución, reescribir el QueryDef. Ahora, no recomiendo alterar QueryDefs guardados para la mayoría de los contextos, ya que causa la saturación inicial y generalmente ni siquiera es necesario (la mayoría de los contextos donde utiliza un QueryDef guardado se pueden filtrar de una manera u otra en el contexto en el que se utilizan, por ejemplo, como Recordsource de un formulario, solo pasa un argumento en DoCmd.OpenForm).

Los gráficos son diferentes porque el SQL que controla los gráficos no se puede modificar en el tiempo de ejecución.

Algunos tienen parámetros sugeridos, pero la apertura de un formulario con un gráfico que utiliza una cadena de SQL con parámetros va a mostrar los cuadros de diálogo de parámetros predeterminados. Una forma de evitar esto es utilizar una forma de diálogo para recoger los criterios y establezca las referencias a los controles en el formulario de diálogo como parámetros, por ejemplo:

PARAMETERS [Forms]![MyForm]![ID] Long; 

Si está utilizando de forma referencias, es crucial que usted hace esto, porque desde Access 2002 en adelante, el servicio Jet Expression no siempre procesa correctamente estos cuando los controles son nulos. Definirlos como parámetros rectifica ese problema (que no estaba presente antes de Access XP).

Una situación en la que debe reescribir el QueryDef para un gráfico es si desea permitir que el usuario elija el N en una sentencia TOP N SQL. En otras palabras, si desea que puedan elegir TOP 5 o TOP 10 o TOP 20, deberá modificar QueryDef guardado, ya que N no se puede parametrizar.

1

"si desea permitir que el usuario elija la N en una declaración TOP N SQL" - bueno, podría usar una subconsulta correlacionada (en lugar de SQL dinámico), p. (Sintaxis modo de consulta ANSI-92):

CREATE PROCEDURE GetOrdersTopN 
(
:N INTEGER 
) 
AS 
SELECT O1.OrderDate, O1.CustomerID 
    FROM Orders AS O1 
WHERE :N >= (SELECT COUNT(*) + 1 
       FROM Orders AS O2 
       WHERE O1.OrderDate < O2.OrderDate); 

... pero la última vez que revisé el motor de acceso no estaba bien optimizado (por decirlo suavemente) para este tipo de construcción.

+0

gracias! no estoy seguro de haber llegado todavía, ¡pero así es como aprendo! – Justin

Cuestiones relacionadas