|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Хотел бы поделиться с некоторыми своими наблюдениями, обнаруженными фактами. Хотелось бы осуществить что-то вроде «обмен мнений». В и-нете много нестандартных решений казалось бы на первый взгляд «нереальных» задач. Когда начинаешь анализировать коды, то иной раз голова идёт кругом от длинного листинга, а чтобы разобраться иной раз необходимо потратить длительное время. Но разбираться в коде хочется. Хочу начать с запросов. Есть в этом форуме несколько интересных топиков о запросах. Вот некоторые из них: - Самоправка запроса - access сам меняет запрос - Социологическое исследование: Как народ хранит запросы? и т.д., и т.д. Этот список можно продолжать достаточно долго. А собственно, почему так происходит, почему Access самопроизвольно меняет SQL текстовку запроса? На сей счёт у меня появилась версия-гипотеза. Я, конечно, не уверен в том, что мои догадки верны, хочу обсуждать с уважаемым гуру! Я считаю главной причиной «всех бед» это системная таблица « MSysQueries »! Кстати, есть интересная статейка, где как раз описываются некоторые детали данной таблицы: Как достать SQL запрос из *.mdb без MS Access Чтобы правильнее объяснить то, что я имею ввиду, пожалуй, следует произвести следующий эксперимент: Создаём простой запрос и назовем «Query1» Код: plaintext
Код: plaintext
Далее, вручную поменяем название 1-запроса как «Q1». С помощью VBA смотрим текст запроса «Query2». Код: plaintext
SQL текст запроса не изменился, хотя мы название 1-запроса поменяли. А теперь откроем запрос «Query2» в режиме таблицы (можно вручную, а можно программно открывать, эффект – одинаковый). Access не будет ругаться, что не может найти «Query1». Ещё раз запустим процедуру TestQuerySQL. Вуаля! В SQL тексте запроса «Query1» исчез, вместо него «Q1». А как это произошло? Именно благодаря системной таблице «MSysQueries»! Помимо системных таблиц видимо Access где-то «запоминает» старое и новое название объекта после переименования. А перед открытием запроса, скорее всего перепроверяет не изменились ли названия объектов, которых использует данный запрос. Если да, то автоматически сам же подправляет. Вообщем-то всё это скорее сделано для «начинающих» пользователей, которые могут изменить названия объектов базы, но при этом могут и забыть подправить запросы. Системная таблица «MSysQueries» разбивает запросы на поля и это означает, что не только название таблиц и запросов, используемые внутри определённого запроса, но и название полей имеет тот же эффект. Т.е. пусть «Таблица1» имеет поле «Поле1». Пишем такой простой запрос «Запрос1»: Код: plaintext
Но не все запросы имеют такой эффект. А именно следующие виды запросов в системной таблице «MSysQueries» вообще не разбиваются на отдельные поля: - запрос на объединение; - запрос к серверу - запрос на управление - вложенный (внутренний) и подчинённый запрос. «Запрос1» перепишем следующим образом: Код: plaintext
А вот теперь «Запрос1» у нас не будет работать правильно. Если откроете его, то Access воспримет «П1» как параметр, а не как название поля! Видать не с проста Microsoft такие виды запросов как «Объединение», «К серверу», «Управление» отделил в своем интерфейсе отдельно как «Запрос SQL». Так как ими в основном пользуются не новички, а продвинутые пользователи, то и автоматическая корректировка посчитали излишней. Итак, почему же Access самопроизвольно меняет SQL текстовку запроса? Потому что так Accessу более удобнее зафиксировать поля в системной таблице «MSysQueries». Здесь не хотелось бы использовать термин «оптимизатор запросов», ибо здесь не идёт в буквальном смысле оптимизация запросов, а скорее всего происходит «помощь чайникам». Может я сильно ошибаюсь по поводу полного отсутствия оптимизации, может и в правду хоть что-то Access наподобие SQL Server оптимизирует. Но очень часто после такой «оптимизации» сложные фильтры запроса получаются чересчур замудрёнными и порой некорректными. С одного раза даже и не понятно, что и как же запрос фильтрует. Здесь также хочу отметить, почему же вложенных запросов Access 2003 и ранние версии отмечает внутри квадратных скобок. Дело в том, что когда Вы во внутри запроса соединяете более двух таблиц / запросов через INNER, LEFT, RIGHT JOIN, то отдельные части Access заключает в обычные скобки и всё, что находится во внутри этих обычных скобок Access разбивает и размещает у себя в таблице «MSysQueries». А вот когда Accessу как бы «нет необходимости» в разбивке (т.е. случай с вложенным запросом), то для «своего удобства» отмечает эту часть SQL текста особым образом. Ну и здесь есть косяк: так сказать «оптимизатор запросов» (который «оптимизирует» SQL текст запроса для размещения в таблице «MSysQueries») видимо сначала анализирует текст и отмечает ту часть, которую не надо разбивать, квадратными скобками. Ну а если уже в тексте есть оные, то тут разработчики видимо толком не объяснили «оптимизатору» как анализировать такие тексты. Т.к. «оптимизатор» не знает, что делать, то и предпочитает ругаться. Но начиная с Access 2007 слегка такой «порядок вещей» был изменён разработчиками. Теперь «оптимизатор» не пишет квадратные скобки в SQL тексте, а держит «в уме» в момент фиксации SQL текста в системной таблице «MSysQueries». А когда кто-то изменит запрос, то и «оптимизатору» нечего ругаться, ибо в тексте изначально нет квадратных скобок. P.S. Надеюсь, народ начнёт критиковать мой топик и спорить. Как известно в спорах рождается истина. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.02.2011, 15:23 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Как оптимизировать запросы? Как известно, существуют проверенные со временем старинные «лекарства», позволяющие повысить быстродействие запросов. Вот некоторые из них: - по возможности вместо «HAVING» использовать «WHERE». Иногда требуется фильтровать данные после групповых функций таких как «MIN», «MAX», «AVG» и т.д. В таких случаях, увы фильтровать данные с помощью «WHERE» нельзя, придётся использовать «HAVING». А в остальных случаях нецелесообразно использование «HAVING». - по возможности не использовать статистических функций по подмножеству, таких как Dsum, Dcount и т.д. В некоторых случаях если требуется обновляемость запроса, то приходится использовать подобные функции. - по возможности не использовать подчинённые запросы на стороне «WHERE» или «HAVING». Иногда бизнес логика все же требует использование подчинённых запросов. - если нет необходимости сортировки, то не применять ORDER BY. Помимо этих способов Microsoft рекомендует: - по чаще сжимать базу; - использовать индексацию полей и т.д., и т.п. Всем всё это известно. Ничего нового. А вот про IIF почти ни слова! Что мы знаем про IIF? Если открыть справочник Access 2003, то там написано следующее: Функция IIf всегда вычисляет и truepart, и falsepart, хотя возвращает только одно из них. Из-за этого могут возникнуть нежелательные побочные эффекты. Например, если в falsepart произошла ошибка при делении на ноль, эта ошибка возникнет, даже если выражение будет оценено как True. Все эти слова оказались справедливы только для VBA, а вот для JET они не справедливы! Недавно Sator Arepo предоставил наиубедительнейший пример в другом топике. Код: plaintext
Код: plaintext
Из этого следует одна очень полезная фитча: Если в фильтре WHERE использованы несколько условий AND и OR, то вместо них можно использовать IIF и тогда запрос будет работать чуть быстрее. Пример: Вместо следующих условий Код: plaintext
Код: plaintext
При этом рекомендуется расположить условия наибольшего отбора выше по веткам IIF, тогда запрос станет наиболее оптимальным. Условия отбора AND в IIF надо писать с точностью до наоборот, т.е. если Вам нужно условие Field1 > 1, то следует писать IIf(Field1 <= 1, False, а в самом конце True (как указано в примере). А вот условие OR придётся писать через = примерно так: Допустим требуется фильтровать данные по следующим условиям: Код: plaintext
Код: plaintext
Функция IIF имеет ещё одно преимущество: Если использовать достаточно сложные условия отбора, то после сохранения запроса так сказать «оптимизатор» самопроизвольно «подтасует» условия так, как ему удобно (см. мой пост выше). А вот в случае IIF порядок проверки условий гарантированно не будет изменен «оптимизатором». ... |
|||
:
Нравится:
Не нравится:
|
|||
04.02.2011, 15:31 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Иногда бывает полезным установить CHECK CONTRSTRAINT к определенной таблице, который может сверять данные одной таблицы с другой. Для этого вовсе не обязательно включать опцию " Синтаксис для SQL Server (ANSI 92) ". Но в этом случае придётся установить его программно. Пример: Допустим, у нас есть таблица "Контракт", где есть поле "КодКонтракта" и "Сумма", а также есть таблица "Спецификация", где есть поля: "КодКонтракта", "КодТовара", "Цена", "Количество". Если умножить "Цена" и "Количество" товара, то получим стоимость одной позиции товара. Предположим нам нужно установить ограничение: общая сумма всех позиций по одному контракту не должна превышать сумму контракта. Как это сделать? Код: plaintext 1. 2. 3. 4. 5. 6. 7.
Ну и чтобы удалить ограничение нужно запустить такой код: Код: plaintext 1. 2. 3. 4. 5.
P.S. Ну а вообще конечно лучше использовать VBA функции, чтобы получить больше возможностей (Триггер Бенедикта). Я вышеуказанными примерами лишь подчеркнул, что включение опции " Синтаксис для SQL Server (ANSI 92) " вовсе не обязательное и как видите кириллица (по крайнем мере в А2003) проходит без проблем. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2011, 07:11 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studieren, А вот это уже интересно. Только насколько это оптимальнее чем другие способы (доп. поле в запросе(форме), рекордсет через подобную sql-строку, Dsum и т.д.)? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2011, 07:48 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
alvk, Вы на уровне базы устанавливаете ограничение. Кто-нибудь даже если создаст линкованную таблицу в "чужой базе" и попытается внести "неправильные" изменения, то уже не сможет. Правда есть маленький нюанс: предметное "ругательство" (наподобие Validation Text) не возможно установить. Для этого ИМХО триггер Бенедикта лучче! Кстати, удаление таблицы также невозможно до тех пор, пока существует CONSTRAINT. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2011, 08:05 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studieren, 1. Тоесть сообщение выдать нельзя никакое? А разве здесь error не обрабатывается?(?) 2. Что касается удаления - пофиг, кто интересно свои рабочие таблицы с данными удаляет? Только маньяк какой-нибудь.. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2011, 09:12 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Интересные факты. Всем известно, что любой запрос в MS Access может иметь максимум 255 полей. А вот в запросах на объединение (UNION) ограничение иное: Общее количество полей каждого блока запроса в сумме не должно превышать 255! Т.е. если 1-блок запроса содержит 128 полей и 2-блок запроса также имеет 128 полей, то Access будет ругаться, т.к. 128+128=256 (больше 255)!!! Пример (этот запрос не пройдёт): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
Если в запросе на объединение имеется поле МЕМО, где имеется значение больше 255 символов, то Access вернет только первые 255 символов. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 13:03 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
авторЕсли в запросе на объединение имеется поле МЕМО, где имеется значение больше 255 символов, то Access вернет только первые 255 символов. Расшифруйте, пожалуйста. По моим наблюдениям, если в 1-й запрос включить мемо поле, то запрос с юнионом не режет длину строки. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 13:58 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studierenИнтересные факты. о! сколько нам открытий чудных... (с) studierenОбщее количество полей каждого блока запроса в сумме не должно превышать 255! формулировочка ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 13:58 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Guest33авторЕсли в запросе на объединение имеется поле МЕМО, где имеется значение больше 255 символов, то Access вернет только первые 255 символов. Расшифруйте, пожалуйста. По моим наблюдениям, если в 1-й запрос включить мемо поле, то запрос с юнионом не режет длину строки. Прошу прощения, что не уточнил деталь: - если используете UNION ALL, то Access не режит. - а вот если просто UNION, то Access покажет только первые 255 символов! Вот теперь кажется описал полностью! полиномstudierenОбщее количество полей каждого блока запроса в сумме не должно превышать 255! формулировочка Ну хорошо, может быть написано не совсем правильно. Ну мысль я надеюсь Вы правильно поняли? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 14:22 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studierenНу мысль я надеюсь Вы правильно поняли? не с первого раза :) ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 17:20 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Вообще-то про особенность ограничения 255 полей в запросах на объединение решил здесь написать после того, как прочёл топик Too many fields defined. В этом топике есть такой запрос: Код: plaintext
Автор также сообщает, что "в главной таблице 83 поля". Как мы видим в каждом блоке запросов есть дополнительное поле "Part_all", стало быть каждый блок имеет 84 поля. Всего блоков 10, в итоге мы имеем 84*10=840. А это гораздо больше чем 255!!!! Вот именно поэтому и Access ругается " Too many fields defined ". Вывод: в запросах на объединение нежелательно использовать "*", лучше явно указать только необходимые поля! В том топике есть ссылка на интересный сайт, где имеется вот такая информация: Tables: "Too many fields defined" error message (Q) When I try to save a table, I keep getting the error message "Too many fields defined". What\'s causing this to come up? (A) Access keeps an internal count of total number of fields in a table and has a limit of 255 fields per table. Each time you modify a field or add a field, this count increases by 1. When you delete a field, Access does NOT reset this counter. So it\'s possible for you to have less than 255 fields and still get this error message. If your field count is less than 255, just compact the database again which should reset the internal field count counter. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 19:45 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studieren, неплохо было бы вам проштудировать давний топик ФАК: А знаете ли вы, что... и то, чего там не хватает, добавить. В одном месте хранить все. Желательно было бы. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 20:17 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 20:36 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
mds_world, Не знал, что есть топик "А знаете ли Вы ..." :)) И что в результате? Опять закроют мой топик? Если это так, то жаль! :(( ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 20:41 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
8060studieren, относительно количества полей в UNION можно посмотреть в этом и следующем за ним постах. Спасибо за ссылку! Значит я ошибся. Бывает. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 20:45 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studierenmds_world, Не знал, что есть топик "А знаете ли Вы ..." :)) И что в результате? Опять закроют мой топик ? Если это так, то жаль! :(( Вовсе нет! Я, во всяком случае этого делать не собираюсь. Вопрос ведь иначе ставится - в аксе есть много различных особенностей, подмеченных разными авторами. Желающему программировать в этой среде полезно их знать. Но поиск затруднителен. Хотя бы потому, что не знаешь, что искать. А когда все собрано в одном месте удобно. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2011, 20:54 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
mds_world, Есть "золотые топики". Они одни, слово "золотые" встречается крайне редко на форуме. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.02.2011, 02:46 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
А2003 Странную вещЧ я сейчас обнаружил. Допустим есть такой запрос Код: plaintext
Можно его переписать вот так Код: plaintext
Код: plaintext 1.
Продолжил эксперимент и написал вот такой запрос: Код: plaintext 1. 2.
Обычно Access не терпит PARAMETERS во вложенных запросах. А здесь парадокс - пашет как надо! И здесь квадратные скобки никак нельзя заменить на обычные скобки! P.S. Смотрю на всё это и диву дивлюсь: сколько же ещё секреты спрятаны за семью замками. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.02.2011, 11:06 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Просьба тем, у кого есть А2007 или А2010: не могли бы протестировать вот эти запросы? К сожалению у меня в наличии нет таких версий под рукой. Код: plaintext
Код: plaintext 1.
Код: plaintext 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
18.02.2011, 11:19 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Уже достаточно причин для ухода с MDB в ADP ... |
|||
:
Нравится:
Не нравится:
|
|||
18.02.2011, 11:23 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
studierenСтранную вещЧ я сейчас обнаружил. Вот здесь пример "странного" запроса без всяких наворотов (в двух постах ниже эта "странность" обсуждается). ... |
|||
:
Нравится:
Не нравится:
|
|||
18.02.2011, 11:32 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
П-ЛУже достаточно причин для ухода с MDB в ADP У меня пока нет ни одной, кроме личного интереса. А будущий переход на акс2010 разве это позволит сделать? p.s. извиняюсь за оффтопик. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.02.2011, 12:13 |
|
интересные факты / наблюдения / анализ чужих и собственных решений
|
|||
---|---|---|---|
#18+
Если в А2007 написать вот такой запрос в режиме SQL и затем открыть его в режиме таблицы, то запрос работает: Код: plaintext 1. 2.
Но!!! Если сохранить запрос, то Access текст SQL меняет до неузнаваемости! Код: plaintext 1.
Да!!! Дела!!! В А2010 не смог экспериментировать из-за не имения, но подозреваю, что там дела обстоят аналогично. Попробовал экспериментировать с перекрестным запросом в А2007: Код: plaintext 1. 2. 3. 4. 5. 6.
... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2011, 09:46 |
|
|
start [/forum/topic.php?fid=45&msg=37124042&tid=1610226]: |
0ms |
get settings: |
9ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
62ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
55ms |
get tp. blocked users: |
1ms |
others: | 303ms |
total: | 457ms |
0 / 0 |