← Назад к вопросам
Что должно быть в таблице в базе данных
2.0 Middle🔥 151 комментариев
#Stream API и функциональное программирование#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Структура таблицы в базе данных
Таблица — это основная структура реляционной БД, организованная в виде строк и столбцов. Правильное проектирование таблицы — основа надёжного приложения.
Обязательные компоненты таблицы
1. Первичный ключ (Primary Key)
Первичный ключ — уникальный идентификатор каждой строки. Без него нельзя гарантировать уникальность данных.
// SQL
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100)
);
// Java JPA
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // Первичный ключ
@Column(nullable = false, unique = true)
private String email;
private String name;
}
2. Колонки (Columns) с типами данных
Каждый столбец должен иметь определённый тип данных:
// Таблица заказов
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
total_amount DECIMAL(10, 2), // деньги
quantity INT, // целое число
description TEXT, // длинный текст
created_at TIMESTAMP, // дата/время
is_active BOOLEAN DEFAULT TRUE // флаг
);
// Соответствующий класс в Java
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private Long userId;
@Column(precision = 10, scale = 2)
private BigDecimal totalAmount;
private Integer quantity;
@Column(columnDefinition = "TEXT")
private String description;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "is_active")
private Boolean isActive = true;
}
3. Ограничения (Constraints)
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL, // NOT NULL
price DECIMAL(10, 2) NOT NULL, // обязательное
sku VARCHAR(50) UNIQUE, // UNIQUE
category_id BIGINT NOT NULL, // FOREIGN KEY
stock INT DEFAULT 0, // DEFAULT
CHECK (price > 0), // CHECK
FOREIGN KEY (category_id) REFERENCES categories(id)
);
@Entity
@Table(name = "products", uniqueConstraints = {
@UniqueConstraint(columnNames = "sku"),
@UniqueConstraint(columnNames = {"name", "category_id"})
})
public class Product {
@Id
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
@Positive // проверка на уровне приложения
private BigDecimal price;
@Column(unique = true)
private String sku;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id", nullable = false)
private Category category;
@Column(columnDefinition = "INT DEFAULT 0")
private Integer stock;
}
4. Внешние ключи (Foreign Keys)
Связывают таблицы между собой и обеспечивают ссылочную целостность:
// Таблица пользователей
CREATE TABLE customers (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
);
// Таблица заказов со внешним ключом на customers
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
customer_id BIGINT NOT NULL,
order_date TIMESTAMP,
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
// Java с JPA
@Entity
public class Customer {
@Id
private Long id;
private String name;
private String email;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private List<Order> orders = new ArrayList<>();
}
@Entity
public class Order {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;
private LocalDateTime orderDate;
}
5. Индексы (Indexes)
Индексы — улучшают быстроту поиска, но замедляют вставку/обновление:
CREATE TABLE users (
id BIGINT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100),
age INT,
INDEX idx_age (age), // индекс по age
INDEX idx_email_name (email, name) // составной индекс
);
// Java
@Entity
@Table(name = "users", indexes = {
@Index(name = "idx_age", columnList = "age"),
@Index(name = "idx_email_name", columnList = "email,name")
})
public class User {
@Id
private Long id;
@Column(unique = true) // автоматически создаёт индекс
private String email;
private String name;
private Integer age;
}
6. Системные колонки
CREATE TABLE posts (
id BIGINT PRIMARY KEY,
title VARCHAR(255),
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at TIMESTAMP NULL -- для мягкого удаления
);
@Entity
@Table(name = "posts")
@EntityListeners(AuditingEntityListener.class)
public class Post {
@Id
private Long id;
private String title;
private String content;
@CreationTimestamp
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(nullable = false)
private LocalDateTime updatedAt;
@Column(name = "deleted_at")
private LocalDateTime deletedAt; // для soft delete
}
Хороший пример полной таблицы
// SQL
CREATE TABLE articles (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
author_id BIGINT NOT NULL,
title VARCHAR(500) NOT NULL,
slug VARCHAR(500) NOT NULL UNIQUE,
content LONGTEXT NOT NULL,
status ENUM(DRAFT, PUBLISHED, ARCHIVED) DEFAULT DRAFT,
view_count INT DEFAULT 0,
like_count INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
published_at TIMESTAMP NULL,
FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_author (author_id),
INDEX idx_status (status),
INDEX idx_created (created_at)
);
// Java
@Entity
@Table(name = "articles", indexes = {
@Index(name = "idx_author", columnList = "author_id"),
@Index(name = "idx_status", columnList = "status"),
@Index(name = "idx_created", columnList = "created_at")
})
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id", nullable = false)
private User author;
@Column(nullable = false, length = 500)
private String title;
@Column(nullable = false, unique = true, length = 500)
private String slug;
@Column(nullable = false, columnDefinition = "LONGTEXT")
private String content;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private ArticleStatus status = ArticleStatus.DRAFT;
@Column(columnDefinition = "INT DEFAULT 0")
private Integer viewCount;
@Column(columnDefinition = "INT DEFAULT 0")
private Integer likeCount;
@CreationTimestamp
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(nullable = false)
private LocalDateTime updatedAt;
private LocalDateTime publishedAt;
}
Нормализация данных
Первая нормальная форма (1NF):
- Все значения атомарные (неделимые)
Вторая нормальная форма (2NF):
- Все атрибуты зависят от первичного ключа целиком
Третья нормальная форма (3NF):
- Нет транзитивных зависимостей
// ❌ Плохо — нарушение 1NF
CREATE TABLE authors (
id INT PRIMARY KEY,
name VARCHAR(100),
phone_numbers VARCHAR(500) // несколько номеров в одной ячейке!
);
// ✅ Хорошо — нормализовано
CREATE TABLE authors (
id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE author_phones (
id INT PRIMARY KEY,
author_id INT NOT NULL,
phone_number VARCHAR(20),
FOREIGN KEY (author_id) REFERENCES authors(id)
);
Ключевые выводы
- Первичный ключ обязателен для уникальности
- Типизированные колонки предотвращают ошибки
- Ограничения защищают целостность данных
- Внешние ключи связывают таблицы
- Индексы ускоряют чтение, но замедляют запись
- Нормализация избегает дублирования
- Системные поля (created_at, updated_at) обычны для аудита
Правильная структура таблицы — залог высокой производительности и надёжности приложения!