Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / sp_executesql (exec) и локальный курсор / 17 сообщений из 17, страница 1 из 1
30.07.2001, 08:04
    #32010642
N_Michael
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Приветствую!

Вот проблемка возникла, навернякак кто-то натыкался на это, но к сожалению в поиске ничего не нашел по данной проблеме.

Проблема в следующем:

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'.

Оно-то и понятно, курсор создался в другой сессии и там же удалился при ее закрытии

А как же тогда создать и использовать этот ЛОКАЛЬНЫЙ курсор через эти процедуры?

Понятно что можно через таблицу или глобальный курсор (##), но это не нормальное решение т.к. этот курсор никому не нужен да и геморой появляется с уникальными именами (т.к. одновременно эту процедуру могут запустить несколько юзеров.).

Заранее благодарен,
Михаил.
...
Рейтинг: 0 / 0
30.07.2001, 08:36
    #32010647
zamm
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Ну так ты сначала создай временную таблицу в процедуре а затем в 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
...
Рейтинг: 0 / 0
30.07.2001, 09:52
    #32010659
N_Michael
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Это единственный выход?
Не хотелось бы переписывать 30 полей с типами .... через некоторое время придется что-то дополнительное добавлять в результат и в нескольких местах менять ?
...
Рейтинг: 0 / 0
30.07.2001, 13:12
    #32010670
MessMaker
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Так можно не писать create table...

select *
into #xx1
from table1
where 1 = 0

Будет создана пустая таблица, а столбцы скопируются из table1
...
Рейтинг: 0 / 0
30.07.2001, 13:35
    #32010672
N_Michael
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
так тоже нельзя т.к. имя таблицы передается как параметр
...
Рейтинг: 0 / 0
31.07.2001, 06:45
    #32010725
zamm
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
>Это единственный выход?
>Не хотелось бы переписывать 30 полей с типами ....
>через некоторое время придется что-то дополнительное добавлять в результат и в нескольких местах менять ?

Смирись и безропотно пиши.
...
Рейтинг: 0 / 0
31.07.2001, 07:30
    #32010733
N_Michael
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Ну вот опять ...
Я конечно понимаю что это легче всего, но это не выход, а как тогда решить такую задачу:

- Есть БД, в ней есть несколько таблиц, в которых поля кроме, скажем, 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 ...

С уважением,
Михаил.
...
Рейтинг: 0 / 0
31.07.2001, 16:06
    #32010796
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Вот так и встречаются то там, то сям собратья, желающие надстроить над обычным SQL-сервером свой собственный . А ведь в MS над этим не задумывались. Точнее, задумывались, но не сильно. Точнее, сильнее чем многие другие (в IB5, в частности, даже динамического SQL нет), но опять же не достаточно сильно... А тем временем в Oracle 9i уже наследование классов... Припоминаете разговор-то про объекто-ориентированный Transact-SQL?
...
Рейтинг: 0 / 0
01.08.2001, 10:24
    #32010829
N_Michael
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
А причем ООП. У меня нормальное желание написать ряд универсальных процедур для того, что бы потом "долгими зимними вечерами" не изменять один и тот же кусок в 10-20 ХП, т.к. вероятность ошибки/опечатки возрастает в геометрической! прогрессии (а цена ошибки очень высока). И не какой это не ООП, а в лучшем случае "процедурный подход". Может я чего-то не понимаю в идеологии? так подскажите где об этом можно прочитать, то что я читал по MSSQL не противоречит моим взглядам (по моему мнению). У меня это первый проект с использованием MSSQL и я пытаюсь просто разобраться что можно, а что нельзя, как можно и как нельзя и т.д. А в ответ получаю - "А чего это ты собственно хочешь?". А хочу я собственно не много - чтоб подсказали, указали в чем я не прав, поделились опытом/информацией (ведь именно в этом и есть основная цель этого форума, или я не прав?). А ответы "Так делать нельзя" и им подобные я не понимаю, потому что в них нет объяснения почему так нельзя делать и как делать можно.
Сорри, что-то меня уже заносить начало.
P.S. Прошу в этих словах не искать ничего личного, я никого не хотел обидеть.
Кстати, тема остается открытой, да и пояснения по дополнительным вопросам хотелось бы услышать, или все рассматриваю MSSQL как "черный ящик" и никто не разбирался почему это так?

С уважением,
Михаил.
...
Рейтинг: 0 / 0
01.08.2001, 11:08
    #32010842
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
2 N_Michael

Миша, Вы извините, но если Вы не напишите "а чего это Вы собственно хотите" врядли кто Вам сможет помочь.
Моё субъективное мнение - если Вы начиная работать с SQL хотите передавать таблицу как параметр, то значит у Вас неправильное понимание того, как надо писать("идеологии" по-Вашему). Мне например такие мысли в голову не приходят.
Вот Вы спрашиваете "а как вот это сделать?", Вам отвечают что типа вообще то так делать и не надо. Может действительно можно придумать что-то более другое? Чё Вы так упёрлись?


С приветом Сергей

P.S. Прошу в этих словах не искать ничего личного...
P.P.S. Кстати курсоры и временные таблицы - совсем разные вещи.
...
Рейтинг: 0 / 0
01.08.2001, 11:41
    #32010856
Glory
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Уважаемый N_Michael!
Я таким же образом пытался облегчить свою будущую работу по правке хранимых процедур, НО ....
со временем вылезают другие проблемы (для меня конечно)

- незаметно универсальные процедуры разрастаются до таких размеров, что теряют свою читабельность и легкость правки(попробуй быстро ориентироваться в процедуре с 1000 строками). Получается это, потому что всегда кажется, что добавить в существующую процедуру еще один маааленький кусочек плёвое дело, неважно что он немного отличается по своему логическому содержанию("давай добавим еще один входной параметер, который будет определять, что собственно нужно делать в универсальной процедуре и все будет путём !"). Это же может сказаться на более "старых" порцедурах, использующих данную процедуру. Вы вдруг с удивлением обнаружите, что замечательно работавшая до этого процедура какого-нибудь отчета стала неоправдано долго выполняться. Свяжите ли вы это событие сразу же с последними исправлениями в универсальной процедуре, тем более, что эти изменения относились совершенно к другой выборке ?

- придется раздавать пользователям прямые права на таблицы и представления базы данных, т.к. exec-у плевать на права владельца универсальной процедуры. И чем "универсальнее" становиться универсальная процедура, тем большие права приобретают пользователи. Конечно, вроде ничего страшного на первый взгляд тут нет(вроде как все работают с базой через вами же составленное клиентское предложение), но свой опыт учит, что если не хочешь, чтобы пользователь что-либо сделал без "разрешения", то убери все возможные(даже теоритически маловероятные) пути совершения таких действий.

Короче, я вернулся к такой схеме: одна выборка(отчет) - одна процедура с явно прописанным SELECT-ом (или что там нужно). Т.е. никаких exec-ов, которые влияют на выходной набор. Использую, конечно, в одной процедуре вариации одного SELECT-а, но, как правило, на уровне выбора по каким полям группировать и/или какие поля показывать/не показывать. Обычно это делаю через временную таблицу.

Конечно, в SQL2000 есть функции, что упрощает программирование , но не всегда убыстряет выполнение.

Резюме. Мне кажется не надо ставить универсальность программного кода как главную цель для базы данных. Главные цели все-таки - скорость и надежность (под эти я понимаю и невозможность осуществления пользователем каких-либо действий через другие средства доступа к базе данных).

Вот собственно в кратце мое мнение
...
Рейтинг: 0 / 0
01.08.2001, 11:44
    #32010857
Vladimir Gomounov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
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. Процедура (точнее, совокупность процедур) масштабируема - всегда можно добавить в процесс ситуацию, не предусмотренную заранее (что бывает в моей практике нередко) БЕЗ МНОГОЧИСЛЕННЫХ ИЗМЕНЕНИЙ в вызывающих и вызываемых процедурах.


Желаю удачи.
...
Рейтинг: 0 / 0
03.08.2001, 08:55
    #32011031
N_Michael
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Большо спасибо господа за ответы.
Может быть действительно я чего-то еще не понял в "идеологии", ну чтож будем "грызть гранит" всеми челюстями.
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:

В это что-то есть

Это решение очень близко к решению моей проблемы, но в литературе написано про эти белые и пушистые курсоры, про то какие они хорошие и в конце обязательно приписка большими буквами, что использовать их стоит очень осторожно и если есть возможность, то вообще обходиться без них, но причины этого не указано. Не могли бы гуру пояснить этот момент!

С уважением,
Михаил.
...
Рейтинг: 0 / 0
03.08.2001, 10:20
    #32011039
Genady
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
По поводу курсоров

Я тут как то проверял одно странное утверждение, что курсор будет работать быстрее чем временная таблица, если делать из нее выборки в цикле по одной записи. Чтобы было заметнее различие я сделал табличку с 50000 записями. Сейчас точные результаты не помню, но количество записей в таблице пришлось уменьшить, потому что цикл по временной таблице отрабатывал, а вот с курсором преблемка вышла, после ожидания так около 5 мин я получил сообщение о том что ресурсы у меня того, в ауте.
так что кому как нравится, а лично я против курсоров однозначно.
...
Рейтинг: 0 / 0
03.08.2001, 10:21
    #32011040
Genady
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Да забыл написать - у меня PIII 550 c 512 Mb RAMa
...
Рейтинг: 0 / 0
03.08.2001, 10:52
    #32011046
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
2 N_Michael
Что касается вопросов ко мне

1.Дык вот я и спрашиваю - для чего Вам "создавать временную таблицу структуры, идентичной передаваемой как параметр в ХП"?
Допустим кто-то бы спрашивал такой вопрос: "- а как мне узнать номер записи в таблице по её ключу?". Получив ответ он бы стал спрашивать: "- а как мне изменить запись в таблице зная её номер?"

Не исключаю, что и Вашу проблемму можно решать иными методами. Ну создадите Вы таблицу идентичной структуры, ну и что? Вы же не знаете какие поля в этой таблице есть(кроме двух общих). Появятся новые вопросы?


2. Процедура принадлежит базе и работает в её контексте. Исходя из этого контекста создаётся план её выполнения. План выполнения - это откомпилированная во внутренние коды SQL-сервера процедура. Наверное эти коды не позволяют в плане менять текущую базу.
Если же Вы пишите через Exec(), то эта строка не компилируется во время компиляции процедуры, а скомпилируется только при её выполнении и сработает как обычный запрос.

То что я выше написал - это только мои размышления, факт же только один - менять текущую базу в процедуре нельзя. Смиритесь с этим.

3. Насчет литературы посоветовать ничего не могу, я сам только BOL читаю.

С приветом Сергей

PS. А курсорами пользоваться действительно не надо. Без них получается и короче, и понятней и быстрей. Бывают конечно исключения, но очень редко.
...
Рейтинг: 0 / 0
03.08.2001, 14:36
    #32011069
George
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
sp_executesql (exec) и локальный курсор
Ну, если сильно захотеть создать таблицу, по своей структуре идентичную той, что передается в параметре в виде строки, то можно собрать строчку скрипта, создающего такую таблицу на основе данных sysobjects, INFORMATIONAL_SCHEMA.COLUMNS, и др. метаданных.

Для упрощения работы, сборку этого скрипта оформить в виде хранимки.

Подобный подход я использую для генерации хранимых процедур разных типов на основе имени "главной" таблицы или представления.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / sp_executesql (exec) и локальный курсор / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]