Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
Дано. Запрос к серверу с изменяемыми параметрами. Найти все счета этого клиента. Найти все счета этого клиента и период. Найти все счета за период. Найти все счета этого клиента и от этой фирмы . Найти все счета этого клиента и от этой фирмы и за период. Найти все счета этой фирмы . И т.д. т.е. параметров n. Сделано так. В процедуру передаются все параметры если параметр не учитывается то 0 В прцедуре генерится на лету SQL строка Declare @sqlstr varchar(2000) Select @sqlstr = "Select ... From .... Where " IF @Param1 <> 0 then Select @sqlstr = @sqlstr + " t1.Param1 = " + convert (varchar(10),@Param1) .... и EXEC (@sqlstr). Есть ли другие варианты??? А вопрос такой: SQL делает предоптимизацию для процедур. И вообщем статистику хранит и т.д. А тут получается без этой статистики и предопримизации и т.п. Moth ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2001, 00:09 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
Почему нельзя использовать разные процедуры? Принцип "разделяй и властвуй" еще отменили? Насчет статистики. Ее наличие/отсутствие/свойства зависят от других вещей. См. например, sp_dboptinon (auto create statistic, auto update statistic). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2001, 03:44 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
To MadDog: А если параметров более 4 от сколько это получится "разных" процедур. Я сейчас Статистику не вспомню, но количество переборов из 5 параметров... вообщем много будет. Такой головняк "влавствуй" точно не назовешь. Moth. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2001, 04:14 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
2Moth Я лично вначале думал так же, как и Вы. НО ... прошло время, накопился опыт и могу заявить: динамичексий запрос сам по себе вещь хорошая и нужная, но - выполняется он в контексте пользователя, а не владельца процедуры, формирующей этот запрос. Поэтому придется раздавать права пользователям(напрямую или через роли не суть важно) на таблицы/представления, хотя бы на SELECT, а значит у пользователя появляется возможность выбирать из них данные(хоть через тот же Excel) не по-вашему сценарию. Я думаю, что в любой фирме может найтись "умелец", который способен на это. Вы скажите - ну так раздадим всем нужные права, я отвечу - ну да и будем тратить время на мэнеджирование каждой таблицы/представления (конечно, есть еще application role, но их использование не всегда возможно, например при доступе через http, asp) - если вдруг понадобиться разделить права доступа к отчетам/поискам для разных пользователей, то придется создать две(три, четыре, ...) процедуры, которые будут выполнять в принципе одно и тоже. Но универсальность (к которой вы, я так понял, стремитесь) будет потеряна. (Можно опять же проверять пользователя внутри процедуры, но придется создать дополнительные таблицы, где прописаны права того или иного пользователя) В итоге все равно вы будете иметь несколько(может и много) процедур плюс дополнительную работу по мэнеджированию прав пользователей на другие объекты. Универсализация вещь хорошая, но не панацея ЗЫ Из личного опыта - у меня на данный момент около 150(и будет больше) различных отчетов и поисков и все они офромлены как отдельные процедуры. Главное - выделить действительно часто повторяющиеся части запросов и постараться как-то унифицировать их, помня об особенностях MS SQL. Например, любые даты в MS SQL находятся в диапазоне 01.01.1753 - 31.12.9999 и эти как раз эти значения могут принимать по умолчанию входные параметры, задающие в вашей процедуре период. В SQL2000 появилиь функции, которые так же облегчают написание общих частей запроса, но пользоваться ими нужно осторожно(можно сильно потерять в производительности) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2001, 08:03 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
2 Clory: Согласен 2Moth: Я ведь не предлагаю Вам создавать только процедуры состоящие из одного select-а. Пусть они будут несколько сложнее. Если имеются однотипные выборки, их можно оформлять в виде view или процедур "нижнего уровня" (или функции в sql2k). А процедуры "верхнего уровня" пусть используют весь этот фундамент. В моем приложении, например, в пяти базах около 300 view, 900 процедур и функций. Причем большая часть из них - служебные, "нижнего уровня". Еще раз соглашусь с Glory - все зависит от требований приложения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2001, 10:10 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
Уточнение. Я не хочу постороить всего одну прроцедуру и в ней леписть все запросы. Понятно что отчет по продажам и тчет по закупкам /*например*/ это разные процедуры со всеми вытекающими последствиями. Берем один случай. /*А не все*/ Но вот необходимо построить отчет но параметры для него разные. То учитывать клиента, то учитывать даты, то оплаты и т.д. И вот теперь мне предлагаете новые процедурки лепить. А если в отчет поле добать. То по всем процедурам и там добавлять... ух как весело. У меня SQL 7.0 А процедура нижнего уровня это хоть где посмотреть??? Антон. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2001, 05:42 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
Так и у меня изначально было около 10 процедур по основным типам отчетов и я считал, что этого мне хватит за глаза. Я хотел акцентировать на том, что только использованием динамических запросов не создать систему отчетов(назовем это так) - нужно создавать набор процедур и представлений, комбинируя которые в запросе, можно покрыть все(ну или очень многие) потребности пользователей в отчетах. Попробую показать вам более наглядно, как можно уйти от динамических запросов(толко ради бога воспримите это как общую идею) 1. Даты. Про ограничения содержимого типа datetime я уже говорил выше, но кроме этого существуют чисто логические ограничения. Например, вряд ли у вас есть счета за 1896 год и за 1955 год наверное нет и даже за 1990 год вряд ли(хотя кто знает ). Соответственно не должно быть пока счетов за 2005 год(не будем пока говорить об ошибках ввода). Т.е. можно в процедуре задать для входных параметров, определяющих период, задать ограничения CREATE PROCEDURE myproc @period_begin datetime = '19900101 00:00:00', @period_end datetime = '99991231 23:59:59' - это на всякий случай AS ..... и вот в любом случае имеем нединамический запрос, который будет работать при любых входных параметрах SELECT * FROM mytable WHERE mydate BETWEEN @period_begin AND @period_end Опять же для удобства можно определить действительно глобальные значения в системе и хранить их как предложено, например, здесь http://www.swynk.com/friends/green/uservar.asp 2. Клиенты 2.1 Если клиент идентифицируется каким-либо символьным полем - именем, кодом, ИНН(кажется есть что-то такое?) - то можно осуществлять выборку использую не прямое сравнение а LIKE А именно CREATE PROCEDURE myproc @period_begin datetime = '19900101 00:00:00', @period_end datetime = '99991231 23:59:59', @client_code varchar(15) = '' AS SET @client_code = @client_code + '%' SELECT * FROM clients WHERE client_code LIKE @client_code SELECT * FROM mytable a INNER JOIN clients b ON b.client_code = a.client_code AND b.client_code LIKE @client_code WHERE a.mydate BETWEEN @period_begin AND @period_end Т.е. с помощью входных параметров и одного запроса можно получить 4 различных результата. 2.1 Если клиент идентифицируется каким-либо полем типа int, то придется усложнить код CREATE PROCEDURE myproc @period_begin datetime = '19900101 00:00:00', @period_end datetime = '99991231 23:59:59', @client_code int = -1 AS SELECT * FROM clients WHERE client_code = CASE @client_code WHEN -1 THEN client_code ELSE @client_code END SELECT * FROM mytable a INNER JOIN clients b ON b.client_code = a.client_code AND b.client_code = CASE @client_code WHEN -1 THEN b.client_code ELSE @client_code END WHERE a.mydate BETWEEN @period_begin AND @period_end ну и так далее. Немножко знаний об определения условий в теле запроса можно почерпнуть вот здесь http://www.osp.ru/win2000/sql/2001/06/075.htm (правда там только насчет ORDER, но все-таки) Теперь об уровнях процедур и полях вывода. Деление на уровни - это логическое деление, т.е. нужно просто определиться какие процедуры не будут напрямую вызываться конечным пользователем, а только другими процедурами. Вот у вас и получиться "нижний" уровень процедур. Поля вывода - т.к. в запросах равно могут участвовать и таблицы и представления, то если у нас имеется представление myview вроде SELECT a.conto_nr, a.mydate, a.conto_summa, b.client_name, b.cleint_code FROM mytable a INNER JOIN clients b ON b.client_code = a.client_code то процедура из моего примера может быть преобразована так CREATE PROCEDURE myproc @period_begin datetime = '19900101 00:00:00', @period_end datetime = '99991231 23:59:59', @client_code int = -1 AS SELECT * FROM myview a WHERE a.mydate BETWEEN @period_begin AND @period_end AND a.client_code = CASE @client_code WHEN -1 THEN a.client_code ELSE @client_code END т.е. меняя количество выбираемых полей в представлении, можно без изменения текста процедуры(!процедур!) изменить количество информации, получаемое конечным пользователем. И еще - не нужно боятся использовать временные таблицы, для хранения промежуточных результатов или для занесения туда конечных данных, которые будут отосланы клиенту. Во-первых, в сложных запросах планировщик может составить неоптимальный план выполнения, что пагубно скажется на производительности. Во-вторых, для сложных запросов сервер и сам будет использовать временные таблицы. Резюме. У динамического запроса, если брать его как один запрос, есть одно неоспоримое преимущество - он будет выполняться быстрее(или не медленне) универсального явного запроса по той причине, что содержит только те условия поверки, которым действительно задал пользователь. Понятно что запрос exec('SELECT * FROM clients') сработает быстрее, чем SET @client_code = '%' SELECT * FROM clients WHERE client_code LIKE @client_code НО IMHO в любой _системе_ нужно уделять внимание и дальнейшей поддержкеи развитию. Открытость, масштабирумость, простота(читай - дешивизна) администрирования хоть и высокие слова(может быть и набившие уже оскомину), но все-таки к ним надо хотя бы стремиться. Поэтому повторюсь - только использование динамических запросов, а равно как предложенных здесь идей есть однобокое, а следовательно неправильное, решение. Комбинировать нужно, комбинировать PS Надеюсь, что не очень утомил Вас ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2001, 11:08 |
|
||
|
"Динамические Запросы"
|
|||
|---|---|---|---|
|
#18+
Thanks Glory!!! Если будешь во Владивостоке, то скинь на пагер 51-22-22 Мобил Телеком. абонент 423201470. С меня причитается. INNER JOIN clients b ON b.client_code = a.client_code AND b.client_code = CASE @client_code WHEN -1 THEN b.client_code ELSE @client_code END Вот это то что нужно. Процедура получается еще проще и читается вообще легко. Moth. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2001, 01:34 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32019535&tid=1824517]: |
0ms |
get settings: |
10ms |
get forum list: |
20ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
46ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
| others: | 249ms |
| total: | 400ms |

| 0 / 0 |
