У меня есть база данных MS Access со связанными таблицами, когда каждая таблица связана с таблицей в той же базе данных SQL Server. У меня есть запрос внутри Access, который объединяет две таблицы (в частности, я обновляю таблицу на основе другой, используя соединение).
Вопрос в том, «загружает» ли Access все данные таблицы перед выполнением соединения? Или это умно и присоединяется к нему на SQL Server?
Запрос:
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;





По словам Альберта Д. Каллала (Access MVP), Access не извлекает целые таблицы, за исключением сложных представлений, где все может запутаться. Однако лучше всего использовать представления на сервере и ссылку на представление или использовать сквозные запросы.
Дополнительная информация: Как создать сквозной запрос SQL в Access
Скорее всего, Jet передаст все это SQL Server, который выполнит индексное соединение, а затем выполнит обновления. Другими словами, для простого запроса, подобного вашему примеру, все выполняется на сервере, и ни один байт не протягивается по сети для локальной обработки.
Довольно легко заставить Jet тянуть за собой весь стол. Самый простой способ - поместить выражение Access в предложение WHERE. Вот пример, который может вызвать это:
WHERE Format(MyDate,"YYYY") = 2008
Придется вытащить всю таблицу, чтобы Access мог запускать функцию Format () для всех дат в вашей таблице. Кроме того, он не сможет использовать какие-либо индексы и, следовательно, будет работать очень медленно. С серверной частью Jet тоже было бы медленно, просто потому, что это так неэффективно. Правильный способ написать это предложение WHERE:
WHERE MyDate Between #1/1/2008# And #12/31/2008#
Если вы напишете это в сохраненном запросе доступа, он будет передан на SQL Server для обработки (и ODBC отправит соответствующие разделители, если ваш внутренний механизм db использует отличные от того, что использует Jet SQL).
Но если вы этого не делаете, вы вряд ли столкнетесь с проблемой передачи слишком большого количества данных по сети. На самом деле Jet довольно умен и отлично справляется с отправкой как можно большего количества запросов по сети для обработки. Например, если вы вызываете функции Access в своем операторе SELECT, базовый выбор без функций Access будет отправлен на сервер, а затем функции будут выполняться в Access для набора результатов. Для этого запроса доступа:
SELECT Format(MyDate,"MM-DD")
FROM MyTable
WHERE MyDate Between #1/1/2008# And #12/31/2008#
Jet отправит это на сервер:
SELECT MyDate
FROM MyTable
WHERE MyDate Between #1/1/2008# And #12/31/2008#
Как только Jet получит от сервера только строки, соответствующие критериям, он только тогда отформатирует поле даты с помощью функции Access Format (). Это также работает с СОЕДИНЕНИЯМИ, особенно с соединениями по индексированным полям (хотя соединения с неиндексированными полями, вероятно, также будут переданы серверу).
Иногда Jet действительно ошибается и оказывается невероятно неэффективным. В этих случаях вы можете настроить представления и хранимые процедуры на сервере и использовать сквозные запросы, чтобы избежать ошибочных предположений Jet.
Я посмотрел на SQL Profiler (к сожалению, у меня нет под рукой реального журнала), и вот что я нашел: