Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Приветствую! Вот проблемка возникла, навернякак кто-то натыкался на это, но к сожалению в поиске ничего не нашел по данной проблеме. Проблема в следующем: CREATE PROCEDURE DBO.TEST1 AS declare @command nvarchar(1000) SET @command = 'select * from table1 into #xx1' exec( @command ) (или sp_executesql @command) select * from #xx1 GO получаем естественно: -Invalid object name '#xx1'. Оно-то и понятно, курсор создался в другой сессии и там же удалился при ее закрытии А как же тогда создать и использовать этот ЛОКАЛЬНЫЙ курсор через эти процедуры? Понятно что можно через таблицу или глобальный курсор (##), но это не нормальное решение т.к. этот курсор никому не нужен да и геморой появляется с уникальными именами (т.к. одновременно эту процедуру могут запустить несколько юзеров.). Заранее благодарен, Михаил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.07.2001, 08:04 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Ну так ты сначала создай временную таблицу в процедуре а затем в exec ее только заполни Что-то типа следующего CREATE PROCEDURE DBO.TEST1 AS declare @command nvarchar(1000) create table #xx1 (...) SET @command = 'insert into #xx1 (...) select * from table1' exec( @command ) (или sp_executesql @command) select * from #xx1 GO ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.07.2001, 08:36 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Это единственный выход? Не хотелось бы переписывать 30 полей с типами .... через некоторое время придется что-то дополнительное добавлять в результат и в нескольких местах менять ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.07.2001, 09:52 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Так можно не писать create table... select * into #xx1 from table1 where 1 = 0 Будет создана пустая таблица, а столбцы скопируются из table1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.07.2001, 13:12 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.07.2001, 13:35 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
>Это единственный выход? >Не хотелось бы переписывать 30 полей с типами .... >через некоторое время придется что-то дополнительное добавлять в результат и в нескольких местах менять ? Смирись и безропотно пиши. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2001, 06:45 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Ну вот опять ... Я конечно понимаю что это легче всего, но это не выход, а как тогда решить такую задачу: - Есть БД, в ней есть несколько таблиц, в которых поля кроме, скажем, 2-х могут отличаться и названием и кол-вом, а эти известные 2 поля неизменны. В ХП передеатся имя таблице. CREATE PROCEDURE DBO.TEST1 ( @table1 nvarchar(20) ) AS declare @command nvarchar(1000) SET @command = 'select * from '+table1+' where field1=X and field2=Y into #xx1' exec( @command ) select * from #xx1 GO Меня не интересует как на клиенте это будет обрабатываться, это его проблемы, но он хочет чтобы так было. Как видим я не могу через запятую перечислить поля. Как быть в таком случае? Неужели через глобальные курсоры и поиметь геморой с уникальными именами или весь остальной код ХП тоже запихивать в строку а затем выполнять. Примерно так: CREATE PROCEDURE DBO.TEST1 ( @table1 nvarchar(20) ) AS declare @command nvarchar(1000) SET @command = 'select * from '+table1+' where field1=X and field2=Y into #xx1' SET @command=@command+ 'select * from #xx1' exec( @command ) GO И есть еще несколько смежных вопросов: 1. Чем отличается сессия тела ХП от сессии, создаваемой при выполнении exec(...). Почем я в теле ХП не могу написАть: USE database1 select * from table1 а через Exec("USE database1 select * from table1 ") все проходит на ура ????? 2. Где можно прочитать нормальную литературу по MSSQL 7.0-2000 желательно в электронном виде (или порекомендуйте бумажную книгу/книги) кроме BOL'a ... С уважением, Михаил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2001, 07:30 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Вот так и встречаются то там, то сям собратья, желающие надстроить над обычным SQL-сервером свой собственный . А ведь в MS над этим не задумывались. Точнее, задумывались, но не сильно. Точнее, сильнее чем многие другие (в IB5, в частности, даже динамического SQL нет), но опять же не достаточно сильно... А тем временем в Oracle 9i уже наследование классов... Припоминаете разговор-то про объекто-ориентированный Transact-SQL? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2001, 16:06 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
А причем ООП. У меня нормальное желание написать ряд универсальных процедур для того, что бы потом "долгими зимними вечерами" не изменять один и тот же кусок в 10-20 ХП, т.к. вероятность ошибки/опечатки возрастает в геометрической! прогрессии (а цена ошибки очень высока). И не какой это не ООП, а в лучшем случае "процедурный подход". Может я чего-то не понимаю в идеологии? так подскажите где об этом можно прочитать, то что я читал по MSSQL не противоречит моим взглядам (по моему мнению). У меня это первый проект с использованием MSSQL и я пытаюсь просто разобраться что можно, а что нельзя, как можно и как нельзя и т.д. А в ответ получаю - "А чего это ты собственно хочешь?". А хочу я собственно не много - чтоб подсказали, указали в чем я не прав, поделились опытом/информацией (ведь именно в этом и есть основная цель этого форума, или я не прав?). А ответы "Так делать нельзя" и им подобные я не понимаю, потому что в них нет объяснения почему так нельзя делать и как делать можно. Сорри, что-то меня уже заносить начало. P.S. Прошу в этих словах не искать ничего личного, я никого не хотел обидеть. Кстати, тема остается открытой, да и пояснения по дополнительным вопросам хотелось бы услышать, или все рассматриваю MSSQL как "черный ящик" и никто не разбирался почему это так? С уважением, Михаил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.08.2001, 10:24 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
2 N_Michael Миша, Вы извините, но если Вы не напишите "а чего это Вы собственно хотите" врядли кто Вам сможет помочь. Моё субъективное мнение - если Вы начиная работать с SQL хотите передавать таблицу как параметр, то значит у Вас неправильное понимание того, как надо писать("идеологии" по-Вашему). Мне например такие мысли в голову не приходят. Вот Вы спрашиваете "а как вот это сделать?", Вам отвечают что типа вообще то так делать и не надо. Может действительно можно придумать что-то более другое? Чё Вы так упёрлись? С приветом Сергей P.S. Прошу в этих словах не искать ничего личного... P.P.S. Кстати курсоры и временные таблицы - совсем разные вещи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.08.2001, 11:08 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Уважаемый N_Michael! Я таким же образом пытался облегчить свою будущую работу по правке хранимых процедур, НО .... со временем вылезают другие проблемы (для меня конечно) - незаметно универсальные процедуры разрастаются до таких размеров, что теряют свою читабельность и легкость правки(попробуй быстро ориентироваться в процедуре с 1000 строками). Получается это, потому что всегда кажется, что добавить в существующую процедуру еще один маааленький кусочек плёвое дело, неважно что он немного отличается по своему логическому содержанию("давай добавим еще один входной параметер, который будет определять, что собственно нужно делать в универсальной процедуре и все будет путём !"). Это же может сказаться на более "старых" порцедурах, использующих данную процедуру. Вы вдруг с удивлением обнаружите, что замечательно работавшая до этого процедура какого-нибудь отчета стала неоправдано долго выполняться. Свяжите ли вы это событие сразу же с последними исправлениями в универсальной процедуре, тем более, что эти изменения относились совершенно к другой выборке ? - придется раздавать пользователям прямые права на таблицы и представления базы данных, т.к. exec-у плевать на права владельца универсальной процедуры. И чем "универсальнее" становиться универсальная процедура, тем большие права приобретают пользователи. Конечно, вроде ничего страшного на первый взгляд тут нет(вроде как все работают с базой через вами же составленное клиентское предложение), но свой опыт учит, что если не хочешь, чтобы пользователь что-либо сделал без "разрешения", то убери все возможные(даже теоритически маловероятные) пути совершения таких действий. Короче, я вернулся к такой схеме: одна выборка(отчет) - одна процедура с явно прописанным SELECT-ом (или что там нужно). Т.е. никаких exec-ов, которые влияют на выходной набор. Использую, конечно, в одной процедуре вариации одного SELECT-а, но, как правило, на уровне выбора по каким полям группировать и/или какие поля показывать/не показывать. Обычно это делаю через временную таблицу. Конечно, в SQL2000 есть функции, что упрощает программирование , но не всегда убыстряет выполнение. Резюме. Мне кажется не надо ставить универсальность программного кода как главную цель для базы данных. Главные цели все-таки - скорость и надежность (под эти я понимаю и невозможность осуществления пользователем каких-либо действий через другие средства доступа к базе данных). Вот собственно в кратце мое мнение ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.08.2001, 11:41 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
2 N_Michael В описанной постановке задачи ZAMM и MessMaker правы. У меня целый класс задач решается с применением временных таблиц, созданных заранее (до начала транзакции, хотя и во время ее выполнения не возбраняется). Средства (читай - ХП) на все случаи жизни наверное не бывает. А если взглянуть на подход к решению задачи несколько иначе. А именно: передавать в качестве параметра не таблицу (или совокупность таблиц) а просто курсор (в общем-то всегда разный и отражающий нюансы логики) по какому-то набору (чуешь, универсальность где-то близко?). Для примера: CREATE PROCEDURE DBO.V_SPTGM_GET_DEAL_11111111 @BRANCH VARCHAR(2) @ONE_DEALNO CHAR(10) = '', @P_CURSOR CURSOR VARYING OUTPUT AS IF LEN(@ONE_DEALNO) > 0 SET @P_CURSOR = CURSOR FORWARD_ONLY STATIC FOR SELECT dbo.DLDT.BR AS BR, dbo.DLDT.DEALNO AS DEALNO, .................................. FROM dbo.DLDT, .................................. WHERE (dbo.DLDT.BR = dbo.DLDT_TGM.BR ) AND (dbo.DLDT.DEALNO = dbo.DLDT_TGM.DEALNO ) AND .................................................. ORDER BY 1, 2, 3 ELSE SET @P_CURSOR = CURSOR FORWARD_ONLY STATIC FOR SELECT dbo.DLDT.BR AS BR, dbo.DLDT.DEALNO AS DEALNO, ............................................................. FROM dbo.DLDT, ......................... (другой список таблиц) WHERE (dbo.DLDT.BR = dbo.DLDT_TGM.BR ) .................... (другие условия) ORDER BY 1, 2, 3 OPEN @P_CURSOR ТАКИХ ПРОЦЕДУР У МЕНЯ МНОГО, НО ВСЕ ОНИ "ПРИБИРАЮТСЯ К РУКАМ" ТОЛЬКО В ОДНОЙ (УНИВЕРСАЛЬНОЙ!!!!!!!!) ----------------------------------------------------------------------------------------------------- CREATE PROCEDURE DBO.V_SPTGM_IMPORT_DEALS_BY_TGM_PROD @BRANCH VARCHAR (56) @FIND_DEALNO CHAR(10) = NULL AS DECLARE @L_BR CHAR(2), /* локальная переменная */ @L_DEALNO CHAR(10), /* локальная переменная */ @CURSOR_BY_PROD CURSOR /* локальный курсор */ /* но результирующий набор имеет одинаковый формат */ /* для каждого случая открываем свой курсор */ IF @L_PROD_NAME = '111' EXEC DBO.V_SPTGM_GET_DEAL_11111 @BRANCH = @BRANCH, @ONE_DEALNO = @FIND_DEALNO, @P_CURSOR = @CURSOR_BY_PROD OUTPUT ELSE IF @L_PROD_NAME = '222' EXEC DBO.V_SPTGM_GET_DEAL_22222 @BRANCH = @BRANCH, @ONE_DEALNO = @FIND_DEALNO, @P_CURSOR = @CURSOR_BY_PROD OUTPUT ELSE IF @L_PROD_NAME = '333' EXEC DBO.V_SPTGM_GET_DEAL_33333 @BRANCH = @BRANCH, @ONE_DEALNO = @FIND_DEALNO, @P_CURSOR = @CURSOR_BY_PROD OUTPUT ELSE IF @L_PROD_NAME = '444' EXEC DBO.V_SPTGM_GET_DEAL_44444 @BRANCH = @BRANCH, @ONE_DEALNO = @FIND_DEALNO, @P_CURSOR = @CURSOR_BY_PROD OUTPUT ELSE IF @L_PROD_NAME = '555' EXEC DBO.V_SPTGM_GET_DEAL_5555 @BRANCH = @BRANCH, @ONE_DEALNO = @FIND_DEALNO, @P_CURSOR = @CURSOR_BY_PROD OUTPUT ELSE ............................................................................ FETCH NEXT FROM @CURSOR_BY_PROD .............................................. WHILE (@@FETCH_STATUS = 0 ) BEGIN -- НЕОБХОДИМЫЕ СТАНДАРТНЫЕ ОПЕРАЦИИ FETCH NEXT FROM @CURSOR_BY_PROD ............ END CLOSE @CURSOR_BY_PROD DEALLOCATE @CURSOR_BY_PROD ............................ Достоинства: 1. Громоздкость конечно-же налицо, но ее гораздо меньше 2. ВСЕ ВЫПОНЯЕТСЯ В РАМКАХ ОДНОГО СЕАНСА, который запросто управляем 3. Процедура (точнее, совокупность процедур) масштабируема - всегда можно добавить в процесс ситуацию, не предусмотренную заранее (что бывает в моей практике нередко) БЕЗ МНОГОЧИСЛЕННЫХ ИЗМЕНЕНИЙ в вызывающих и вызываемых процедурах. Желаю удачи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.08.2001, 11:44 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Большо спасибо господа за ответы. Может быть действительно я чего-то еще не понял в "идеологии", ну чтож будем "грызть гранит" всеми челюстями. 2SergSuper: Как что я хочу, я же написал: 1. Создать временную таблицу структуры, идентичной передаваемой как параметр в ХП. 2. Понять чем отличается следующее Код1: USE database1 select * from table1 Код2: Exec("USE database1 select * from table1 ") Почему в первом случае не работае USE, а во втором все работает нормально. 3. Прошу порекомендовать хорошую литературу по MSSQL 7.0/2000, желательно в електронном виде, но и бумажный вариант тоже ничего. 2Glory: Я с Вами полностью согласен, но очень сложно так сразу мне заставить себя продублироваь одно и тоже в несколько БД, т.к. я почти физически ощущая геморой который я поименю когда они начнут чуть-чуть различаться и обновлять придется все в отдельности ... а об отладке я вообще не говорю ... многие из нас будут отлаживать по полной программе 3 процедуру с идентичными исправлениями, когда в предыдущих двух все прошло ОК, а в этой казалось бы такие же изменения? Ну честно, положа руку на сердце? Вот тут-то и могут появиться ошибки, которые потом могу слишком дорого стоить .... 2Vladimir Gomounov: В это что-то есть Это решение очень близко к решению моей проблемы, но в литературе написано про эти белые и пушистые курсоры, про то какие они хорошие и в конце обязательно приписка большими буквами, что использовать их стоит очень осторожно и если есть возможность, то вообще обходиться без них, но причины этого не указано. Не могли бы гуру пояснить этот момент! С уважением, Михаил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.08.2001, 08:55 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
По поводу курсоров Я тут как то проверял одно странное утверждение, что курсор будет работать быстрее чем временная таблица, если делать из нее выборки в цикле по одной записи. Чтобы было заметнее различие я сделал табличку с 50000 записями. Сейчас точные результаты не помню, но количество записей в таблице пришлось уменьшить, потому что цикл по временной таблице отрабатывал, а вот с курсором преблемка вышла, после ожидания так около 5 мин я получил сообщение о том что ресурсы у меня того, в ауте. так что кому как нравится, а лично я против курсоров однозначно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.08.2001, 10:20 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Да забыл написать - у меня PIII 550 c 512 Mb RAMa ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.08.2001, 10:21 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
2 N_Michael Что касается вопросов ко мне 1.Дык вот я и спрашиваю - для чего Вам "создавать временную таблицу структуры, идентичной передаваемой как параметр в ХП"? Допустим кто-то бы спрашивал такой вопрос: "- а как мне узнать номер записи в таблице по её ключу?". Получив ответ он бы стал спрашивать: "- а как мне изменить запись в таблице зная её номер?" Не исключаю, что и Вашу проблемму можно решать иными методами. Ну создадите Вы таблицу идентичной структуры, ну и что? Вы же не знаете какие поля в этой таблице есть(кроме двух общих). Появятся новые вопросы? 2. Процедура принадлежит базе и работает в её контексте. Исходя из этого контекста создаётся план её выполнения. План выполнения - это откомпилированная во внутренние коды SQL-сервера процедура. Наверное эти коды не позволяют в плане менять текущую базу. Если же Вы пишите через Exec(), то эта строка не компилируется во время компиляции процедуры, а скомпилируется только при её выполнении и сработает как обычный запрос. То что я выше написал - это только мои размышления, факт же только один - менять текущую базу в процедуре нельзя. Смиритесь с этим. 3. Насчет литературы посоветовать ничего не могу, я сам только BOL читаю. С приветом Сергей PS. А курсорами пользоваться действительно не надо. Без них получается и короче, и понятней и быстрей. Бывают конечно исключения, но очень редко. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.08.2001, 10:52 |
|
||
|
sp_executesql (exec) и локальный курсор
|
|||
|---|---|---|---|
|
#18+
Ну, если сильно захотеть создать таблицу, по своей структуре идентичную той, что передается в параметре в виде строки, то можно собрать строчку скрипта, создающего такую таблицу на основе данных sysobjects, INFORMATIONAL_SCHEMA.COLUMNS, и др. метаданных. Для упрощения работы, сборку этого скрипта оформить в виде хранимки. Подобный подход я использую для генерации хранимых процедур разных типов на основе имени "главной" таблицы или представления. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.08.2001, 14:36 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32010796&tid=1825983]: |
0ms |
get settings: |
7ms |
get forum list: |
20ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
31ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
61ms |
get tp. blocked users: |
1ms |
| others: | 238ms |
| total: | 377ms |

| 0 / 0 |
