2015-03-20 3 views
1

У меня есть две таблицы на MSSQL (2012) DB («tblA» и «tblB»). После вставки на «tblA» мне нужен триггер для автогенерации на «tblB» записей с датами между STARTDATE и ENDDATE из «tblA», но только в будние дни, выбранные на «tblA»sql trigger daterange с будними днями

например, на «tblA»:

tblA_ID: 99 
CAT: TEXT1 
STARTDATE: 01/01/2015 
ENDDATE: 31/01/2015 
MONDAY: true 
TUESDAY: false 
WEDNESDAY: false 
THURSDAY: false 
FRIDAY: true 
SATURDAY: false 
SUNDAY: false 

"TBLB" должен получить

1 99 TEXT1 02/01/2015 (=Friday) 
2 99 TEXT1 04/01/2015 (=Monday) 
3 99 TEXT1 09/01/2015 (=Friday) 
4 99 TEXT1 11/01/2015 (=Monday) 
5 99 TEXT1 16/01/2015 (=Friday) 
6 99 TEXT1 28/01/2015 (=Monday) 
7 99 TEXT1 23/01/2015 (=Friday) 
8 99 TEXT1 25/01/2015 (=Monday) 
9 99 TEXT1 30/01/2015 (=Friday) 




    CREATE TABLE [dbo].[tblA] 
(
    [tblA_ID] INT NOT NULL IDENTITY, 
    [tblA_CAT] NVARCHAR(50) NULL, 
    [tblA_STARTDATE] DATE NULL, 
    [tblA_ENDDATE] DATE NULL, 
    [tblA_MONDAY] BIT NULL, 
    [tblA_TUESDAY] BIT NULL, 
    [tblA_WEDNESDAY] BIT NULL, 
    [tblA_THURSDAY] BIT NULL, 
    [tblA_FRIDAY] BIT NULL, 
    [tblA_SATURDAY] BIT NULL, 
    [tblA_SUNDAY] BIT NULL, 
    CONSTRAINT [PK_tblA] PRIMARY KEY ([tblA_ID]), 
) 

CREATE TABLE [dbo].[tblB] 
(
    [tblB_ID] INT NOT NULL IDENTITY, 
    [tblA_ID] INT NOT NULL, 
    [tblB_CAT] NVARCHAR(50) NULL, 
    [tblB_DATE] DATE NULL, 
    CONSTRAINT [PK_tblB] PRIMARY KEY ([tblB_ID]), 
) 
+0

Какие dbms? (Большинство продуктов dbms имеют свои собственные реализации триггеров ... и дату/время ...) – jarlh

+0

используя ** MSSQL 2012 ** – RMU

ответ

0

Этот триггер должен работать для вас. Он использует рекурсивное общее табличное выражение для генерации всех значений tblB_DATE в диапазоне, а затем выражение case, чтобы проверить, совпадает ли имя дня с именем, помеченным как true. Обратите внимание, что эта часть зависит от системного языка, поэтому, если вы не используете английский язык, вам нужно настроить литералы имени даты в соответствии с вашим конкретным языком.

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

Пожалуйста, также помните, что код не содержит ошибок и не оптимизирован и, вероятно, может быть улучшен. Это должно дать вам представление о том, как вы можете решить свою проблему.

CREATE TRIGGER ins_tblb ON [dbo].[tblA] AFTER INSERT AS 
BEGIN 

    WITH dates AS (
     SELECT 
      tblA_ID, tbla_CAT, tbla_STARTDATE, tbla_ENDDATE, 
      tbla_MONDAY, tbla_TUESDAY, tbla_WEDNESDAY, tbla_THURSDAY, 
      tbla_FRIDAY, tbla_SATURDAY, tbla_SUNDAY, 
      tblA_STARTDATE tblB_DATE 
     FROM inserted 
     UNION ALL 
     SELECT tblA_ID, tbla_CAT, tbla_STARTDATE, tbla_ENDDATE, 
      tbla_MONDAY, tbla_TUESDAY, tbla_WEDNESDAY, tbla_THURSDAY, 
      tbla_FRIDAY, tbla_SATURDAY, tbla_SUNDAY, 
      DATEADD(DAY, 1, tblB_DATE) tblB_DATE 
     FROM dates 
     WHERE dates.tblB_DATE <= tblA_ENDDATE 
    ) 

    INSERT tblB (tblA_ID, tblB_CAT, tblB_DATE) 
    SELECT tblA_ID, tblA_CAT, tblB_DATE 
    FROM dates 
    WHERE DATENAME(DW,tblB_DATE) IN (
     CASE WHEN tblA_MONDAY = 1 
      THEN N'Monday' END, 
     CASE WHEN tblA_TUESDAY = 1 
      THEN N'Tuesday' END, 
     CASE WHEN tblA_WEDNESDAY = 1 
      THEN N'Wednesday' END, 
     CASE WHEN tblA_THURSDAY = 1 
      THEN N'Thursday' END, 
     CASE WHEN tblA_FRIDAY = 1 
      THEN N'Friday' END, 
     CASE WHEN tblA_SATURDAY = 1 
      THEN N'Saturday' END, 
     CASE WHEN tblA_SUNDAY = 1 
      THEN N'Sunday' END 
    ) 

    ORDER BY tblA_ID, tblB_DATE 
    OPTION (MAXRECURSION 0) 
END 
+0

thats ** удивительный **. Я искал это месяц. Могу ли я спросить, как это сделать, если разница между Startdate и enddate больше 30 дней. Например: tblA_ID: 99 КПП: ТЕКСТ1 STARTDATE: 01/01/2015 ENDDATE: 31.12.2015 Понедельник: истинно Вторник: ложные среда: ложные четверг: ложные пятницой: истинно субботу: ложные SUNDAY: false – RMU

+0

@RMU Я изменю его, чтобы обрабатывать более длинные диапазоны; Я думал, что это так, но я думаю, что я не испытывал этого достаточно. – jpw

+0

@RMU Я изменил способ работы кода и заменил конструкцию значений на рекурсивный cte. Он должен работать так, как вы хотите. – jpw