Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Конструкция declare @table='table' create table @table (m int)

5.4K
23 октября 2009 года
cursor
114 / / 05.01.2008
Здравствуйте.
Появилась необходимость написать хранимую процедуру для MSSQL.
Мне нужно выполнить такой запрос:
 
Код:
CREATE PROCEDURE test
@table varchar(20)
AS

select * from @table

Check syntax не позволяет этому сохраниться: must declare variable @table, хотя @table, как вы видите, определена.
Мне необходимо создавать и посылать запросы для той таблицы, которую процедура получит в агрументах. Видимо MSSQL не позволяет так делать из соображений безопасности? Или в чем-то другом ошибка? Как можно это обойти?
Заранее спасибо
49K
23 октября 2009 года
suff84
8 / / 08.06.2009
Привет.
Попробуй в этом направлении:

CREATE PROCEDURE test
@table varchar(20)
AS

DECLARE @CmdText AS VARCHAR(50)

@CmdText = 'select * from ' + @table

EXEC(@CmdText )

Только нужно следить за длиной строки.
385
23 октября 2009 года
SomewherSomehow
477 / / 25.07.2004
Нет никаких соображений безопасности.
Ты пытаешься сделать селект из строковой переменной, что невозможно.
Я так понял что ты хочешьс делать примерно это:
 
Код:
CREATE PROCEDURE test
@table varchar(20)
AS

declare @query varchar(250)
set @query = 'select * from ' + @table
exec (@query)

-- в 2005 можно просто
-- exec ('select * from ' + @table)
385
23 октября 2009 года
SomewherSomehow
477 / / 25.07.2004
Уже опередили =)
Ну в общем используй вышесказанное...
Хотя, по своей практике, могу сказать что строить динамические запросы в коде SQL - очень плохая идея...потом в них тяжело разбираться и трудно сопровождать...
5.4K
23 октября 2009 года
cursor
114 / / 05.01.2008
Цитата: SomewherSomehow
Уже опередили =)


Зато ты пояснил че почем)
Вообщем-то мне надо чуть другое... Еxec не вернет результат в CURSOR ведь? Подскажите как в курсор
DECLARE CT CURSOR global forward_only dynamic FOR SELECT * from @table

385
23 октября 2009 года
SomewherSomehow
477 / / 25.07.2004
я б сделал самое простое, что приходит в голову, через таблицу, в которую записал бы результат exec.
Код:
declare @table varchar(50)
set @table = 'MyTable'

declare @query varchar(250)
set @query = 'select MyFiled from '+@table

declare @cur_table table (MyFiled int)
declare @cur_var int

insert into @cur_table
exec (@query)

declare cur cursor for
select * from @cur_table

open cur
fetch next from cur into @cur_var
while @@FETCH_STATUS = 0 begin

    select @cur_var
    fetch next from cur into @cur_var

end
close cur
deallocate cur

м.б. как-то еще можно...
5.4K
23 октября 2009 года
cursor
114 / / 05.01.2008
А именно мой вариант кто нибудь мне подскажет как реализовать?
385
23 октября 2009 года
SomewherSomehow
477 / / 25.07.2004
А чем твой вариант отличается от приведенного выше?
Ты ведь все-равно в курсоре будешь читать какие-то определенные данные, заранее известного типа, опредленное количество полей, ну так и объяви таблицу куда положишь эти данные из своего динамического запроса.

Если же сам курсор, количество и тип перебираемых в нем полей должно отличаться в зависимости от таблицы (т.е. у таблиц вообще нет общих данных, которые можно было бы обрабатывать в курсоре единообразно, с помощью фиксированного набора переменных в курсоре), то тогда, как мне подсказывает интуиция, надо и сам курсор создавать при помощи динамического запроса...=)

Или я чего-то не понимаю?
5.4K
23 октября 2009 года
cursor
114 / / 05.01.2008
Цитата: SomewherSomehow
А чем твой вариант отличается от приведенного выше?


В программе много запросов. Строк около 60к и запросов по 3-7 на каждую строку. И время выполнения критично.
А если еще и таблицы создавать, чтобы туда записи записывать, а потом оттуда брать...
Но если других вариантов нет, то ...

385
23 октября 2009 года
SomewherSomehow
477 / / 25.07.2004
ну как вариант еще можно так
Код:
declare @query nvarchar(250)
set @query = 'declare cur cursor global forward_only static read_only FOR SELECT MyFiled from ' + @table
exec (@query)
open cur
declare @cur_var int
fetch next from cur into @cur_var
while @@FETCH_STATUS = 0 begin

    select @cur_var
    fetch next from cur into @cur_var

end
close cur
deallocate cur


Но все равно необходимо перечислить в курсоре поля которые будешь из него брать, даже если использовать SELECT *. Так или иначе кол-во и тип полей в курсоре должно совпадать с кол-вом в предложении fetch.

Кстати если критично быстродействие, посмотри на выделенные жирным шрифтом опции если задача позволяет - установи их, многократно ускоряется работа с курсорами.
5.4K
24 октября 2009 года
cursor
114 / / 05.01.2008
вот, вот оно! Спасибо. Буду пробовать
5.4K
24 октября 2009 года
cursor
114 / / 05.01.2008
Извините за назойливость, а вот это как:
 
Код:
DECLARE @cursor CURSOR
SET @cursor = CURSOR FOR SELECT field1 from table1

Попробовал так
 
Код:
DECLARE @cursor CURSOR
SET @table = 'table'
SET @query = 'CURSOR FOR SELECT field1 from ' + @table
SET @cursor = @query

Анализатор пишет что варчар не присвоить типу курсор..
6
24 октября 2009 года
George
4.1K / / 05.01.2007
какая версия сервера?
начиная с 2005 делается так. читаем http://forum.codenet.ru/showthread.php?t=53882
[highlight=sql]
DECLARE @tmp TABLE(<params>)

INSERT INTO @tmp
EXEC ('SELECT * FROM ' + @tablename)

DECLARE @cursor CURSOR
SET @cursor = CURSOR FOR SELECT * FROM @tmp
[/highlight]
ну вот так как то...
хотя если 2000-ый сервер, то по идее можно так:
[highlight=sql]
INSERT INTO #tmp
EXEC ('SELECT * FROM ' + @tablename)

DECLARE @cursor CURSOR
SET @cursor = CURSOR FOR SELECT * FROM #tmp
[/highlight]
385
25 октября 2009 года
SomewherSomehow
477 / / 25.07.2004
Цитата: cursor
Извините за назойливость, а вот это как:
 
Код:
DECLARE @cursor CURSOR
SET @cursor = CURSOR FOR SELECT field1 from table1

Попробовал так
 
Код:
DECLARE @cursor CURSOR
SET @table = 'table'
SET @query = 'CURSOR FOR SELECT field1 from ' + @table
SET @cursor = @query

Анализатор пишет что варчар не присвоить типу курсор..



Ну правильно, нельзя, ты строковой переменной пытаешься присвоить значение переменной курсор, я вроде такого и не советовал...

Цитата: Washington

хотя если 2000-ый сервер, то по идее можно так:
[highlight=sql]
INSERT INTO #tmp
EXEC ('SELECT * FROM ' + @tablename)

DECLARE @cursor CURSOR
SET @cursor = CURSOR FOR SELECT * FROM #tmp
[/highlight]



К сожалению, это не сработает т.к. врем.таблица #tmp заранее не объявлена, чтобы ее объявить нужно знать структуру, что приводит нас к тому варианту, который ранее уже озвучивался...
Если уж извращаться так, чтоб сделать таблицу произвольной структуры, и это работало не только в 2005, то можно вот так...
[highlight=sql]
use Northwind

declare @tablename varchar(200)
set @tablename = 'Categories'

EXEC ('select * into tmp from ' + @tablename)
select * from tmp

drop table tmp
[/highlight]

6
25 октября 2009 года
George
4.1K / / 05.01.2007
Цитата: SomewherSomehow
К сожалению, это не сработает т.к. врем.таблица #tmp заранее не объявлена, чтобы ее объявить нужно знать структуру, что приводит нас к тому варианту, который ранее уже озвучивался...


хм, разве? по моему для создания темповых таблиц не надо структуру знать. их вообще объявлять вроде как не надо. хотя могу ошибаться. щас погуглю...

upd.
хм, да, ты был прав. почему то я думал иначе. подзабываю уже. ну тада для гиков - наверняка должна храниться служебная информация по таблицам, по ней теоретически можно создать темповую таблицу и применить мой вариант. но это для гиков, хотя я б так наверное попробовал сделать - интересно же =)

5
25 октября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Washington
тада для гиков - наверняка должна храниться служебная информация по таблицам, по ней теоретически можно создать темповую таблицу и применить мой вариант. но это для гиков, хотя я б так наверное попробовал сделать - интересно же =)


Для гиков было бы засунуть в SqlServer2005/2008 сборку на .NET и посредством такой хранимой процедуры выполнить требуемую логику. ;)

6
25 октября 2009 года
George
4.1K / / 05.01.2007
Цитата: hardcase
Для гиков было бы засунуть в SqlServer2005/2008 сборку на .NET и посредством такой хранимой процедуры выполнить требуемую логику. ;)


ну это другая степень гиковости. хотя да, в том, что предложил я ниче такого и нет. =)

5.4K
26 октября 2009 года
cursor
114 / / 05.01.2008
Цитата: SomewherSomehow

[highlight=sql]
EXEC ('select * into tmp from ' + @tablename)
select * from tmp
drop table tmp
[/highlight]


Сам же знал такую конструкцию. И почему сразу в голову не приходит

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог