Postgres Есть ли способ создать внешний ключ даты, который ссылается на диапазон дат в другой таблице? - PullRequest
4 голосов
/ 10 декабря 2010

Предполагая, что у нас есть две таблицы следующим образом

CREATE TABLE calendar_month (  
  id serial PRIMARY KEY,  
  start_date date NOT NULL,  
  end_date date NOT NULL,  
  reporting_month character varying(50) NOT NULL
);

CREATE TABLE calendar (    
  id serial PRIMARY KEY,  
  holiday bool NOT NULL,  
  actual_date date NOT NULL  
);

Не прибегая к триггерам, есть ли способ убедиться, что любая фактическая_дата, введенная в таблицу календаря, всегда имеет соответствующий отчет__месяц в таблице calendar_month, что она можетсм?

Ответы [ 3 ]

6 голосов
/ 10 декабря 2010

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

CREATE TABLE calendar_month (  
  id serial PRIMARY KEY, 
  start_date date NOT NULL UNIQUE,  
  end_date date NOT NULL,  
  reporting_month character varying(50) NOT NULL
);

CREATE TABLE calendar (    
  id serial PRIMARY KEY,  
  month_start_date date NOT NULL REFERENCES calendar_month(start_date),
  holiday bool NOT NULL,  
  actual_date date NOT NULL CHECK ( 
    actual_date>=month_start_date and
    actual_date<(month_start_date+'1 month'::interval)::date)
);

РЕДАКТИРОВАТЬ: Мохан сказал, что «конечная дата в строке календаря не обязательно будет= дата начала + интервал 1 месяц ".Предположим, что мы не можем делать какие-либо предположения относительно фактической даты начала и окончания месяца, нам нужно сделать что-то немного (как предлагает сам Мохан):

CREATE TABLE calendar_month (  
  id serial PRIMARY KEY, 
  start_date date NOT NULL,  
  end_date date NOT NULL,  
  reporting_month character varying(50) NOT NULL,
  UNIQUE(start_date, end_date)
);

CREATE TABLE calendar (    
  id serial PRIMARY KEY,  
  month_start_date date NOT NULL,
  month_end_date date NOT NULL,
  holiday bool NOT NULL,
  foreign key(month_start_date, month_end_date) 
    REFERENCES calendar_month(start_date, end_date) )  
  actual_date date NOT NULL 
    CHECK (actual_date>=month_start_date and actual_date<month_end_date)
);

Или, возможно, actual_date<month_end_date должно быть actual_date<=month_end_date в ограничении check - это зависит от того, как вы определяете границы месяца.

1 голос
/ 12 декабря 2010

Если ваш calendar_month начинается в первый день месяца (что может показаться логичным):

CREATE TABLE calendar_month (  
  start_date DATE PRIMARY KEY CHECK( start_date = date_trunc( 'month', start_date )),
  reporting_month TEXT NOT NULL
);

INSERT INTO calendar_month( start_date, reporting_month ) VALUES
 ('2010-01-01','january 2010'),
 ('2010-02-01','february 2010');

CREATE TABLE calendar (    
  id serial PRIMARY KEY,  
  month_date DATE NOT NULL REFERENCES calendar_month(start_date),
  actual_date DATE NOT NULL CHECK ( month_date = date_trunc( 'month', actual_date ) )
);

CREATE OR REPLACE FUNCTION calendar_default_trigger_f() RETURNS trigger AS $$
BEGIN 
    NEW.month_date = date_trunc( 'month', NEW.actual_date );
    RETURN NEW;
END
$$ LANGUAGE plpgsql;

CREATE TRIGGER calendar_default_trigger BEFORE INSERT OR UPDATE ON calendar
  FOR EACH ROW EXECUTE PROCEDURE calendar_default_trigger_f();

INSERT INTO calendar (actual_date) VALUES ('2010-01-12'),('2010-01-31'),('2010-02-28');

test=> SELECT * FROM calendar;
 id | month_date | actual_date 
----+------------+-------------
  2 | 2010-01-01 | 2010-01-12
  3 | 2010-01-01 | 2010-01-31
  4 | 2010-02-01 | 2010-02-28

INSERT INTO calendar (actual_date) VALUES ('2010-04-12');

ERREUR:  une instruction insert ou update sur la table « calendar » viole la contrainte de clé
étrangère « calendar_month_date_fkey »
DÉTAIL : La clé (month_date)=(2010-04-01) n'est pas présente dans la table « calendar_month ».

Используется триггер, но это только для удобства.Фактическая проверка выполняется внешними ключами.

1 голос
/ 10 декабря 2010

Нет:

  • Внешние ключи не позволяют изменять тип данных перед сравнением
  • проверка ограничений применяется только к той же таблице, но не к другим

Триггер - ваш единственный вариант, основанный на предоставленных инструкциях CREATE TABLE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...