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

Может ли быть два одинаковых Primary Key?

2.0 Middle🔥 191 комментариев
#Другое

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

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

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

Может ли быть два одинаковых Primary Key

Краткий ответ: НЕТ. Primary Key должен быть уникальным — это одно из его главных свойств. Попытка вставить дублирующееся значение приведёт к ошибке.

1. Определение Primary Key

Primary Key (первичный ключ) — это колонка или набор колонок, которые:

✓ UNIQUE — каждое значение уникально
✓ NOT NULL — никогда не может быть NULL
✓ IMMUTABLE — не должно изменяться
✓ IDENTIFIES — однозначно идентифицирует строку

2. Попытка вставить дубликат Primary Key

// SQL таблица
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255)
);

// Вставить первую строку
INSERT INTO users (id, email) VALUES (1, 'alice@example.com');
// Успешно ✓

// Попытка вставить строку с тем же id
INSERT INTO users (id, email) VALUES (1, 'bob@example.com');
// Ошибка: Duplicate entry '1' for key 'PRIMARY'
// Невозможно! ✗

3. Пример на Java с Hibernate

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;  // Primary Key
    
    @Column(nullable = false, unique = true)
    private String email;
    
    private String name;
}

// Сервис для сохранения
@Service
public class UserService {
    @Autowired
    private UserRepository repository;
    
    public User createUser(String name, String email) {
        User user = new User();
        user.setName(name);
        user.setEmail(email);
        return repository.save(user); // id генерируется БД
    }
    
    public void tryInsertDuplicate() {
        User user1 = new User();
        user1.setId(1L);
        user1.setName("Alice");
        repository.save(user1); // Успешно
        
        User user2 = new User();
        user2.setId(1L); // Тот же id!
        user2.setName("Bob");
        
        try {
            repository.save(user2);
            // Ошибка: DataIntegrityViolationException
            // Попытка вставить дубликат Primary Key
        } catch (DataIntegrityViolationException e) {
            System.out.println("Ошибка: " + e.getMessage());
        }
    }
}

4. Почему Primary Key должен быть уникальным

Пrimary Key используется для:
1. ИДЕНТИФИКАЦИИ строки — нужна UNIQUE
2. СВЯЗЕЙ между таблицами — Foreign Key ссылается на PRIMARY KEY
3. ИНДЕКСАЦИИ — БД индексирует PRIMARY KEY
4. ПОИСКА — быстрый поиск по PRIMARY KEY

Если бы Primary Key не был уникальным:
- Какую строку вернуть по id? Первую? Все?
- Foreign Key не знал бы на какую строку ссылаться
- Индекс был бы неполезен

5. Ограничение PRIMARY KEY в SQL

-- При создании таблицы
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) NOT NULL
);

-- Эквивалентно:
CREATE TABLE users (
    id BIGINT NOT NULL UNIQUE,
    email VARCHAR(255) NOT NULL
);

-- При попытке добавить дубликат
INSERT INTO users (id, email) VALUES (1, 'test@test.com');
INSERT INTO users (id, email) VALUES (1, 'another@test.com');
-- Error: Duplicate entry '1' for key 'PRIMARY'

6. Составной Primary Key (Composite Key)

-- Таблица заказов (Primary Key = user_id + order_date)
CREATE TABLE orders (
    user_id BIGINT NOT NULL,
    order_date DATE NOT NULL,
    amount DECIMAL(10, 2),
    PRIMARY KEY (user_id, order_date)
);

-- Это ОК — разные пользователи
INSERT INTO orders VALUES (1, '2025-03-15', 100.00);
INSERT INTO orders VALUES (2, '2025-03-15', 150.00); -- Разный user_id ✓

-- Это ОК — один пользователь, разные даты
INSERT INTO orders VALUES (1, '2025-03-16', 200.00); -- Разная дата ✓

-- Это ОШИБКА — дубликат составного ключа
INSERT INTO orders VALUES (1, '2025-03-15', 300.00); -- Ошибка! ✗

7. UUID как Primary Key

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID) // UUID генерируется
    private UUID id;
    
    private String email;
}

// UUID гарантирует уникальность
UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.randomUUID();

System.out.println(uuid1.equals(uuid2)); // false — разные!

// Вероятность коллизии UUID v4: 1 в 5.3 × 10^36
// На практике: невозможно получить дубликат

8. Что отличает PRIMARY KEY от UNIQUE

-- PRIMARY KEY
CREATE TABLE users (
    id BIGINT PRIMARY KEY,        -- NOT NULL + UNIQUE
    email VARCHAR(255)
);

-- UNIQUE KEY
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) UNIQUE     -- Может быть NULL, но если не NULL — уникален
);

-- Различия:
INSERT INTO users VALUES (1, NULL);
INSERT INTO users VALUES (2, NULL); -- ОК! UNIQUE позволяет множество NULL

INSERT INTO users VALUES (3, 'alice@test.com');
INSERT INTO users VALUES (4, 'alice@test.com');
-- Ошибка! UNIQUE не позволяет дубликаты (кроме NULL)

9. Миграция и изменение Primary Key

-- Добавить таблицу с PRIMARY KEY
CREATE TABLE accounts (
    account_id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    balance DECIMAL(10, 2)
);

-- Попытка добавить дубликат PRIMARY KEY
ALTER TABLE accounts ADD CONSTRAINT unique_user_id
    UNIQUE (user_id);

-- Теперь PRIMARY KEY остаётся уникальным
-- UNIQUE (user_id) тоже уникален

10. Обработка PRIMARY KEY в Java/JPA

@Entity
@Table(name = "products")
public class Product {
    @Id
    private Long id; // Primary Key
    
    private String sku;  // Stock Keeping Unit
    private String name;
}

// Репозиторий
public interface ProductRepository extends JpaRepository<Product, Long> {
    Optional<Product> findById(Long id); // Ищет по PRIMARY KEY
}

// Обработка дубликата
@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;
    
    public Product createProduct(Long id, String name) {
        // Проверить перед сохранением
        if (repository.existsById(id)) {
            throw new ProductAlreadyExistsException(id);
        }
        
        Product product = new Product();
        product.setId(id);
        product.setName(name);
        return repository.save(product);
    }
}

Правильный подход

// Генерировать Primary Key автоматически
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// Или использовать UUID
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

// Никогда не устанавливай Primary Key вручную,
// если можно дать БД это делать

Вывод

Primary Key ВСЕГДА уникален. Это основное свойство Primary Key, гарантированное БД на уровне constraints.

Если попытаешься вставить дубликат:

✓ Монолитная БД — ошибка на уровне БД
✓ JPA/Hibernate — DataIntegrityViolationException
✓ Твой код — должен обработать эту ошибку

Всегда проверяй уникальность перед вставкой, или используй INSERT OR UPDATE (UPSERT) операции.

Может ли быть два одинаковых Primary Key? | PrepBro