Domanda

Voglio eseguire un elenco di query su un database di Access utilizzando DAO. Il " Database.Execute () " il metodo sembra adatto a questo con l'osservazione che può eseguire solo "query di azioni", ovvero query che non restituiscono un set di risultati ( riferimento MSDN ). Per query che restituiscono record "Database.OpenRecordset ()" può essere utilizzato. Entrambi i metodi generano eccezioni se viene passato il tipo di query errato.

Avere entrambe le query di azione e selezionare le query nell'elenco come posso decidere in anticipo quale restituirà i record e quali no?

È stato utile?

Soluzione 3

Ispirato dalla risposta di @ HansUp, ho studiato un po 'di più la struttura QueryDef fornita dall'interfaccia DAO. La struttura ha un "Tipo" proprietà che posso utilizzare per differenziare i diversi tipi di query ( MSDN ) . Ho finito con la seguente implementazione:

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;

Grazie a tutti per le utili risposte e osservazioni.

Altri suggerimenti

Si noti che il metodo ADO Execute può essere utilizzato indipendentemente dal fatto che la query restituisca o meno un gruppo di risultati.

Ma vuoi davvero eseguire tutte le "query"? Cosa succede se contengono SQL DDL? Considera di aver creato un PROCEDURE utilizzando questo codice DDL SQL:

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

;)

Access mantiene una tabella di sistema nascosta chiamata MSysObjects che include un campo (Flag) che memorizza un valore che indica il tipo di query. È possibile provare la seguente funzione con ciascuno dei nomi di query dall'elenco e utilizzare il valore restituito per determinare se utilizzare Database.Execute () o Database.OpenRecordset ()

La funzione richiede l'autorizzazione di lettura per MSysObjects. Ho sentito delle segnalazioni che ad alcuni utenti di Access 2007 è stata negata l'autorizzazione a leggere MSysObjects. Tuttavia, non ho riscontrato questo problema con Access 2007.

Ho testato diversi tipi di query per determinare i valori Flags. Se una delle tue query è di un tipo che non ho verificato, la funzione restituirà il valore Flags come non riconosciuto. Puoi modificare la funzione per includere quel tipo di flag.

L'unica query DDL che ho testato era DROP TABLE (Flags = 96).

Inoltre, tieni presente che non tutto " SELEZIONA ... DA ... " le query sono query selezionate per il tuo scopo (restituzione di un recordset). Una query come " SELECT campi IN newtable FROM oldtable; " non restituisce record e l'interfaccia utente di Access lo classifica come query Crea tabella.

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

Perché non cogli l'eccezione generata e la analizzi?

Hai qualche modo di usare un'istruzione beginTrans / Rollback? È quindi possibile inviare il comando SQL, raccogliere gli errori, quindi ripristinare le transazioni, lasciando invariato il database.

Che dire dell'utilizzo della connessione ADO, un po 'più intelligente di quella ADO, in cui la connessione contiene una raccolta di "errori" e restituisce altri dati come il numero di record interessati?

Queste informazioni si applicano al tipo di query. Quindi:

  • Tutte le query che eseguono un SELEZIONA ... DA ... sono seleziona query
  • Tutte le INSERT , AGGIORNAMENTO , ELIMINA sono query di azioni

Devi solo ispezionare il testo del comando query sql per vedere se inizia con una delle parole chiave sopra e agire di conseguenza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top