Выражение архитектуры БД на языке SQL.

Имеются следующие отношения:

  • (№ Корта, Время начала, Клиент, Продолжительность) reserves
  • (Название тарифа, Член клуба, № Корта) tariffs
  • (Название тарифа, Цена в час) prices
  • (Клиент, ФИО, Член клуба) clients

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

  • (№ Корта) courts

Дополнительно, поскольку сравнение чисел заведомо быстрее, чем сравнение строк, введем ‘№ Тарифа’, эквивалентный в нашей модели ‘Название тарифа’. Название сохраним там, где оно является первичным ключом (чтобы не повторяться)

Перепишем эти отношения с указанием типов и заодно используем более удобные (для СУБД) названия:

  • reserves:
    • idCourt : INT UNSIGNED
    • startTime : DATETIME
    • idClient : INT UNSIGNED
    • duration : TIME
  • tariffs:
    • idCourt : INT UNSIGNED
    • isMember : BOOL
    • idPrice : INT UNSIGNED
  • prices:
    • id : INT UNSIGNED
    • name : VARCHAR(50)
    • price : DECIMAL(14,4)
  • clients:
    • id : INT UNSIGNED
    • name : VARCHAR(200)
    • isMember : BOOL
  • courts:
    • id : INT UNSIGNED

Жирным обозначены первичные ключи. Курсивом – внешние ключи.

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

CREATE DATABASE IF NOT EXISTS tennis CHARACTER SET UTF8;

USE tennis;

CREATE TABLE courts (
	id INT UNSIGNED NOT NULL,
  PRIMARY KEY (id)
  );

CREATE TABLE clients (
	id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(200) NOT NULL,
  isMember BOOL NOT NULL DEFAULT FALSE,
  PRIMARY KEY (id)
  );

CREATE TABLE prices (
	id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  price DECIMAL(14,4) NOT NULL,
  PRIMARY KEY (id)
  );

CREATE TABLE tariffs (
	idCourt INT UNSIGNED NOT NULL,
  isMember BOOL NOT NULL,
  idPrice INT UNSIGNED NOT NULL,
  PRIMARY KEY (idCourt, isMember),
  INDEX (idCourt),
  INDEX (idPrice),
  FOREIGN KEY (idCourt)
		REFERENCES courts (id)
	    ON DELETE RESTRICT -- Не позволять удалять корт, если на него завязаны тарифы
	    ON UPDATE CASCADE,
	FOREIGN KEY (idPrice)
		REFERENCES prices (id)
	    ON DELETE CASCADE -- При удалении тарифа, удалять так связь с кортами
	    ON UPDATE CASCADE
	);

CREATE TABLE reserves (
  idCourt INT UNSIGNED NOT NULL,
  startTime DATETIME NOT NULL,
  idClient INT UNSIGNED NOT NULL,
  duration TIME NOT NULL,
  PRIMARY KEY (idCourt , startTime),
  INDEX (idCourt),
  INDEX (idClient),
  FOREIGN KEY (idCourt)
      REFERENCES courts (id)
	      ON DELETE RESTRICT -- Не позволять удалять корт, если на него завязаны тарифы
				ON UPDATE CASCADE,
  FOREIGN KEY (idClient)
      REFERENCES clients (id)
	      ON DELETE RESTRICT -- Не позволять удалять клиента, если у него есть резервы
				ON UPDATE CASCADE
	);