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

Что такое Primary Key?

2.2 Middle🔥 151 комментариев
#Python Core

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

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

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

Primary Key

Primary Key (первичный ключ) — это столбец или группа столбцов в таблице базы данных, который уникально идентифицирует каждую строку. Это фундаментальное понятие в реляционных базах данных для обеспечения целостности данных и оптимизации поиска.

Характеристики Primary Key

  1. Уникальность — каждое значение должно быть уникальным в таблице
  2. Не может быть NULL — обязательно должно быть значение
  3. Идентификация — однозначно идентифицирует строку
  4. Индексирован — БД автоматически создает индекс для быстрого поиска
  5. Одна на таблицу — максимум один primary key (но может быть составной)

Примеры Primary Key

SQL синтаксис:

-- Простой Primary Key
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100)
);

-- С AUTO_INCREMENT
CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(200),
    content TEXT,
    user_id INT
);

-- Составной Primary Key (несколько столбцов)
CREATE TABLE order_items (
    order_id INT,
    item_id INT,
    quantity INT,
    PRIMARY KEY (order_id, item_id)
);

Primary Key vs Unique Key

ХарактеристикаPrimary KeyUnique Key
УникальностьДаДа
NULL значенияЗапрещеныРазрешены (множество)
ИндексированиеАвтоматическоеДа
Количество на таблицуМаксимум 1Не ограничено
ИспользованиеИдентификацияОграничение дубликатов
CREATE TABLE users (
    id INT PRIMARY KEY,  -- Уникальный идентификатор
    email VARCHAR(100) UNIQUE,  -- Уникальный, но может быть NULL
    phone VARCHAR(20) UNIQUE,
    name VARCHAR(100)
);

Типы Primary Key

1. Natural Primary Key — использует существующий естественно уникальный атрибут:

CREATE TABLE countries (
    iso_code CHAR(2) PRIMARY KEY,  -- Код страны уникален
    name VARCHAR(100),
    population INT
);

2. Surrogate Primary Key — искусственно сгенерированный ключ:

CREATE TABLE products (
    product_id INT AUTO_INCREMENT PRIMARY KEY,  -- Искусственный ID
    sku VARCHAR(100) UNIQUE,
    name VARCHAR(100)
);

3. UUID Primary Key — глобально уникальный идентификатор:

CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(100) UNIQUE,
    name VARCHAR(100)
);

Primary Key в Python/SQLAlchemy

from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    
    # Простой primary key
    id = Column(Integer, primary_key=True)
    email = Column(String(100), unique=True, nullable=False)
    name = Column(String(100))

# Создание таблицы
engine = create_engine('sqlite:///test.db')
Base.metadata.create_all(engine)

Составной Primary Key:

from sqlalchemy import Column, Integer, String, ForeignKey, PrimaryKeyConstraint

class OrderItem(Base):
    __tablename__ = 'order_items'
    
    order_id = Column(Integer, ForeignKey('orders.id'), primary_key=True)
    item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
    quantity = Column(Integer, default=1)
    
    # Альтернативный синтаксис:
    # __table_args__ = (PrimaryKeyConstraint('order_id', 'item_id'),)

UUID Primary Key:

import uuid
from sqlalchemy import Column, UUID

class User(Base):
    __tablename__ = 'users'
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    email = Column(String(100), unique=True)
    name = Column(String(100))

Foreign Key зависит от Primary Key

Primary Key и Foreign Key связаны:

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100)
);

CREATE TABLE posts (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200),
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

В SQLAlchemy:

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(100))
    posts = relationship('Post', back_populates='author')

class Post(Base):
    __tablename__ = 'posts'
    id = Column(Integer, primary_key=True)
    title = Column(String(200))
    user_id = Column(Integer, ForeignKey('users.id'))
    author = relationship('User', back_populates='posts')

Ограничения и best practices

1. Выбор Primary Key:

-- ПЛОХО: Слишком большой
CREATE TABLE users (
    email VARCHAR(255) PRIMARY KEY  -- email может измениться
);

-- ХОРОШО: Маленький, неизменяемый
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(100) UNIQUE
);

2. Не используйте составные ключи без необходимости:

-- ПЛОХО: Слишком сложно для Foreign Keys
CREATE TABLE order_items (
    order_date DATE,
    order_sequence INT,
    item_id INT,
    quantity INT,
    PRIMARY KEY (order_date, order_sequence, item_id)
);

-- ХОРОШО: Простой ID + уникальное ограничение
CREATE TABLE order_items (
    id INT AUTO_INCREMENT PRIMARY KEY,
    order_id INT,
    item_id INT,
    quantity INT,
    UNIQUE(order_id, item_id)
);

3. Primary Key никогда не меняется:

# Плохо:
user.id = 999  # Никогда не меняйте primary key!

# Хорошо: если нужно изменить уникальное значение
user.email = 'newemail@example.com'  # Это OK если есть UNIQUE constraint

Производительность Primary Key

Индекс на Primary Key:

-- Primary Key автоматически индексирован
-- Поиск по ID очень быстрый (B-tree индекс)
SELECT * FROM users WHERE id = 123;  -- O(log n)

-- Vs без индекса
SELECT * FROM users WHERE email = 'test@example.com';  -- O(n) если нет индекса
SELECT * FROM users WHERE email = 'test@example.com' AND email IS UNIQUE;  -- O(log n)

Когда нельзя использовать NULL в Primary Key

-- ОШИБКА: NULL в primary key запрещен
CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(100)  -- Если это NULL, нарушается уникальность
);

INSERT INTO users VALUES (NULL, 'test@example.com');  -- Ошибка!

Итого

Primary Key это:

  • Уникальный идентификатор каждой строки
  • Основа для Foreign Keys и связей между таблицами
  • Автоматически индексируется для быстрого поиска
  • Обязателен в нормальной базе данных (3NF)
  • Никогда не меняется — выбирайте тщательно

Обычно лучший выбор — это маленький числовой AUTO_INCREMENT ID или UUID, а не естественные атрибуты которые могут меняться.

Что такое Primary Key? | PrepBro