How I can define this constraint?

℡╲_俬逩灬. 提交于 2020-03-23 14:32:53

问题


I am designing a database for a parking lot in Postgres. I need to define a constraint (or similar) to verify the Id_Lot in Ticket is empty in the table "Lot".

How I can do it?

The relevant tables are:

Ticket:

"Id_Ticket"         serial PRIMARY KEY,
"Date_Entrance"     date NOT NULL,
"Time_Entrance"     time without time zone NOT NULL,
"License_plate"     varchar(6) NOT NULL references "Vehicle"("L_Plate"), 
"Id_Lot"            varchar(4) NOT NULL references "Lot"("Code")

Lot:

"Code"              varchar(4) NOT NULL PRIMARY KEY,
"Type"              varchar(5) NOT NULL,
"Empty"             boolean NOT NULL

回答1:


Solution for what you ask

Assuming you want to enforce that:

  1. "Id_Lot" actually exists in "Lot"."Code". -> FK constraint
  2. "Lot"."Empty" for the spot is TRUE at the time of the check only.

You could do this with a NOT VALID CHECK constraint using a fake IMMUTABLE function to check on the other table. Details:

  • Disable all constraints and table checks while restoring a dump

But your data model is shaky in a number of aspects. I would suggest a much cleaner approach.

Cleaner design with exclusion constraint

Don't store whether a lot is currently empty redundantly with the lot. That's very error prone and susceptible to concurrency issues. Enforce that each lot can only be taken once at a time with an exclusion constraint. For that to work, save the time of exit in ticket, additionally.

CREATE TABLE lot (
  lot_id   varchar(4) NOT NULL PRIMARY KEY  -- I would use integer if possible
, lot_type text NOT NULL
);

No redundant current state in the lot table.

For the exclusion constraint to work, you need the additional module btree_gist. Detailed instructions:

  • 'one-to-many' relation integrity issue for time ranges
  • Store the day of the week and time?

CREATE TABLE ticket (
  ticket_id  serial PRIMARY KEY
, during     tsrange NOT NULL
, license_plate text NOT NULL REFERENCES "Vehicle"("L_Plate"),
, lot_id     int NOT NULL REFERENCES  lot
, CONSTRAINT lot_uni_ticket EXCLUDE USING gist (lot_id WITH =, during WITH &&)
, CONSTRAINT during_lower_bound_not_null CHECK (NOT lower_inf(during))
, CONSTRAINT during_bounds CHECK (lower_inc(during) AND NOT upper_inc(during))
);
  • Using a timestamp range data type tsrange for the parking duration during. Enter with upper bound NULL, when the car enters. Update with upper bound when the car exits. Among other things, this also makes it possible for cars to park multiple days.

  • Some additional CHECK constraints to enforce basic rules on during:

    • Inclusive lower bound, exclusive upper bound to stay consistent.
    • The lower bound (entrance) can never be missing.
      • PostgreSQL tsrange: is it correct for lower_inf('(-infinity,today)'::tsrange) to be false?

Related:

  • How to find first free start times from reservations in Postgres


来源:https://stackoverflow.com/questions/27337614/how-i-can-define-this-constraint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!