Проверка на пересечение периодов дат

Tsql теория > Проверка на пересечение периодов дат
01.04.2013 13:53:34



Статья:

Достаточно часто в разработке возникает задача создать таблицу в которой будут лежать периоды дат (закрытые - без NULL) и необходимо обеспечить ограничениями БД, что бы эти периоды не пересекались.

Решается следуюшим путем, необходимо создать скалярную функцию, которая будет замыкать сама на себя таблицу (self join) и проверять пересеклись ли мы.

Решение стандартное, но почему то все забывают, что у SQL следующий порядок проверок:

1. Проверка ключей (Foreign keys, Unique Keys)

2. Проверка ограничений (Check constraints)

Так что можно чуть оптимизировать данную задачу и проверять сперва повторение периода, через UK, а затем уже проверять ограничения.

Вот код:

CREATE FUNCTION dbo.Check_Period_Intersect ( )
RETURNS BIT
AS 
BEGIN
  RETURN
  CASE WHEN EXISTS ( SELECT *
         FROM   dbo.PERIOD P1
         JOIN   dbo.PERIOD P2 ON P1.period_id <> P2.period_id
         WHERE  P1.[start_date] <= P2.end_date
          AND P1.end_date >= P2.[start_date] ) THEN 1
    ELSE 0
  END
END
GO
 
CREATE TABLE dbo.PERIOD
(
  period_id SMALLINT IDENTITY(1, 1)
      CONSTRAINT PK_PERIOD PRIMARY KEY ,
  [start_date] DATE NOT NULL ,
  end_date DATE NOT NULL
  -- Ограничения таблицы
  CONSTRAINT UK_PERIOD_start_date_end_date UNIQUE ( [start_date], [end_date] )
  CONSTRAINT CK_PERIOD_prevent_intersect_period CHECK ( dbo.Check_Period_Intersect() = 0 )
)
GO