Модераторы: Akina
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование результата одной процедуры в другой, без временных таблиц 
V
    Опции темы
default_user
Дата 27.12.2006, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 27.12.2006
Где: Москва

Репутация: нет
Всего: 1



Доброго времени суток всем! smile 

Я совсем немного времени работаю с MS SQL,  у меня возникают некоторые затруднения, касательно написания хранимых процедур, т.к. логика их построения отличается от процедур на Interbase (с которым некоторый опыт имеется), по крайней мере, мне так кажется smile 
Так вот. Возникла такая проблема. У меня есть процедура, которая возвращает некоторый набор данных. Далее, мне нужно использовать этот набор в другой процедуре как условие запроса. Каким образом можно это сделать, не используя промежуточных таблиц? И можно ли вообще объединить эти две процедуры в одну? 

Мне нужен аналог оператора for select из Interbase (который делает какие-либо действия для каждой строки из выборки, в том числе и другие выборки).
Первая процедура (определяет пользователей, которых "видит" данный по статусу):
Код

CREATE PROCEDURE [dbo].[UsersAccess]
@Login varchar(50),
@Pass varchar(50)

 AS
declare @workgr int
declare @stat int
declare @user int

select @workgr=workgroup, @stat=status, @user=[user_id] from logins where [log]=@Login and pwrd=@Pass

if @stat=1
 begin
  select [user_id] from logins where [user_id]=@user
  return
 end

if @stat=2
 begin
  select [user_id] from logins where workgroup=@workgr
   return
 end

else
 begin
  select [user_id] from logins
  return
 end
GO



Во второй производится выборка и суммирование, которую нужно провести только для записей этих пользователей. То есть,  нужен либо цикл по каждому значению из первой процедуры (как???), либо условие where create_user in (*результирующий набор из процедуры 1*). Только как его сюда вписать этот набор? варианты
in (select [user_id]  from UsersAccess и in (execute UsersAccess @login=@ID, @pass=@Pswd) 
не проходят  smile 
Код

CREATE PROCEDURE [dbo].[SumByProjects]
@ID varchar(50)='',
@Pswd varchar(50)=''
 AS
select add_ind, sum(reestr.price_in) as in_sum, sum(reestr.price_out) as out_sum from
addition inner join reestr on 
(addition.project_id=reestr.project_id and addition.period_id=0 and addition.create_user in (???)
group by addition.add_ind
GO

PM MAIL   Вверх
SergKO
Дата 28.12.2006, 06:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 14.3.2005

Репутация: 17
Всего: 20



1 вариант: использовать

Код

INSERT #Table EXECUTE UsersAccess @Login, @Pass


2 вариант: оформить UsersAccess в виде функции

Код

CREATE FUNCTION [dbo].[UsersAccess] (@Login varchar(50),@Pass varchar(50))
RETURNS @UserId TABLE
(
    [user_id]    int
)
BEGIN 

declare @workgr int
declare @stat int
declare @user int
    
    select @workgr=workgroup, @stat=status, @user=[user_id] from logins where [log]=@Login and pwrd=@Pass
    
    if @stat=1 begin
        INSERT INTO @UserId
              select [user_id] from logins where [user_id]=@user
    end ELSE if @stat=2 begin
        INSERT INTO @UserId
          select [user_id] from logins where workgroup=@workgr
    end else begin
        INSERT INTO @UserId
          select [user_id] from logins
    end

RETURN
END
GO


и использовать в запросе


Код

select add_ind, sum(reestr.price_in) as in_sum, sum(reestr.price_out) as out_sum from
addition inner join reestr on 
(addition.project_id=reestr.project_id and addition.period_id=0 and addition.create_user in (SELECT user_id FROM dbo.UsersAccess(@Login, @Pass) )
group by addition.add_ind

PM MAIL   Вверх
default_user
Дата 28.12.2006, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 27.12.2006
Где: Москва

Репутация: нет
Всего: 1



Спасибо за совет!  smile 

Я вот пытаюсь реализовать это с помощью курсоров, но в виде функции будет работать быстрее, да?

И еще маленький вопрос. Как сделать, чтобы в результат не включался результирующий набор вызова какой-нибудь промежуточной процедуры? А то в query analizer я получаю два окна результатов.


Это сообщение отредактировал(а) default_user - 28.12.2006, 10:44
PM MAIL   Вверх
SergKO
Дата 28.12.2006, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 14.3.2005

Репутация: 17
Всего: 20



1. Да. Быстрее курсоров.
2. В queryanaliser'е Вы будете видеть столько наборов, сколько "попросили". Если у Вас появляются "лишние" наборы, значит где-то неверно используется эта самая промежуточная процедура.
PM MAIL   Вверх
default_user
Дата 28.12.2006, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 27.12.2006
Где: Москва

Репутация: нет
Всего: 1



Мои результаты  smile 
С функцией все работает, только условие нужно вписать не в join, а в секцию where после join. (Это я так, мало ли пригодится кому).
А вот первый вариант с #table что-то не получился  smile  Ситнтакс проходит, а вот при исполнении пишет: Invalid object name '#Table'.
Может я чего недопонимаю? Объясните, плз, значение символа #  smile  Наверное, я неправильно понимаю:
Код

CREATE PROCEDURE [dbo].[SumByProjects]
@Login varchar(50)='',
@Pass varchar(50)=''
 AS
INSERT  #Table EXECUTE UsersAccess @Login, @Pass
select add_ind, sum(reestr.price_in) as in_sum, sum(reestr.price_out) as out_sum from
addition inner join reestr on 
(addition.project_id=reestr.project_id and addition.period_id=0) where addition.create_user in (SELECT [user_id] FROM #Table) 
group by addition.add_ind
GO

PM MAIL   Вверх
SergKO
Дата 28.12.2006, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 14.3.2005

Репутация: 17
Всего: 20



Перед выполнением конструкции

Код

INSERT  #Table EXECUTE UsersAccess @Login, @Pass

необходимо создать временную таблицу #Table (символ # говорит о том, что она временная)

Код

CREATE TABLE #Table ([user_id]    int)


т.е.

Код

CREATE PROCEDURE [dbo].[SumByProjects]
@Login varchar(50)='',
@Pass varchar(50)=''
 AS
CREATE TABLE #Table ([user_id]    int)
INSERT  #Table EXECUTE UsersAccess @Login, @Pass
select add_ind, sum(reestr.price_in) as in_sum, sum(reestr.price_out) as out_sum from
addition inner join reestr on 
(addition.project_id=reestr.project_id and addition.period_id=0) where addition.create_user in (SELECT [user_id] FROM #Table) 
group by addition.add_ind
GO



Добавлено @ 11:12 
Кстати, если Вы посмотрите план запроса, то условие

Код

where addition.create_user in (SELECT [user_id] FROM #Table) 


должно быть преобразовано оптимизатором в

Код

INNER JOIN #Table t ON t.user_id = addition.create_user


Тогда, сначала будет произведена выборка по этому условию, и только потом JOIN с reestr

PM MAIL   Вверх
default_user
Дата 28.12.2006, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 27.12.2006
Где: Москва

Репутация: нет
Всего: 1



SergKO, 
Спасибо вам большое-пребольшое!!! smile 

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "MS SQL"
Akina

Akina

Запрещается!

Публиковать ссылки и обсуждать взлом чего бы то ни было.

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы составления неспецифических запросов рассматриваются здесь
  • Используйте теги [code=sql][/code] для подсветки кода. Используйтe чекбокс "транслит" (возле кнопок кодов) если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, Akina.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MS SQL Server | Следующая тема »


 




[ Время генерации скрипта: 0.0466 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.