Access
 sql >> база данни >  >> RDS >> Access

Как Access общува с ODBC източници на данни? част 6

Ефект от обединяването в набор от записи

В нашата шеста и последна статия от поредицата за проследяване на ODBC ще разгледаме как Access ще обработва присъединяванията в заявките на Access. В предишната статия видяхте как филтрите се обработват от Access. В зависимост от израза, Access може да избере да го параметризира или може да бъде принуден да го оцени сам, като изтегли всички входни данни, след което извърши оценките локално. В тази статия ще се съсредоточим върху съединенията. Като се замислите, съединенията всъщност са специален вид филтър. Следователно, на теория, Access трябва да се отдалечава колкото е възможно повече дори и с присъединявания. Обикновено може да видите съединения, написани в следния псевдо-SQL:

FROM a INNER JOIN b ON a.ID = b.ID
Въпреки това, той може да се счита за еквивалентен на следния синтаксис:

FROM a, b WHERE a.ID = b.ID
Това илюстрира, че въпреки че може да използваме по-четливия и познат JOIN..ON , Access е безплатен да го третира като WHERE което е полезно в ситуации, когато Access не може напълно да отдалечи заявката. Но тук е проблемът... кога Access решава да отдалечи присъединяванията? Нека опитаме проста заявка за присъединяване:

SELECT 
   c.CityID
  ,c.StateProvinceID
  ,c.CityName
  ,s.StateProvinceName
FROM Cities AS c 
INNER JOIN StateProvinces AS s 
  ON c.StateProvinceID = s.StateProvinceID;
Ако проследим тази заявка, ще видим следния изход:

SQLExecDirect: 
SELECT 
   "c"."CityID"
  ,"s"."StateProvinceID" 
FROM "Application"."Cities" "c",
     "Application"."StateProvinces" "s" 
WHERE ("c"."StateProvinceID" = "s"."StateProvinceID" ) 

SQLPrepare: 
SELECT 
  "CityID"
 ,"CityName"
 ,"StateProvinceID"  
FROM "Application"."Cities"  
WHERE "CityID" = ?

SQLExecute: (GOTO BOOKMARK)

SQLPrepare: 
SELECT 
   "StateProvinceID"
  ,"StateProvinceName"  
FROM "Application"."StateProvinces"  
WHERE "StateProvinceID" = ?

SQLExecute: (GOTO BOOKMARK)

SQLPrepare: 
SELECT 
   "StateProvinceID"
  ,"StateProvinceName"  
FROM "Application"."StateProvinces"  
WHERE "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ? 
   OR "StateProvinceID" = ?

SQLExecute: (MULTI-ROW FETCH)

SQLPrepare: 
SELECT 
   "CityID"
  ,"CityName"
  ,"StateProvinceID"  
FROM "Application"."Cities"  
WHERE "CityID" = ? 
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?  
   OR "CityID" = ?

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Access реши да не отдалечава присъединяването, въпреки че оригиналната заявка на Access е напълно способна да бъде изпълнена в SQL Server. Вместо това той получи идентификаторите от всяка таблица в тета-съединяване, след което създаде 2 отделни вериги от заявки, сякаш сме отворили 2 набора от записи от тип dynaset. Двете различни подготвени заявки след това се подават на ключовете за съответните таблици от първата заявка. Очаквано е, че това може да бъде много бърборене, за да се пренесе в мрежата.

Ако променим същата заявка за достъп да бъде тип моментна снимка вместо тип dynaset по подразбиране, получаваме:

SQLExecDirect: 
SELECT 
   "c"."CityID"
  ,"c"."CityName"
  ,"c"."StateProvinceID"
  ,"s"."StateProvinceName"  
FROM "Application"."Cities" "c",
     "Application"."StateProvinces" "s" 
WHERE ("c"."StateProvinceID" = "s"."StateProvinceID" )
Така че Access отдалечава връзките добре в случай на заявка от тип моментна снимка. Защо Access не направи това с оригиналната заявка от тип dynaset? Уликата е в следващата екранна снимка, където се опитваме да редактираме и двете колони на таблици на следната екранна снимка:

Такава заявка позволява актуализиране на двете колони. Това всъщност не може да се изрази в SQL, но такова действие е законно за потребителя. Следователно, за да изпълни тази актуализация, Access ще изпрати следния ODBC SQL:

SQLExecDirect: 
UPDATE "Application"."StateProvinces" 
SET "StateProvinceName"=?  
WHERE "StateProvinceID" = ? 
  AND "StateProvinceName" = ?

SQLExecDirect: 
UPDATE "Application"."Cities" 
SET "CityName"=?  
WHERE "CityID" = ? 
  AND "CityName" = ? 
  AND "StateProvinceID" = ?
Това не би било възможно, ако Access нямаше информацията, необходима за актуализиране на всяка таблица, което обяснява защо Access е избрал да не отдалечава присъединяването при разрешаване на оригиналната заявка от тип dynaset. Урокът тук е, че ако не се нуждаете от заявка, за да може да се актуализира, и получените данни са достатъчно малки, може да е по-добре да конвертирате заявката в тип моментна снимка. В случай, когато трябва да формулирате сложен източник на записи, обикновено ще получите много по-добра производителност, като използвате SQL изглед като основа, отколкото извършването на обединявания от страна на Access.

За да докажем това, ще създадем SQL изглед и ще го свържем с Access:

CREATE VIEW dbo.vwCitiesAndStates AS
SELECT 
  c.CityID
  ,c.StateProvinceID
  ,c.CityName
  ,s.StateProvinceName
FROM Application.Cities AS c 
INNER JOIN Application.StateProvinces AS s 
  ON c.StateProvinceID = s.StateProvinceID;
; След това коригираме заявката за достъп, както следва:

SELECT 
   c.CityID
  ,c.StateProvinceID
  ,c.CityName
  ,c.StateProvinceName
FROM vwCitiesAndStates AS c;
Ако след това повторим актуализацията, която опитахме първоначално, трябва да видим следния проследен ODBC SQL:

SQLExecDirect: 
SELECT "c"."CityID" 
FROM "dbo"."vwCitiesAndStates" "c" 

SQLPrepare: 
SELECT 
   "CityID"
  ,"StateProvinceID"
  ,"CityName"
  ,"StateProvinceName"  
FROM "dbo"."vwCitiesAndStates"  
WHERE "CityID" = ?

SQLExecute: (GOTO BOOKMARK)

SQLPrepare: 
SELECT 
   "CityID"
  ,"StateProvinceID"
  ,"CityName"
  ,"StateProvinceName"  
FROM "dbo"."vwCitiesAndStates"  
WHERE "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ? 
  OR "CityID" = ?

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (GOTO BOOKMARK)

SQLExecDirect: 
UPDATE "dbo"."vwCitiesAndStates" 
SET "CityName"=?,
    "StateProvinceName"=?  
WHERE "CityID" = ?
  AND "StateProvinceID" = ?
  AND "CityName" = ? 
  AND "StateProvinceName" = ?
Това демонстрира, че използвайки SQL изгледи за „отдалечено“ свързване, Access ще работи само с един източник, а не с 2 таблици и ще отдалечи актуализацията на изгледа изцяло към SQL Server. Един страничен ефект е, че тази актуализация вече ще се провали със съобщението за грешка:

Това не трябва да е изненада, тъй като правихме UPDATE на един източник, докато в оригиналния пример Access всъщност тайно издаваше два отделно UPDATE изявления на всяка отделна таблица. Надяваме се, че това ще помогне да се обоснове, че трябва да избягвате да правите обединявания в заявки на Access/recordsources/rowsources, особено когато те трябва да бъдат актуализирани. Ако не го направят, използвайте моментна снимка, където е възможно.

Бърза бележка относно хетерогенните съединения

Трябва да коментираме връзките между две свързани таблици, които идват от два различни източника на ODBC данни. Такива обединения са „хетерогенни“, тъй като Access трябва да обработва обединяванията локално, тъй като се предполага, че всеки източник на данни не знае един за друг. Независимо дали сте посочили набори от записи от тип dynaset или моментна снимка, Access трябва да извлече пълния набор от ключове от всеки източник на данни и да разреши обединяванията, като изпрати отделни параметризирани заявки към всеки източник на данни. Ако актуализирането е разрешено, Access ще формулира отделен UPDATE заявка към всеки източник на данни, който трябва да бъде актуализиран. Също така е важно да се отбележи, че присъединяването между две свързани таблици, което идва от две различни бази данни, всяка от които все още се счита от Access като хетерогенна. Това все още е вярно, дори ако двете бази данни са на един и същ сървър и нямате проблем да правите кръстосани заявки за база данни. В този сценарий изгледът на SQL може да помогне за намаляване на допълнителния бърборене, като скрие кръстосаните присъединявания към база данни от Access, подобно на това, което видяхме вече в тази статия.

Разлика в синтаксиса на външно присъединяване

Докато външните обединявания не влияят върху актуализацията на заявката на Access, Access ще я обработва подобно на начина, по който се справяше с версията за вътрешно присъединяване. Ако модифицираме същата заявка, която използвахме като ляво присъединяване, проследеният ODBC SQL ще изведе ключовата популационна заявка по следния начин:

SQLExecDirect: 
SELECT 
   "c"."CityID"
  ,"s"."StateProvinceID" 
FROM {oj 
	"Application"."Cities" "c" 
	LEFT OUTER JOIN "Application"."StateProvinces" "s" 
		ON ("c"."StateProvinceID" = "s"."StateProvinceID" ) 
}
Синтаксисът изглежда доста различен от това, което може да очаквате в други SQL диалекти. Това е така, защото граматиката на ODBC SQL изисква всички външни съединения да бъдат обвити в {oj ...} изразяване. За повече подробности относно този синтаксис вижте документацията. За нашата цел можем просто да пренебрегнем {oj и затварящият } като шум.

Заключения

Видяхме, че присъединяванията се третират така, сякаш са вид филтър и Access ще се опита да отдалечи връзките, където му е разрешено. Една конкретна област, на която трябва да обърнете специално внимание, е фактът, че по подразбиране използваме набори от записи от типа dynaset и Access няма да прави никакви предположения дали искаме да разрешим промяна на тези и така колони в набора от записи и се опитва да направи това възможно за нас да актуализирате до две таблици, което всъщност не се изразява лесно в стандартен SQL. В резултат на това Access ще върши много повече работа, за да поддържа актуализация за заявка, която съдържа обединения, което може да повлияе негативно на производителността.

Можем да помогнем за избягване на наказанието, като използваме SQL изгледи вместо съединения, изразени в заявка за Access. Компромисът е, че след това сме обект на правилата за актуализиране на SQL изглед; може да не ни е позволено да актуализираме две таблици едновременно. Обикновено, тъй като добре проектираният формуляр за достъп ще представлява само една таблица за актуализиране, това не е голямо ограничение и е добра дисциплина, която да следвате.

С това текущата серия е готова. Въпреки това, научаването, което се надяваме да запали поредицата, не трябва да се прави. Искрено се надявам, че сте намерили поредицата за полезна и с нетърпение очаквате да чуете за нови прозрения, които сте получили от използването на инструменти за анализ и справяне с проблеми с производителността с приложения на Access, използващи източници на ODBC данни. Чувствайте се свободни да оставяте коментари или да поискате повече информация и благодаря, че четете заедно!

За допълнителна помощ относно всичко, свързано с Microsoft Access, обадете се на нашите експерти на 773-809-5456 или ни изпратете имейл на [email protected].


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво е новото в Access 2016? Заслужава ли си надграждане?

  2. Използване на Microsoft Access с Power BI

  3. Корупция на MS Access, част 2:Най-добри практики за превенция и възстановяване

  4. Как да уплътните и поправите автоматично база данни в Access 2016

  5. Кои са 6-те основни компонента на Microsoft Access?