Question

Je souhaite exécuter une liste de requêtes sur une base de données Access à l'aide de DAO. La base de données " Database.Execute () " Cette méthode semble convenir à cela, car elle indique qu'elle ne peut exécuter que des "requêtes d'action", c'est-à-dire des requêtes qui ne renvoient pas de jeu de résultats ( référence MSDN ). Pour les requêtes qui renvoient des enregistrements "Database.OpenRecordset ()" " peut être utilisé. Les deux méthodes lèvent des exceptions si le type de requête incorrect est transmis.

Avoir les deux requêtes d’action et les requêtes de sélection dans la liste, comment puis-je décider en amont qui renvoie ou non les enregistrements?

Était-ce utile?

La solution 3

Inspiré par la réponse de @ HansUp, j'ai étudié un peu plus la structure QueryDef fournie par l'interface DAO. La structure a un "Type". propriété que je peux utiliser pour différencier différents types de requêtes ( MSDN ) . Je me suis retrouvé avec l'implémentation suivante:

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;

Merci à tous pour vos réponses et remarques utiles.

Autres conseils

Notez que la méthode ADO Execute peut être utilisée que la requête retourne ou non un jeu de résultats.

Mais voulez-vous vraiment exécuter toutes les "requêtes"? Et s'ils contiennent du DDL SQL? Considérez que vous avez créé une PROCEDURE en utilisant ce code SQL DDL:

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

;)

Access maintient une table système cachée appelée MSysObjects, qui comprend un champ (Flags) qui stocke une valeur indiquant le type de requête. Vous pouvez essayer la fonction suivante avec chacun des noms de requête de votre liste et utiliser la valeur de retour pour déterminer s'il faut utiliser Database.Execute () ou Database.OpenRecordset ()

La fonction nécessite une autorisation de lecture pour MSysObjects. J'ai entendu dire que certains utilisateurs d'Access 2007 se voient refuser l'autorisation de lire MSysObjects. Cependant, je n'ai pas rencontré ce problème avec Access 2007.

J'ai testé plusieurs types de requêtes pour déterminer les valeurs des indicateurs. Si l'une de vos requêtes est d'un type que je n'ai pas testé, la fonction renvoie la valeur Flags comme non reconnue. Vous pouvez modifier la fonction pour inclure ce type de drapeaux.

La seule requête DDL que j'ai testée était DROP TABLE (Flags = 96).

Sachez également que tous les " SELECT ... FROM ... " les requêtes sont des requêtes sélectionnées pour votre objectif (renvoyer un jeu d'enregistrements). Une requête telle que "SELECT fields " dans newtable FROM oldtable; " ne renvoie pas d'enregistrements et l'interface utilisateur d'accès le classe comme une requête Make Table.

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

Pourquoi ne pas capturer l'exception levée et l'analyser?

Avez-vous un moyen d’utiliser une instruction beginTrans / Rollback? Vous pouvez ensuite envoyer votre commande SQL, collecter les erreurs, puis annuler vos transactions en laissant votre base de données inchangée.

Qu'en est-il de l'utilisation de la connexion ADO, un peu plus intelligente que celle ADO, où la connexion contient une collection "erreurs" et renvoie d'autres données, telles que le nombre d'enregistrements affectés?

Cette information s'applique au type de la requête. Donc:

  • Toutes les requêtes qui exécutent un SELECT ... FROM ... sont des requêtes de sélection
  • Tous les INSERT , MISE À JOUR , SUPPRIMER sont des requêtes d'action

Il vous suffit d'examiner le texte de la commande sql de la requête pour voir s'il commence par l'un des mots clés ci-dessus et agir en conséquence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top