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 года
Сначала сделал селект в временную таблицу, затем курсором прошелся по ней и проставил нужные значения, и наконец вывел данные с нужными мне параметрами (с возможностью задать минимум и максимум в наличии).
а зачем вы новую тему для того же самого вопроса создаете? писали бы в этой.
хотя, наверное, общая "реструктуризация" форума провоцирует на подобные действия...печально. В любом случае, просьба больше так не далеать, а так же код оформлять специальным тегом, чтобы другие участники не ломали глаза.
По теме, вот вы собрали данные временную таблицу, дальше сделайте из нее селект и на клиенте разберите? Если нужно передать в другую процедуру на сервере минуя клиента, просто вызовите из этой процедуры, другую, глобальная временная таблица будет доступна внутренней процедуре (но.т.к. это видно и другим сессиям, то подумайте что будет, когда будет много юзеров?).
Но вообще, процедуры в сиквеле немного не для этого, результатом выполнения процедуры, должно являться какое-то осмысленное законченное действие. То что вы пытаетесь возложить на процедуру - должна выполнять функция в скивел серере. Так что мой совет переделайте в функцию!
Просто вот так:
Код:
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;
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_);
--...бла-бла-бла...
as
--...бла-бла-бла...
select
*
from
dbo.uf_glmat(@dat2_);
--...бла-бла-бла...
Ну и повторяя предыдущее высказывание, теперь, когда я увидель код, со всей ответственностью заявляю вам, что в этой задачке использование курсоров проистекает от неумения готовить sql. Курсор тут не нужен. По этому, после переделки процедуру в функцию, советую еще переделать тип функции с "Multistatement Table-valued Function Syntax" на "Transact-SQL Inline Table-Valued Function Syntax", вот тут про типы функций.
Удачи.
С функциями понятно, но как обойтись без курсоров. Напишите пожалуйста образец кода этой задачи без использования курсора..
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
);
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 - нормальные смысловые имена.
Спасибо большое за помощь!