Конструкция declare @table='table' create table @table (m int)
Появилась необходимость написать хранимую процедуру для MSSQL.
Мне нужно выполнить такой запрос:
@table varchar(20)
AS
select * from @table
Check syntax не позволяет этому сохраниться: must declare variable @table, хотя @table, как вы видите, определена.
Мне необходимо создавать и посылать запросы для той таблицы, которую процедура получит в агрументах. Видимо MSSQL не позволяет так делать из соображений безопасности? Или в чем-то другом ошибка? Как можно это обойти?
Заранее спасибо
Попробуй в этом направлении:
CREATE PROCEDURE test
@table varchar(20)
AS
DECLARE @CmdText AS VARCHAR(50)
@CmdText = 'select * from ' + @table
EXEC(@CmdText )
Только нужно следить за длиной строки.
Ты пытаешься сделать селект из строковой переменной, что невозможно.
Я так понял что ты хочешьс делать примерно это:
@table varchar(20)
AS
declare @query varchar(250)
set @query = 'select * from ' + @table
exec (@query)
-- в 2005 можно просто
-- exec ('select * from ' + @table)
Ну в общем используй вышесказанное...
Хотя, по своей практике, могу сказать что строить динамические запросы в коде SQL - очень плохая идея...потом в них тяжело разбираться и трудно сопровождать...
Зато ты пояснил че почем)
Вообщем-то мне надо чуть другое... Еxec не вернет результат в CURSOR ведь? Подскажите как в курсор
DECLARE CT CURSOR global forward_only dynamic FOR SELECT * from @table
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
м.б. как-то еще можно...
Ты ведь все-равно в курсоре будешь читать какие-то определенные данные, заранее известного типа, опредленное количество полей, ну так и объяви таблицу куда положишь эти данные из своего динамического запроса.
Если же сам курсор, количество и тип перебираемых в нем полей должно отличаться в зависимости от таблицы (т.е. у таблиц вообще нет общих данных, которые можно было бы обрабатывать в курсоре единообразно, с помощью фиксированного набора переменных в курсоре), то тогда, как мне подсказывает интуиция, надо и сам курсор создавать при помощи динамического запроса...=)
Или я чего-то не понимаю?
В программе много запросов. Строк около 60к и запросов по 3-7 на каждую строку. И время выполнения критично.
А если еще и таблицы создавать, чтобы туда записи записывать, а потом оттуда брать...
Но если других вариантов нет, то ...
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.
Кстати если критично быстродействие, посмотри на выделенные жирным шрифтом опции если задача позволяет - установи их, многократно ускоряется работа с курсорами.
SET @cursor = CURSOR FOR SELECT field1 from table1
Попробовал так
SET @table = 'table'
SET @query = 'CURSOR FOR SELECT field1 from ' + @table
SET @cursor = @query
Анализатор пишет что варчар не присвоить типу курсор..
начиная с 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]
SET @cursor = CURSOR FOR SELECT field1 from table1
Попробовал так
SET @table = 'table'
SET @query = 'CURSOR FOR SELECT field1 from ' + @table
SET @cursor = @query
Анализатор пишет что варчар не присвоить типу курсор..
Ну правильно, нельзя, ты строковой переменной пытаешься присвоить значение переменной курсор, я вроде такого и не советовал...
хотя если 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]
хм, разве? по моему для создания темповых таблиц не надо структуру знать. их вообще объявлять вроде как не надо. хотя могу ошибаться. щас погуглю...
upd.
хм, да, ты был прав. почему то я думал иначе. подзабываю уже. ну тада для гиков - наверняка должна храниться служебная информация по таблицам, по ней теоретически можно создать темповую таблицу и применить мой вариант. но это для гиков, хотя я б так наверное попробовал сделать - интересно же =)
Для гиков было бы засунуть в SqlServer2005/2008 сборку на .NET и посредством такой хранимой процедуры выполнить требуемую логику. ;)
ну это другая степень гиковости. хотя да, в том, что предложил я ниче такого и нет. =)
[highlight=sql]
EXEC ('select * into tmp from ' + @tablename)
select * from tmp
drop table tmp
[/highlight]
Сам же знал такую конструкцию. И почему сразу в голову не приходит