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

Ваш аккаунт

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

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

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

Передача данных из хранимой хроцедуры в приложение

78K
27 февраля 2012 года
alchonok62
4 / / 24.02.2012
Подскажите, пожалуйста. Объясняю ситуацию. Я разрабатываю подсистему "Склад", то есть мне нужно в хранимой процедуре выбрать материалы, которые на конкретную дату есть в остатках. Я в процедуре выбираю все материалы, которые есть в приходных ТТН в курсор. Затем в цикле по каждому материалу запросом определяю количество расходов на данную дату из таблицы расходных ТТН. Нахожу разность, и, если количество больше нуля, то его нужно передать в результирующие выходные параметры. Как в цикле передавать данные в output параметры?

Мне уже ответили(спасибо большое), но у меня ничего не получилось. Помогите, пожалуйста. Потратила уйму времени. Привожу пример кода.
Код:
ALTER PROCEDURE [dbo].[GlMat] (@DAT2_ datetime, @KOD_M_ int output, @NAME_M_ int output)
AS

If (Select object_Id('tempdb..##TmpMat'))>0 begin drop table ##TmpMat End

Create table ##TmpMat (KOD_M  int, NAME_M varchar(60))

Declare KURS Cursor For select TrPPrix.ID_M,  SUM (TrPPrix.KOL) as KOL  from TrPPrix left join TrPrix on (TrPPrix.ID_OSN=TrPrix.ID_STR)  Where TrPrix.DATA<=@DAT2_ Group By ID_M
Declare @KOL_REZ_ int, @KOL_OT_ int
Declare @ID_M_ int, @KOL_ int --Для курсора

Open KURS

Fetch NEXT From KURS into @ID_M_, @KOL_

While @@Fetch_STATUS = 0
Begin

Set @KOL_OT_= (Select SUM (TrRRasx.KOL_OT)AS KOL_OT From TrRRasx left join TrRasx on (TrRasx.ID_STR = TrRRasx.ID_OSN) left join TrPPrix on (TrRRasx.ID_PRIX=TrPPrix.ID_PSTR) Where DATA<=@DAT2_ and TrPPrix.ID_M = @ID_M_)
Set @KOL_REZ_=@KOL_- @KOL_OT_

If (@KOL_REZ_>0)  Begin

Set @KOD_M_ = (Select KOD_M from TrSprMat where TrSprMat.ID_STR=@ID_M_)
Set @NAME_M_ = (Select NAME_M from TrSprMat where TrSprMat.ID_STR=@ID_M_)

Insert Into ##TmpMat (KOD_M, NAME_M) values (@KOD_M_, @NAME_M_ )

End

Fetch NEXT From KURS into @ID_M_, @KOL_

End

Close KURS
Deallocate KURS
  • Спасибо большое. А не могли бы Вы мне привести весь код. Буду очень признательна. Знаний по хранимым процедурам мало от alchonok62, 28 февраля 2012 года
18K
27 февраля 2012 года
imAlex
179 / / 29.07.2010
Я имитировал подобную задачу и решил ее сл. образом.
Сначала сделал селект в временную таблицу, затем курсором прошелся по ней и проставил нужные значения, и наконец вывел данные с нужными мне параметрами (с возможностью задать минимум и максимум в наличии).
385
28 февраля 2012 года
SomewherSomehow
477 / / 25.07.2004
alchonok62,
а зачем вы новую тему для того же самого вопроса создаете? писали бы в этой.
хотя, наверное, общая "реструктуризация" форума провоцирует на подобные действия...печально. В любом случае, просьба больше так не далеать, а так же код оформлять специальным тегом, чтобы другие участники не ломали глаза.

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

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


Код:
create function dbo.uf_glmat(@dat2_ datetime)
returns @tmpmat table(kod_m int, name_m varchar(60))
as begin

    declare @kod_m_ int, @name_m_ int;

    declare kurs cursor for
    select
        trpprix.id_m,
        sum (trpprix.kol) as kol
    from
        trpprix
        left join trprix on trpprix.id_osn = trprix.id_str
    where trprix.data<=@dat2_
    group by id_m
    ;

    declare @kol_rez_ int, @kol_ot_ int;
    declare @id_m_ int, @kol_ int; --для курсора

    open kurs;
    fetch next from kurs into @id_m_, @kol_;

    while @@fetch_status = 0 begin

        set @kol_ot_= (
            select
                sum (trrrasx.kol_ot)as kol_ot
            from
                trrrasx
                left join trrasx on trrasx.id_str = trrrasx.id_osn
                left join trpprix on trrrasx.id_prix=trpprix.id_pstr
            where
                data<=@dat2_ and trpprix.id_m = @id_m_
        );
       
        set @kol_rez_=@kol_- @kol_ot_;

        if (@kol_rez_>0) begin

            set @kod_m_ = (select kod_m from trsprmat where trsprmat.id_str=@id_m_);
            set @name_m_ = (select name_m from trsprmat where trsprmat.id_str=@id_m_);

            insert into @tmpmat (kod_m, name_m) values (@kod_m_, @name_m_ );

        end;

        fetch next from kurs into @id_m_, @kol_;
    end;

    close kurs;
    deallocate kurs;

    return;

end;

после чего в любой процедуре сможете к ней обращаться как

 
Код:
alter proc my_proc
as

--...бла-бла-бла...
select
    *
from
    dbo.uf_glmat(@dat2_);
   
--...бла-бла-бла...


Ну и повторяя предыдущее высказывание, теперь, когда я увидель код, со всей ответственностью заявляю вам, что в этой задачке использование курсоров проистекает от неумения готовить sql. Курсор тут не нужен. По этому, после переделки процедуру в функцию, советую еще переделать тип функции с "Multistatement Table-valued Function Syntax" на "Transact-SQL Inline Table-Valued Function Syntax", вот тут про типы функций.
Удачи.
78K
29 февраля 2012 года
alchonok62
4 / / 24.02.2012
С функциями понятно, но как обойтись без курсоров. Напишите пожалуйста образец кода этой задачи без использования курсора..
385
29 февраля 2012 года
SomewherSomehow
477 / / 25.07.2004
Т.е вы хотите, чтобы я,
1) без структуры таблиц?
2) не зная логики
3) не видя отношений между таблицами
4) и не имея под рукой никаких тестовых данных
- предоставил вам код? =)))
Спасибо за оказанное доверие! =))

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


Код:
create function dbo.uf_glmat(@dat2_ datetime)
returns table
as return (

    with A as
    (
        select
            t1.id_m,
            sum (t1.kol) as kol
        from
            trpprix t1
            left join trprix t2 on t1.id_osn = t2.id_str
        where
            t2.data <= @dat2_      
        group by
            t1.id_m
    ),
    B as
    (
        select
            t2.id_m,
            sum (t1.kol_ot)as kol_ot
        from
            trrrasx t1
            /*left вы уверены что тут лефт нужен?*/ join trpprix t2 on t1.id_prix = t2.id_pstr            
            left join trrasx t3 on t3.id_str = t1.id_osn
        where
            data <= @dat2_
        group by
            t2.id_m  
    )
    select
        C.kod_m,
        C.name_m
    from
        A
        join B on B.id_m = A.id_m
        join trsprmat C on C.id_str = A.id_m
    where
        A.kol > B.kol_ot
               
);


И клятвенно и слезно вас прошу! Ну используйте вы в запросах альясы! Суть - альтернативные имена для таблиц в запросе. Они могут раскрывать смысл таблицы, если она имеет "нечеловеческое" называние (как у вас trpprix,trprix,trrrasx,trrasx - кстати кто придумал давать такие имена?? там же опечататься очень легко, сами себе грабли раскладываете!), тогда можно развернуть trpprix в Income например или еще во что-то более осмысленное, старайтесь делать свой код, максимально самодокументируемым, либо наоборот, если таблица имеет хорошее описательное име типа EmployeeTarifGategory, в запросе не надо писать EmployeeTarifGategory. EmployeeID, сделайте альяс etg и обращайтесь etg.EmployeeID. Ну ведь реально глаза же сломаешь читать!
До сих пор сижу исправляю у себя на работе код, после одного такого "умельца", любителя интеллисенса, чтоб ему. Так что приучайте себя к хорошему стилю сразу, и вам удобнее читать будет и другие спасибо скажут.
Когда будете адаптировать мой запрос в свой продакшн или куда там, дайте вместо альясов A,B,C - нормальные смысловые имена.
78K
01 марта 2012 года
alchonok62
4 / / 24.02.2012
Спасибо большое за помощь!

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

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