← Назад к вопросам

Что должно быть в таблице в базе данных

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) обычны для аудита

Правильная структура таблицы — залог высокой производительности и надёжности приложения!

Что должно быть в таблице в базе данных | PrepBro