Как определить первичный ключ таблицы
Что проверяют
Два вопроса в одном: понимаете ли вы, что такое первичный ключ, и умеете ли быстро найти его в незнакомой базе, чтобы писать проверки и готовить тестовые данные. Следом часто спрашивают про отличие от уникального и внешнего ключа или просят найти дубли в таблице без ключа.
Как отвечать
Коротко про свойства: первичный ключ однозначно определяет строку, он уникален и не бывает NULL, в таблице он один, но может состоять из нескольких колонок. Бывает суррогатным (id через IDENTITY, SERIAL или UUID) и естественным (ИНН, номер договора). В рабочих системах чаще суррогатный: естественные значения со временем меняются.
Как найти ключ в существующей таблице:
- GUI-клиент: в DBeaver или DataGrip ключевые колонки помечены значком ключа, ограничения видны в свойствах таблицы;
- PostgreSQL: в
psqlкоманда\d ordersвыводит строку вида"orders_pkey" PRIMARY KEY, btree (id); - MySQL:
SHOW KEYS FROM orders WHERE Key_name = 'PRIMARY'; - универсально:
information_schema.table_constraintsсconstraint_type = 'PRIMARY KEY', соединённая сkey_column_usageпо имени ограничения.
Если ключа нет, кандидата проверяют запросом SELECT a, b, COUNT(*) FROM t GROUP BY a, b HAVING COUNT(*) > 1. Пустой результат на текущих данных ещё не доказательство, но непустой сразу отвергает вариант.
Что тестировщик проверяет вокруг ключа: вставка дубля отклоняется (в PostgreSQL ошибка 23505, unique_violation), NULL в ключ не пишется, удаление родителя ведёт себя по правилу внешнего ключа (RESTRICT или CASCADE), а API на дубль отвечает понятной ошибкой вроде 409, а не 500.
Где спотыкаются
Считают, что колонка id и есть первичный ключ. Бывает, что ограничения нет вовсе, уникальность держится только на коде приложения, а дубли уже лежат в базе.
Путают первичный ключ с уникальным. UNIQUE в PostgreSQL по умолчанию допускает несколько NULL, и таких ограничений на таблице может быть сколько угодно.
В составном ключе проверяют уникальность каждой колонки отдельно, хотя уникальной должна быть только их комбинация.