Pregunta

Quiero ejecutar una lista de consultas en una base de datos de Access mediante DAO. El " Database.Execute () " El método parece adecuado para esto con la observación de que solo puede ejecutar " consultas de acción " ;, es decir, consultas que no devuelven un conjunto de resultados ( referencia de MSDN ). Para consultas que devuelven registros " Database.OpenRecordset () " puede ser usado. Ambos métodos lanzan excepciones si se pasa el tipo incorrecto de consulta.

Teniendo consultas tanto de acción como de selección en la lista, ¿cómo puedo decidir por adelantado qué devolverá los registros y cuáles no?

¿Fue útil?

Solución 3

Inspirado por la respuesta de @ HansUp, investigué un poco más la estructura QueryDef proporcionada por la interfaz DAO. La estructura tiene un " Tipo " propiedad que puedo usar para diferenciar los diferentes tipos de consulta ( MSDN ) . Terminé con la siguiente implementación:

function TAccessDatabase.SQLExec(AName, AQuery: String): Integer;
var
  I: Integer;
  QDef: QueryDef;
  QDefExists: Boolean;
begin
  Result := 0;

  // Lookup querydef in the database
  QDefExists := False;
  for I := 0 to DB.QueryDefs.Count - 1 do
  begin
    QDef := DB.QueryDefs[I];
    if QDef.Name = AName then
    begin
      QDefExists := True;
      break; //-->
    end;
  end;

  // Create query def if it doesn't exists
  if not QDefExists then
  begin
    QDef := DB.CreateQueryDef(AName, AQuery);
    // Refresh is required to get the correct QDef.Type_
    DB.QueryDefs.Refresh;
  end;

  // Execute the query only if it is not a SELECT
  if QDef.Type_ <> dbQSelect then
  begin
    db.Execute(AQuery, dbInconsistent);
    Result := DB.RecordsAffected;
  end;
end;

Gracias a todos por las útiles respuestas y comentarios.

Otros consejos

Tenga en cuenta que el método de ejecución ADO se puede utilizar independientemente de si la consulta devuelve un conjunto de resultados.

¿Pero realmente quieres ejecutar todas las 'consultas'? ¿Qué pasa si contienen SQL DDL? Considere que creó un PROCEDURE usando este código DDL de SQL:

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

;)

Access mantiene una tabla de sistema oculta llamada MSysObjects que incluye un campo (Flags) que almacena un valor que indica el tipo de consulta. Puede probar la siguiente función con cada uno de los nombres de consulta de su lista y usar el valor de retorno para determinar si debe usar Database.Execute () o Database.OpenRecordset ()

La función requiere permiso de lectura para MSysObjects. He escuchado informes de que a algunos usuarios de Access 2007 se les niega el permiso para leer MSysObjects. Sin embargo, no he encontrado ese problema con Access 2007.

Probé varios tipos de consulta para determinar los valores de los indicadores. Si una de sus consultas es un tipo que no probé, la función devolverá el valor de los indicadores como no reconocido. Puede modificar la función para incluir ese tipo de indicadores.

La única consulta DDL que probé fue DROP TABLE (Flags = 96).

Además, tenga en cuenta que no todas " SELECT ... FROM ... " las consultas son consultas selectas para su propósito (devolver un conjunto de registros). Una consulta como " Seleccionar campos EN newtable FROM oldtable; " no devuelve registros, y la IU de acceso lo clasifica como una consulta de creación de tabla.

Public Function QueryType(ByVal pQueryName As String) As String
    Dim lngFlags As Long
    Dim strType As String
    Dim strCriteria As String

    strCriteria = "[Name] = """ & pQueryName & """ And [Type] = 5"
    lngFlags = DLookup("Flags", "MSysObjects", strCriteria)

    Select Case lngFlags
    Case 0
        strType = "Select"
    Case 16
        strType = "Crosstab"
    Case 32
        strType = "Delete"
    Case 48
        strType = "Update"
    Case 64
        strType = "Append"
    Case 80
        strType = "Make Table"
    Case 96
        strType = "Drop Table"
    Case 128
        strType = "Union"
    Case Else
        strType = "Flags " & CStr(lngFlags) & " unrecognized"
    End Select

    QueryType = strType
End Function

¿Por qué no atrapas la excepción lanzada y la analizas?

¿Tiene alguna forma de usar una instrucción beginTrans / Rollback? Luego puede enviar su comando SQL, recopilar los errores y luego revertir sus transacciones, dejando su base de datos sin cambios.

¿Qué pasa con el uso de la conexión ADO, algo más inteligente que la ADO, donde la conexión contiene una colección de 'errores' y devuelve otros datos como el número de registros afectados?

Esta información se aplica al tipo de la consulta. Entonces:

  • Todas las consultas que ejecutan un SELECT ... FROM ... son consultas de selección
  • Todos INSERT , UPDATE , DELETE son consultas de acción

Solo tiene que inspeccionar el texto del comando query sql para ver si comienza con alguna de las palabras clave anteriores y actuar en consecuencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top