Exécution de requêtes à l'aide de DAO
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?
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.