sql >> Databasteknik >  >> RDS >> Access

Hur pratar Access med ODBC-datakällor? Del 6

Effekt av kopplingar i en postuppsättning

I vår sjätte och sista artikel i ODBC-spårningsserien kommer vi att ta en titt på hur Access kommer att hantera anslutningar i Access-frågor. I den tidigare artikeln såg du hur filter hanteras av Access. Beroende på uttrycket kan Access välja att parametrisera bort det eller tvingas utvärdera det själv genom att ladda ner all indata och sedan utföra utvärderingarna lokalt. I den här artikeln kommer vi att fokusera på sammanfogningar. När du tänker efter är sammanfogningar faktiskt en speciell typ av filter. Därför, i teorin, borde Access distanseras så mycket som möjligt även med joins. Du kanske vanligtvis ser joins skrivna i följande pseudo-SQL:

FRÅN en INRE JOIN b PÅ a.ID =b.ID
Det kan dock anses likvärdigt med följande syntax:

FRÅN a, b WHERE a.ID =b.ID
Det illustrerar att även om vi kan använda den mer läsbara och välbekanta JOIN..ON , Access är gratis för att behandla det som en WHERE vilket är användbart i situationer där Access inte kan fjärrstyra frågan helt. Men här är rubbet ... när bestämmer Access sig för att fjärransluta anslutningarna? Låt oss prova en enkel kopplingsfråga:

VÄLJ c.CityID ,c.StateProvinceID ,c.CityName ,s.StateProvinceNameFROM Cities AS c INNER JOIN StateProvinces AS s ON c.StateProvinceID =s.StateProvinceID;
Om vi ​​spårar den frågan kommer vi att se följande utdata:

SQLExecDirect:VÄLJ "c"."CityID" ,"s"."StateProvinceID" FRÅN "Application"."Städer" "c", "Application"."StateProvinces" "s" WHERE ("c"." StateProvinceID" ="s"."StateProvinceID" ) SQLPrepare:VÄLJ "CityID" ,"CityName" ,"StateProvinceID" FRÅN "Application"."Cities" WHERE "CityID" =?SQLEExecute:(GOTO BOOKMARK)SQLPrepare:SELECTID "State" " ,"StateProvinceName" FRÅN "Application"."StateProvinces" WHERE "StateProvinceID" =?SQLEExecute:(GOTO BOOKMARK)SQLPrepare:VÄLJ "StateProvinceID" ,"StateProvinceName" FRÅN "ApplicationState"."StateProvinces" "ProvinceID" WHERE? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =? ELLER "StateProvinceID" =?SQLEExecute:(MULTI-RAW FETCH)SQLPrepare:VÄLJ "CityID" ,"CityName" ,"StateProvinceID" FRÅN "Application"."Cities" WHERE "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =?SQLEexekvera:(FLERA RADSHÄMTA)SQLEexekvera:(FLERARADERSHÄMTA)SQLEexekvera:(FLERARADERHÄMTA)SQLEexekvera:(FLERARADERHÄMTA)SQLExecute:(QMETCHUT:(QMETCHUT) -ROW FETCH)SQLEexekvera:(MULTI-ROW FETCH)SQLEexecute:(MULTI-ROW FETCH)SQLEexecute:(MULTI-ROW FETCH)
Access beslutade att inte fjärransluta anslutningen, även om den ursprungliga Access-frågan är perfekt att köra på SQL Server. Istället fick den ID:n från varje tabell i en theta-join och satte sedan upp 2 separata kedjor av frågor som om vi hade öppnat 2 dynaset-typ-postuppsättningar. De två olika förberedda frågorna matas sedan med nycklarna för respektive tabell från den första frågan. Förutsägbart kan det vara mycket prat att gå över nätverket.

Om vi ​​ändrar samma Access-fråga till att vara en snapshot-typ istället för standarddynaset-typen får vi:

SQLExecDirect:VÄLJ "c"."Stads-ID" ,"c"."Stadsnamn" ,"c"."StateProvinceID" ,"s"."StateProvinceName" FRÅN "Application"."Städer" "c", " Application"."StateProvinces" "s" WHERE ("c"."StateProvinceID" ="s"."StateProvinceID" )
Så Access fjärransluter kopplingarna bra när det gäller en fråga av ögonblicksbildstyp. Varför gjorde inte Access det med den ursprungliga sökfrågan av dynaset-typ? Ledtråden finns i följande skärmdump där vi försöker redigera båda tabellernas kolumner i följande skärmdump:

En sådan fråga tillåter uppdatering till båda kolumnerna. Det är faktiskt inte uttryckligt i SQL men en sådan åtgärd är laglig för användaren att utföra. Därför, för att utföra den uppdateringen, skulle Access skicka följande ODBC SQL:

SQLExecDirect:UPPDATERA "Application"."StateProvinces" SET "StateProvinceName"=? VAR "StateProvinceID" =? AND "StateProvinceName" =?SQLExecDirect:UPPDATERA "Application"."Cities" SET "CityName"=? VAR "CityID" =? OCH "Stadsnamn" =? OCH "StateProvinceID" =?
Det skulle inte vara möjligt om Access inte hade den information som krävs för att uppdatera varje tabell, vilket förklarar varför Access valde att inte fjärransluta anslutningen när den löste den ursprungliga frågan av dynaset-typ. Lärdomen här är att om du inte behöver en fråga för att kunna uppdateras, och den resulterande informationen är tillräckligt liten, kan det vara bättre att konvertera frågan till en ögonblicksbildstyp. I fallet där du behöver formulera en komplex postkälla, kommer du vanligtvis att få mycket bättre prestanda med en SQL-vy som bas än att göra kopplingarna på Access-sidan.

För att bevisa detta kommer vi att skapa en SQL-vy och länka den till Access:

SKAPA VY dbo.vwCitiesAndStates ASSELECT c.CityID ,c.StateProvinceID ,c.CityName ,s.StateProvinceNameFROM Application.Cities AS c INNER JOIN Application.StateProvinces AS s ON c.StateProvinceID =s.StateProvinceID;

Vi justerar sedan Access-frågan enligt följande:

VÄLJ c.CityID ,c.StateProvinceID ,c.CityName ,c.StateProvinceNameFROM vwCitiesAndStates AS c;
Om vi ​​sedan upprepar uppdateringen vi försökte ursprungligen, bör vi se följande spårade ODBC SQL:

SQLExecDirect:VÄLJ "c"."CityID" FRÅN "dbo"."vwCitiesAndStates" "c" SQLPrepare:VÄLJ "CityID" ,"StateProvinceID" ,"CityName" ,"StateProvinceName" FRÅN "dbo"."vwCitiesAndStates" WHERE "CityID" =?SQLEExecute:(GOTO BOOKMARK)SQLPrepare:VÄLJ "CityID" ,"StateProvinceID" ,"CityName" ,"StateProvinceName" FRÅN "dbo"."vwCitiesAndStates" VAR "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =? ELLER "CityID" =?SQLEexecute:(MULTI-ROW FETCH)SQLEexecute:(MULTI-RAW FETCH)SQLEexecute:(MULTI-ROW FETCH)SQLEexecute:(MULTI-RAW FETCH)SQLExecute:(MULTI-RAW FETCH) BOOKMARK)SQLExecDirect:UPPDATERA "dbo"."vwCitiesAndStates" SET "CityName"=?, "StateProvinceName"=? VAR "CityID" =? OCH "StateProvinceID" =? OCH "Stadsnamn" =? OCH "StateProvinceName" =?
Detta visar att när du använder SQL-vyer för att "fjärrstyra" anslutningarna, kommer Access bara att fungera med en enda källa, snarare än med 2 tabeller och fjärruppdateringen av vyn helt till SQL Server. En bieffekt är att den här uppdateringen nu kommer att misslyckas med felmeddelandet:

Det borde inte komma som en överraskning eftersom vi gjorde en UPDATE på en enda källa, medan Access i det ursprungliga exemplet faktiskt i hemlighet utfärdade två separat UPDATE påståenden på varje enskild tabell. Förhoppningsvis bidrar det till att du bör undvika att göra joins i Access-frågor/recordsources/rowsources, särskilt när de behöver kunna uppdateras. Om de inte gör det, använd ögonblicksbild där det är möjligt.

En snabb anteckning om heterogena sammanfogningar

Vi måste kommentera angående kopplingar mellan två länkade tabeller som kommer från två olika ODBC-datakällor. Sådana kopplingar är "heterogena" eftersom Access måste hantera kopplingarna lokalt eftersom varje datakälla antas inte känna till varandra. Oavsett om du anger postuppsättningar av dynaset- eller snapshot-typ, måste Access hämta hela uppsättningen nycklar från varje datakälla och lösa kopplingarna genom att skicka separata parametriserade frågor till varje datakälla. Om uppdatering tillåts kommer Access att formulera en separat UPDATE fråga till varje datakälla som behöver uppdateras. Det är också viktigt att notera att en koppling mellan två länkade tabeller som kommer från två olika databaser var och en fortfarande betraktas av Access som heterogen. Det är fortfarande sant även om de två databaserna finns på samma server och du inte har några problem med att göra korsdatabasfrågor. I det här scenariot kan en SQL-vy hjälpa till att minska det extra chatt genom att dölja korsdatabaskopplingarna från Access liknande det vi såg redan i den här artikeln.

Skillnad i syntax för yttre koppling

Så länge de yttre kopplingarna inte påverkar uppdateringsbarheten för Access-frågan kommer Access att hantera den på samma sätt som den hanterade versionen av den inre kopplingen. Om vi ​​ändrar samma fråga som vi brukade vara en vänsterkoppling, kommer den spårade ODBC SQL-koden att mata ut nyckelpopulationsfrågan så här:

SQLExecDirect:VÄLJ "c"."CityID" ,"s"."StateProvinceID" FRÅN {oj "Application"."Cities" "c" VÄNSTER YTTRE JOIN "Application"."StateProvinces" "s" PÅ (" c"."StateProvinceID" ="s"."StateProvinceID" ) }
Syntaxen ser helt annorlunda ut än vad du kan förvänta dig i andra SQL-dialekter. Det beror på att ODBC SQL-grammatik kräver att alla yttre kopplingar lindas in i en {oj ...} uttryck. Mer information om den syntaxen finns i dokumentationen. För vårt syfte kan vi bara bortse från {oj och den avslutande } som brus.

Slutsatser

Vi såg att joins behandlas som om de är ett slags filter och Access kommer att försöka fjärrstyra joins där det är tillåtet. Ett särskilt område att vara mycket uppmärksam på är det faktum att vi som standard använder dynaset-postuppsättningar och Access kommer inte att göra några antaganden om huruvida vi vill tillåta modifiering av si och så-kolumner i postuppsättningen och gör allt för att göra det möjligt för oss att uppdatera till två tabeller som faktiskt inte är lätt att uttrycka i standard SQL. Som en konsekvens kommer Access att göra mycket mer arbete för att stödja uppdateringsbarhet för en fråga som innehåller kopplingar som kan påverka prestandan negativt.

Vi kan hjälpa till att undvika påföljden genom att använda SQL-vyer i stället för kopplingar som uttrycks i en Access-fråga. Avvägningen är att vi då är föremål för uppdateringsreglerna för en SQL-vy; vi kanske inte får uppdatera två tabeller samtidigt. Vanligtvis eftersom ett väldesignat åtkomstformulär bara representerar en enda tabell att uppdatera, är det inte mycket av en begränsning och är en bra disciplin att följa.

Därmed är den aktuella serien klar. Inlärningen som serien förhoppningsvis gnistor bör dock inte göras. Jag hoppas verkligen att du tyckte att serien var användbar och ser fram emot att höra om nya insikter du fått genom att använda verktyg för att analysera och åtgärda prestandaproblem med Access-applikationer som använder ODBC-datakällor. Lämna gärna kommentarer eller begär mer information och tack för att ni läser tillsammans!

För ytterligare hjälp med allt relaterat till Microsoft Access, ring våra experter på 773-809-5456 eller maila oss på [email protected].


  1. Fungerar funktionen snabbare utan STRICT modifierare?

  2. DELETE VS DROP i SQL

  3. Välj n slumpmässiga rader från SQL Server-tabellen

  4. Ändra MySQL standardteckenuppsättning till UTF-8 i my.cnf?