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

Что такое первая нормальная форма базы данных?

2.0 Middle🔥 141 комментариев
#Базы данных (SQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Первая нормальная форма (1NF) — Атомарность данных

Первая нормальная форма (1NF) — это основной уровень нормализации БД, который требует, чтобы все значения в таблице были атомарными (неделимыми).

Основное правило 1NF

  1. Каждая ячейка таблицы должна содержать одно значение, а не список или составной тип
  2. Не должно быть повторяющихся групп данных
  3. Каждый столбец должен содержать только одно значение одного типа данных
  4. Должен быть первичный ключ для уникальной идентификации строк

Пример: Нарушение 1NF

-- ❌ ПЛОХО: нарушает 1NF
CREATE TABLE students (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    phone VARCHAR(100),  -- Может содержать несколько номеров: '123-456, 789-101'
    skills VARCHAR(255)   -- Может содержать список: 'Python, Java, JavaScript'
);

-- Данные
INSERT INTO students VALUES
(1, 'Алиса', '123-456, 789-101', 'Python, Java, JavaScript'),
(2, 'Боб', '555-1234', 'C++, Rust');

Проблемы:

  • Сложно искать студентов с телефоном 123-456
  • Сложно найти всех, кто знает Python
  • Сложно добавить один навык студенту
  • Сложно удалить один навык

Решение: Соответствие 1NF

-- ✅ ХОРОШО: соответствует 1NF
CREATE TABLE students (
    id INT PRIMARY KEY,
    name VARCHAR(100)
);

CREATE TABLE phones (
    id INT PRIMARY KEY,
    student_id INT,
    phone VARCHAR(15),
    FOREIGN KEY (student_id) REFERENCES students(id)
);

CREATE TABLE skills (
    id INT PRIMARY KEY,
    student_id INT,
    skill VARCHAR(50),
    FOREIGN KEY (student_id) REFERENCES students(id)
);

-- Данные
INSERT INTO students VALUES (1, 'Алиса'), (2, 'Боб');
INSERT INTO phones VALUES (1, 1, '123-456'), (2, 1, '789-101'), (3, 2, '555-1234');
INSERT INTO skills VALUES (1, 1, 'Python'), (2, 1, 'Java'), (3, 1, 'JavaScript'), (4, 2, 'C++'), (5, 2, 'Rust');

Пример с использованием Python + SQLAlchemy

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()

# ❌ Нарушение 1NF (использовать НЕ нужно)
class StudentBad(Base):
    __tablename__ = 'students_bad'
    
    id = Column(Integer, primary_key=True)
    name = Column(String)
    phone = Column(String)  # Может быть '123, 456, 789'
    skills = Column(String)  # Может быть 'Python, Java, JavaScript'

# ✅ Соответствие 1NF
class Student(Base):
    __tablename__ = 'students'
    
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    
    phones = relationship('Phone', back_populates='student')
    skills_rel = relationship('StudentSkill', back_populates='student')

class Phone(Base):
    __tablename__ = 'phones'
    
    id = Column(Integer, primary_key=True)
    student_id = Column(Integer, ForeignKey('students.id'))
    phone = Column(String, nullable=False)
    
    student = relationship('Student', back_populates='phones')

class StudentSkill(Base):
    __tablename__ = 'student_skills'
    
    id = Column(Integer, primary_key=True)
    student_id = Column(Integer, ForeignKey('students.id'))
    skill = Column(String, nullable=False)
    
    student = relationship('Student', back_populates='skills_rel')

Практические примеры нарушений 1NF

Пример 1: Адреса

-- ❌ ПЛОХО
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    address VARCHAR(255)  -- '123 Main St, New York, NY 10001, USA'
);

-- ✅ ХОРОШО
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100)
);

CREATE TABLE addresses (
    id INT PRIMARY KEY,
    user_id INT,
    street VARCHAR(100),
    city VARCHAR(50),
    state VARCHAR(50),
    zip VARCHAR(10),
    country VARCHAR(50),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

Пример 2: Теги

-- ❌ ПЛОХО
CREATE TABLE posts (
    id INT PRIMARY KEY,
    title VARCHAR(255),
    tags VARCHAR(255)  -- 'python, django, web-development'
);

-- ✅ ХОРОШО
CREATE TABLE posts (
    id INT PRIMARY KEY,
    title VARCHAR(255)
);

CREATE TABLE tags (
    id INT PRIMARY KEY,
    name VARCHAR(100) UNIQUE
);

CREATE TABLE post_tags (
    post_id INT,
    tag_id INT,
    PRIMARY KEY (post_id, tag_id),
    FOREIGN KEY (post_id) REFERENCES posts(id),
    FOREIGN KEY (tag_id) REFERENCES tags(id)
);

Преимущества 1NF

  1. Легче искать данные: SELECT * FROM skills WHERE skill = 'Python'
  2. Легче обновлять: Изменить один навык без влияния на другие
  3. Легче удалять: Удалить один телефон без удаления студента
  4. Нет дублирования: Студента нужно вводить один раз
  5. Целостность данных: FOREIGN KEY обеспечивает консистентность

На интервью

Ответи так:

"Первая нормальная форма требует, чтобы каждая ячейка таблицы содержала одно атомарное значение, а не список или составной тип. Например, вместо хранения 'Python, Java, JavaScript' в одной колонке, нужно создать отдельную таблицу skills и связать её через внешний ключ. Это избегает дублирования, упрощает запросы и гарантирует целостность данных."

Что такое первая нормальная форма базы данных? | PrepBro