Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Передача в табличную переменную результатов EXEC  [new]
Darteus
Member

Откуда:
Сообщений: 5
есть функция, которая должна принимать в качестве аргумента имя таблицы, по отношению к которой будут производиться вычисления. функция в результате этих вычислений возвращает табличную переменную.
пример функции (вычисления упразднены):
create function func1 (@t varchar(255))
returns @res table (nn int)
as
begin
declare @sql varchar(255)
set @sql='select count(id) as nn from '+@t

insert into @res exec(@sql)
return
end

MSSQL ругается на конструкцию INSERT EXEC, говоря, что их использование вызывает побочное действие в функции.

Как быть?
14 фев 13, 20:38    [13928694]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
qwerty112
Guest
Darteus,

у вас 2-а "пути" :
- подождать пока в функциях "разрешат" динамик скл
- переписать функцию / переделать на процедуру
14 фев 13, 20:46    [13928719]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Darteus
Member

Откуда:
Сообщений: 5
с процедурами в моем случае есть проблема. в последствии результат этой функции должен использоваться в SQL-запросе вида:
select * from TABLE1 where pole1 in (select pole1 from dbo.МОЯ_ФУНКЦИЯ)

А использовать в таком виде ПРОЦЕДУРУ сервер не хочет: говорит, что мол недопустимое имя объекта dbo.МОЯ_ПРОЦЕДУРА

Если подскажите, как его заставить это делать - сделаю все это ввиде процедур.
14 фев 13, 20:55    [13928750]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
А почему нельзя использовать временные таблицы?
14 фев 13, 21:05    [13928792]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Владимир Затуливетер
Member

Откуда:
Сообщений: 427
Вычисления засунуть в функцию dbo.FnBaseCalc(param1, param2, ... paramN)
Написать для каждой таблицы отдельные функци в которых вызывать базовую dbo.FnBaseCalc
Если такое прокатит у вас.
14 фев 13, 21:10    [13928807]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
invm
Member

Откуда: Москва
Сообщений: 9838
Если потребовалась функция с динамикой, значит, скорее всего, БД спроектирована с ошибками.
14 фев 13, 21:29    [13928870]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Darteus
Member

Откуда:
Сообщений: 5
Временные таблицы использовать не хочу, ибо обрабатываемые в базах данные исчисляются сотнями миллионов. Может я чего-то не знаю, но не думаю, что сервак будет в восторге от создания временной таблицы, которая в ходе работы будет заполняться таким количеством данных.

Идея написать для каждой таблицы отдельные функции рабочая, но очень не хотелось копи-пастить один и тот же код. Хотелось единое красивое решение, применимое ко всем базам (структура то у них одинаковая).
14 фев 13, 21:31    [13928880]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
qwerty112
Guest
Darteus
Идея написать для каждой таблицы отдельные функции рабочая, но очень не хотелось копи-пастить один и тот же код. Хотелось единое красивое решение, применимое ко всем базам (структура то у них одинаковая).


"базами" - вы таблицы, конечно, называете, да ?

тогда вопрос :
- а зачем вам столько одинаковых по структуре "баз" ?
14 фев 13, 21:34    [13928892]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
qwerty112
Guest
invm
Если потребовалась функция с динамикой, значит, скорее всего, БД спроектирована с ошибками.

+1
14 фев 13, 21:35    [13928894]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Darteus
Member

Откуда:
Сообщений: 5
Нет. задача именно с базами.

Есть база, в которой помимо данных должна быть эта процедура/функция. И есть несколько баз с однотипной информацией. Все базы на одном сервере.
В идеале хотелось бы чтобы эта процедура/функция в базе, вызывалась с параметром (параметр являет собой имя одной из тех баз с однотипной информацией) я бы получал некий результат вычислений, который потом можно было бы положить, например, в ту отдельную базу.
Но фишка в том, что эту процедуру/функцию надо вызывать не просто по имени, а указывая ее в стороннем sql-запросе, который использует ее результаты. И вот тут возникает заковырка, ибо таким макаром можно только функции вызывать.

Почему три базы с одинаковой структурой? Данные в них поступают из трех источников и данных этих сотни миллионов. Плюс к тому же есть задачи, которые надо решать отдельно для каждой базы (для каждого источника). Поэтому объединять их не будет правильным.
14 фев 13, 21:48    [13928944]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Darteus
Поэтому объединять их не будет правильным.

Почему?
14 фев 13, 22:04    [13929003]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Crimean
Member

Откуда:
Сообщений: 13147
а кто мешает пользовать "exec @procname" ?
где @procname = @dbname + '.dbo.myproc'
то есть "динамика без динамики"

ибо сделать select from @tablename у вас точно не получится
так что "диспетчер" над базами вам делать в любом случае
только надо регить где - на сервере или на клиенте
14 фев 13, 22:21    [13929073]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31984
Darteus
Временные таблицы использовать не хочу, ибо обрабатываемые в базах данные исчисляются сотнями миллионов. Может я чего-то не знаю, но не думаю, что сервак будет в восторге от создания временной таблицы, которая в ходе работы будет заполняться таким количеством данных.
Использование функций намного драматичнее сказывается на производительности, это просто несравнимо.
Crimean
а кто мешает пользовать "exec @procname" ?
где @procname = @dbname + '.dbo.myproc'
то есть "динамика без динамики"
Ещё можно вьюхами объединять данные, в общем, нужно смотреть постановку задачи.
14 фев 13, 23:34    [13929297]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Mikebond
Member

Откуда: Киев
Сообщений: 32
Darteus
Временные таблицы использовать не хочу, ибо обрабатываемые в базах данные исчисляются сотнями миллионов. Может я чего-то не знаю, но не думаю, что сервак будет в восторге от создания временной таблицы, которая в ходе работы будет заполняться таким количеством данных.

Т.е. пихать эти "сотни миллионов" в оперативу, а если оперативка закончится, то все-равно свопить на диск - лучше? Меня терзают смутные сомнения....
Если не вдаваться в анализ архитектуры, я бы сделал так: заменить функции на процедуры, в которых выбираются нужные наборы данных (в зависимости от параметра). Сторонний запрос перед основной работой запускает эту процедуру, сохраняя результат во #временную таблицу(это возможно. Если не ошибаюсь, то "инсерт #моя_временная_таблица екзек моя_процедура(...) "), и потом эту таблицу использует по своему усмотрению.

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


Ну, можно добавить на вход одной функции параметр (@source_id int) и внутри сваять что-то типа if @source_id = 1 Begin...<select из "базы 1"> ...end if @source_id =2 и т.д.
От копипасты не спасет, но она хоть будет в одном месте. Кстати, не забываем доделывать процедуру (и все подобные ей) каждый раз при изменении количества источников данных....бр-р-р-р-р.

Другой вариант - сделать одну таблицу для всех данных с доп полем source_id и при выполнении разных операций добавлять where source_id =@source_id . Наполнение этого поля можно организовать при загрузке данных. Ну, + таблица (сорс_ид, сорс_нейм,<все нужные параметры/поля>), индекы.

Кроме того, передавать id int, а не tableName varchar(255) лучше и из соображений безопасности (про sql injection слыхал? в 255 символов можно много чего наинжектить...).

Как-то так...
15 фев 13, 03:13    [13929668]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
Darteus
Идея написать для каждой таблицы отдельные функции рабочая, но очень не хотелось копи-пастить один и тот же код. Хотелось единое красивое решение, применимое ко всем базам (структура то у них одинаковая).
можно написать процедурку которая могла бы генерить вам нужное количество функций
типа и "копипастить" не надо и все получилось так как хотели
это довольно странный взгляд, но код лежащий на сервере это такие же данные как и все остальные лежащие в таблицах
я довольно часто храню код в своих таблицах
часто пишу селекты которые возвращают скрипты которые потом надо прогнать
бывало что скрипты надо было прогонять пару раз (т.е фактически третья производная)
15 фев 13, 13:47    [13931696]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Darteus
Member

Откуда:
Сообщений: 5
Выбрал для себя наиболее легкий вариант из предложенных - использование хранимых процедур, результат которых кладется в глобальные временные таблицы, ну а далее из любого запроса к ним можно спокойно обратиться.
Вообщем, всем спасибо!
15 фев 13, 14:52    [13932211]     Ответить | Цитировать Сообщить модератору
 Re: Передача в табличную переменную результатов EXEC  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Darteus
Есть база, в которой помимо данных должна быть эта процедура/функция. И есть несколько баз с однотипной информацией. Все базы на одном сервере.
В идеале хотелось бы чтобы эта процедура/функция в базе, вызывалась с параметром (параметр являет собой имя одной из тех баз с однотипной информацией) я бы получал некий результат вычислений, который потом можно было бы положить, например, в ту отдельную базу.
Но фишка в том, что эту процедуру/функцию надо вызывать не просто по имени, а указывая ее в стороннем sql-запросе, который использует ее результаты. И вот тут возникает заковырка, ибо таким макаром можно только функции вызывать.

Почему три базы с одинаковой структурой? Данные в них поступают из трех источников и данных этих сотни миллионов. Плюс к тому же есть задачи, которые надо решать отдельно для каждой базы (для каждого источника). Поэтому объединять их не будет правильным.
Darteus
Выбрал для себя наиболее легкий вариант из предложенных - использование хранимых процедур, результат которых кладется в глобальные временные таблицы, ну а далее из любого запроса к ним можно спокойно обратиться.
Может так?
use Base0 -- главная база
GO
create proc MyProc0 @bases int, @params int as
  create table #group (BaseId int, OtherData ....) -- накопитель итоговой информации
  if @bases%10=1
    insert #group exec Base1.dbo.MyProc @params -- своя обработка, в финальном селекте BaseId=1
  if @bases/10%10=1
    insert #group exec Base2.dbo.MyProc @params -- своя обработка, в финальном селекте BaseId=2
  if @bases/100=1
    insert #group exec Base3.dbo.MyProc @params -- своя обработка, в финальном селекте BaseId=3
  select * from #group -- дальнейшая обработка накопленной в других базах информации
  drop table #group
GO
exec Base0.dbo.MyProc0 101, 90 -- выполнить на 1 и 3 базах с общим для MyProc параметром "90"
и - никаких глобальных временных таблиц?
15 фев 13, 16:00    [13932725]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить