2008-12-08 9 views
2

J'ai une base de données MS Access avec des tables liées, chaque fois que chaque table est liée à une table dans la même base de données SQL Server. J'ai une requête dans Access qui joint deux tables (en particulier je mets à jour une table basée sur une autre en utilisant une jointure).Comment MS Access rejoint-il des tables liées (liées à la même base de données SQL Server)?

La question est fait Accès "télécharger" toutes les données de la table avant de faire une jointure? Ou est intelligent et rejoint sur le serveur SQL?

La requête est:

UPDATE TBL_INVOICE_CHARGES INNER JOIN TBL_ANI 
ON (TBL_INVOICE_CHARGES.CH_CUST_ID = TBL_ANI.ANI_CUST_ID) 
AND (TBL_INVOICE_CHARGES.CH_ANI = TBL_ANI.ANI_NZ_ANI) 
SET TBL_INVOICE_CHARGES.ANI_NOTES = TBL_ANI.ANI_NOTES; 

Répondre

0

Je l'ai regardé SQL Profiler (malheureusement je n'ai pas le journal réelle à portée de main) et voici ce que j'ai trouvé:

  • il sélectionne tous les enregistrements des deux tables
  • pour chaque enregistrement dans un table appelle un UPDATE Donc, ce sera lent.
2

Selon Albert D. Kallal (accès MVP), l'accès ne tire pas toutes les tables, à l'exception des vues complexes, où les choses peuvent se foiré. Cependant, il est préférable d'utiliser les vues sur le serveur et de lier la vue, ou d'utiliser des requêtes de passage.

Informations complémentaires: How to create an SQL pass-through query in Access

2

Jet probable remettra de la chose à SQL Server, qui fera un join index puis effectuez les mises à jour. En d'autres termes, pour une requête simple comme votre exemple, c'est tous étant fait sur le serveur, avec pas un octet tiré à travers le fil pour le traitement local.

Il est assez facile de faire en sorte que Jet tire toute la table. Le plus simple est de mettre une expression Access dans votre clause WHERE. Voici un exemple qui causerait que cela se produise:

WHERE Format(MyDate,"YYYY") = 2008 

Toute la table va être tiré de telle sorte que l'accès peut exécuter la fonction Format() sur toutes les dates de votre table. De plus, il ne pourra pas utiliser d'index et sera donc très lent. Ce serait aussi lent avec un backend Jet, tout simplement parce que c'est trop inefficace. La bonne façon d'écrire cette clause WHERE est:

WHERE MyDate Between #1/1/2008# And #12/31/2008# 

Si vous écrivez que dans une requête d'accès enregistré, il sera transféré au serveur SQL pour le traitement (et ODBC envoie délimiteurs appropriés si votre arrière db le moteur utilise différents ceux que Jet SQL utilise). Mais si vous ne faites pas ce genre de chose, il est peu probable que vous rencontriez le problème de tirer trop de données à travers le réseau. Jet est, en fait, très intelligent, et fait un travail remarquablement bien d'envoyer autant de requête à travers le fil pour le traitement que possible. Par exemple, si vous appelez des fonctions Access dans votre instruction SELECT, la sélection sous-jacente sans les fonctions Access sera envoyée au serveur et les fonctions seront alors exécutées dans Access sur le jeu de résultats. Pour cette requête d'accès:

SELECT Format(MyDate,"MM-DD") 
    FROM MyTable 
    WHERE MyDate Between #1/1/2008# And #12/31/2008# 

Jet envoie ceci au serveur:

SELECT MyDate 
    FROM MyTable 
    WHERE MyDate Between #1/1/2008# And #12/31/2008# 

Une fois que Jet a reçu du serveur uniquement les lignes qui correspondent aux critères, il ne puis formatez le champ de date en utilisant la fonction Access Format(). Cela fonctionne également avec JOINs, en particulier les jointures sur des champs indexés (bien que les jointures de champs non indexées soient probablement également transmises au serveur). Maintenant, il arrive que Jet devine mal et finit par être incroyablement inefficace. Dans ces cas, vous pouvez configurer des vues et des procédures stockées sur le serveur et utiliser des requêtes passthrough pour vous assurer que les fausses estimations de Jet seront évitées.