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

Откуда: Новосибирск
Сообщений: 18
Здравствуйте!

Есть 2 таблицы Events (мероприятия) и Actions (занятия) связанные внешним ключом events 1 - * actions.
Пользователи программы работают с этими двумя таблицами с текущими датами.
Так же есть еще две аналогичных таблицы Calendar_events (1 - *) Calendar_actions без привязки к датам (календарные планы), которые хочется использовать для заполнения таблиц Events и Actions.

До этого с курсорами работать не приходилось, почитал, погуглил и вот что у меня получилось:

declare @fromdate datetime = '18.11.2013'
declare @todate datetime = '24.11.2013'
declare @currdate datetime = @fromdate
declare @FacilityID int = 100
declare @counter int = 0
declare @eventcounter int = 0
declare @CurrEventID int 
declare @DayID int

declare EventList cursor for --объявляем курсор
(select	[events].CurrEventID
	from	[dbo].[events] INNER JOIN [dbo].event_list
			ON ([dbo].[events].EventID = [dbo].[event_list].EventID)
			AND ([event_list].FacilityID = @FacilityID)
	WHERE ActionDate = @currdate)

SET XACT_ABORT ON

BEGIN TRANSACTION

--цикл по заполняемым датам
WHILE @currdate <= @todate
BEGIN --начало цикла WHILE (1)
--день недели
SET @DayID = DATEPART(WEEKDAY,@currdate)

	--проверяем отсутствие записей в таблице events на текущую дату
	SET @eventcounter = (select	Count([events].EventID)
	from	[dbo].[events] INNER JOIN [dbo].event_list
			ON ([dbo].[events].EventID = [dbo].[event_list].EventID)
			AND ([event_list].FacilityID = @FacilityID)
	WHERE ActionDate = @currdate)

	--если нет записей на текущую дату
	IF 	@eventcounter = 0
		BEGIN --начало блока IF (1)

	--добавляем записи в таблицу events на текущую дату 
insert into [dbo].[events] (EventID, ActionDate, BeginTime, EndTime, Match)
(select	[calendar_events].EventID, @currdate AS ActionDate, BeginTime, EndTime, 0 AS Match
	from	[dbo].[calendar_events] INNER JOIN [dbo].event_list
			ON ([dbo].[calendar_events].EventID = [dbo].[event_list].EventID)
			INNER JOIN  [dbo].[facilities]
			ON ([dbo].[facilities].FacilityID = @FacilityID)
	WHERE DayID =DATEPART(WEEKDAY,@currdate)) 

	--открываем курсор
	OPEN EventList

	FETCH NEXT FROM EventList INTO @CurrEventID

	WHILE @@FETCH_STATUS = 0
		BEGIN  --Цикл по курсору

	insert into [dbo].[actions] (CurrEventID, TrackID, GroupID, HeaderID, ContractContact)
	select	@CurrEventID AS CurrEvent, TrackID, GroupID, HeaderID, ContractContact
	from	[dbo].[calendar_actions] INNER JOIN [dbo].[calendar_events]
			ON ([calendar_actions].CalendarEventID = [calendar_events].CalendarEventID)
			AND ([dbo].[calendar_events].EventID = @CurrEventID)
			INNER JOIN  [dbo].[facilities]
			ON ([dbo].[facilities].FacilityID = @FacilityID)
	WHERE DayID =DATEPART(WEEKDAY,@currdate)

		FETCH NEXT FROM EventList INTO @CurrEventID
		END --Цикл по курсору

	--закрываем курсор
	CLOSE EventList

		END --конец блока IF (1)

SET @currdate = DATEADD(DAY,1,@currdate)
END --Конец цикла WHILE (1)

DEALLOCATE EventList --уничтожаем курсор

COMMIT TRANSACTION


Пытался отлавливать ошибки, сообщений нет, транзакция выполняется. Но при этом курсор работает только со статикой и данные переносятся только в таблицу events из calendar_events. В таблицу actions данные из calendar_actions не переносятся, даже если курсор объявлен без переменных (при этом сам курсор инициализируется заданным значением).

Опыта маловато, пишу диплом. Поэтому прошу Вашей помощи! Спасибо, что уделили время.
17 ноя 13, 16:00    [15143823]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
rsagro
Member

Откуда: Новосибирск
Сообщений: 18
upd: Пошаговое выполнение инициализирует курсор переменными как и должно быть, тело цикла выполняется, но данных в таблице по прежнему нет.

@@Version Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (X64)
Dec 28 2012 20:23:12
Copyright (c) Microsoft Corporation
Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
17 ноя 13, 16:22    [15143888]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
invm
Member

Откуда: Москва
Сообщений: 9825
rsagro
Опыта маловато, пишу диплом
Если цель всего лишь написать диплом - перенесите DEALLOCATE EventList внутрь цикла, сразу за CLOSE EventList.
Если хотите написать диплом и чему-то научиться - задачу можно решить вообще без курсоров и циклов.
17 ноя 13, 16:25    [15143899]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
rsagro
Member

Откуда: Новосибирск
Сообщений: 18
invm, мне непременно интересно какими еще способами можно решить задачу. Просто я сейчас по 16 часов в день провожу за компом, ибо не успеваю и детально изучить возможности языка не представляется возможным. А DEALLOCATE у меня изначально после CLOSE и был, уже потом его вынес за цикл. Попробовал вернуть, не помогло.
17 ноя 13, 16:36    [15143928]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31949
rsagro
upd: Пошаговое выполнение инициализирует курсор переменными как и должно быть, тело цикла выполняется, но данных в таблице по прежнему нет.
Очевидно, раз ошибок нет, то вставляются не те данные, которые вы ожидаете (или вы неправильно проверяете данные после вставки).

Отладить это очень легко.
Ставите отладочный вывод перед "insert into [dbo].[actions]", далее выполняете insert into [dbo].[actions] с этими данными.
И смотрите, почему не вставляется.
17 ноя 13, 16:47    [15143961]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31949
invm
перенесите DEALLOCATE EventList внутрь цикла, сразу за CLOSE EventList.
ИМХО всё правильно расставлено. Просто неудачное оформление текста.

То есть там:
1. OPEN курсор
2. цикл по курсору
3. CLOSE курсор
17 ноя 13, 16:49    [15143971]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
invm
Member

Откуда: Москва
Сообщений: 9825
alexeyvg
ИМХО всё правильно расставлено
DECLARE CURSOR (Transact-SQL)
Variables may be used as part of the select_statement that declares a cursor. Cursor variable values do not change after a cursor is declared. In SQL Server version 6.5 and earlier, variable values are refreshed every time a cursor is reopened.
17 ноя 13, 17:41    [15144114]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
invm
Member

Откуда: Москва
Сообщений: 9825
rsagro
А DEALLOCATE у меня изначально после CLOSE и был, уже потом его вынес за цикл. Попробовал вернуть, не помогло.
Вам внутрь цикла нужно перенести и declare cursor и deallocate.
17 ноя 13, 18:31    [15144241]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31949
invm,

А, вы про этот цикл...
Да, согласен, declare и deallocate нужно внести в цикл.
17 ноя 13, 18:44    [15144272]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
rsagro
Member

Откуда: Новосибирск
Сообщений: 18
Дело оказалось в том, что при переносе в Events из Calendar_Events генерируются новые PK, которые не соответствуют вносимым после этого FK в Calendar_Actions.
Сейчас пытаюсь разобраться как установить между ними соответствие. Наверное надо использовать составной ключ...
17 ноя 13, 19:02    [15144329]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
rsagro
Member

Откуда: Новосибирск
Сообщений: 18
Проблему решил добавлением в таблицу Events внешнего ключа CalendarEventID (*) к таблице Calendar_events (1).
Теперь при INSERT в таблицу events задается строгое соответствие записи в таблице Calendar_events.

Спасибо всем, что откликнулись )

2 invm: хотелось бы узнать, какие всё же ещё методы решения данной задачи есть?

Исходник выкладываю, может кому поможет в будущем.
+
USE [sport]

declare @fromdate datetime = '18.11.2013'
declare @todate datetime = '24.11.2013'
declare @currdate datetime = @fromdate
declare @FacilityID int = 100
declare @counter int = 0
declare @eventcounter int = 0
declare @CurrEventID int 
declare @CurrCalendarEventID int 
declare @DayID int



SET XACT_ABORT ON

BEGIN TRANSACTION

WHILE @currdate <= @todate
BEGIN --начало цикла WHILE (1)
--день недели
SET @DayID = DATEPART(WEEKDAY,@currdate)

	--проверяем отсутствие записей в таблице events на текущую дату
	SET @eventcounter = (select	Count([events].EventID)
	from	[dbo].[events] INNER JOIN [dbo].event_list
			ON ([dbo].[events].EventID = [dbo].[event_list].EventID)
			AND ([event_list].FacilityID = @FacilityID)
	WHERE ActionDate = @currdate)


	--IF 	@counter = 0 AND @eventcounter = 0
	IF 	@eventcounter = 0
		BEGIN --начало блока IF (1)

	--добавляем записи в таблицу events на текущую дату 
insert into [dbo].[events] (EventID, ActionDate, BeginTime, EndTime, Match, CalendarEventID)
(select	[calendar_events].EventID, @currdate AS ActionDate, BeginTime, EndTime, 0 AS Match, [calendar_events].CalendarEventID
	from	[dbo].[calendar_events] INNER JOIN [dbo].event_list
			ON ([dbo].[calendar_events].EventID = [dbo].[event_list].EventID)
			INNER JOIN  [dbo].[facilities]
			ON ([dbo].[facilities].FacilityID = @FacilityID)
	WHERE DayID =DATEPART(WEEKDAY,@currdate)) 

declare EventList cursor GLOBAL  for --создаем курсор
(select CurrEventID, CalendarEventID
from [events]
where ActionDate = @currdate)


	--открываем курсор
	OPEN EventList

	FETCH NEXT FROM EventList INTO @CurrEventID, @CurrCalendarEventID

	WHILE @@FETCH_STATUS = 0
		BEGIN  --Цикл по курсору

	--	SELECT @CurrEventID, @CurrCalendarEventID

	insert into  [dbo].[actions] (CurrEventID, TrackID, GroupID, HeaderID, ContractContact)
	select			@CurrEventID AS CurrEvent, TrackID, GroupID, HeaderID, ContractContact
	from			[dbo].[calendar_actions] 
	WHERE			([calendar_actions].CalendarEventID = @CurrCalendarEventID)

		FETCH NEXT FROM EventList INTO @CurrEventID, @CurrCalendarEventID
		END --Цикл по курсору

	--закрываем курсор
	CLOSE EventList
	DEALLOCATE EventList --уничтожаем курсор

		END --конец блока IF (1)

SET @currdate = DATEADD(DAY,1,@currdate)
END --Конец цикла WHILE (1)

COMMIT TRANSACTION
17 ноя 13, 19:34    [15144429]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
invm
Member

Откуда: Москва
Сообщений: 9825
rsagro
2 invm: хотелось бы узнать, какие всё же ещё методы решения данной задачи есть?
Примерно так:
declare @t table (EventID int, CalendarEventID int);

with x(ActionDate) as
(
 select @fromdate, datepart(weekday, @fromdate) as wd

 union all

 select
  dateadd(day, 1, ActionDate), datepart(weekday, dateadd(day, 1, ActionDate))
 from
  x
 where
  ActionDate <= @todate
),
s as
(
 select
  ce.eventID, x.ActionDate, BeginTime, EndTime, 0 as Match, ce.CalendarEventID
 from
  x join
  dbo.calendar_events ce on ce.DayID = x.wd join
  dbo.event_list el on el.EventID = ce.EventID join
  dbo.facilities f on f.FacilityID = @FacilityID
)
merge into dbo.events t
using s on s.EventID = t.EventID and s.ActionDate = t.ActionDate
when not matched then
 insert
  (EventID, ActionDate, BeginTime, EndTime, Match, CalendarEventID)
 values
  (s.EventID, s.ActionDate, s.BeginTime, s.EndTime, s.Match, s.CalendarEventID)
output
 inserted.EventID, inserted.CalendarEventID into @t (EventID, CalendarEventID);

insert into dbo.Actions 
 (CurrEventID, TrackID, GroupID, HeaderID, ContractContact)
 select
  t.EventID, ca.TrackID, ca.GroupID, ca.HeaderID, ca.ContractContact
 from
  @t t join
  dbo.calendar_actions ca on ca.CalendarEventID = t.CalendarEventID;
Т.к. схему таблиц вы не привели, алиасы в запросах не используете, то понять какой столбец к какой таблице относится невозможно. Поэтому доработывать вам придется самостоятельно .
17 ноя 13, 20:29    [15144598]     Ответить | Цитировать Сообщить модератору
 Re: Не инициализируется курсор, не добавляются данные в таблицу  [new]
rsagro
Member

Откуда: Новосибирск
Сообщений: 18
invm, о спасибо! на досуге поразбираюсь!
18 ноя 13, 08:52    [15146135]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить