UNIQUE в Oracle SQL. Введение
Ограничение UNIQUE в Oracle SQL используется для того, чтобы значения в указанном столбце или комбинации столбцов были уникальными. Это значит, что дубликаты недопустимы. UNIQUE помогает сохранять целостность данных и предотвращает повторное внесение одинаковых значений. В этой статье ты найдёшь 50 практических примеров использования UNIQUE.
🖋️ Синтаксис ограничения UNIQUE
При создании таблицы:
CREATE TABLE users (
user_id NUMBER,
email VARCHAR2(100) UNIQUE
);
Альтернативный синтаксис:
CREATE TABLE users (
user_id NUMBER,
email VARCHAR2(100),
CONSTRAINT uq_email UNIQUE (email)
);
Добавление ограничения к уже существующей таблице:
ALTER TABLE users ADD CONSTRAINT uq_username UNIQUE (username);
🔄 Где используется UNIQUE
- Уникальные email, логины, номера телефонов
- Идентификаторы, не являющиеся первичным ключом
- Комбинации столбцов (составной UNIQUE)
- Временные и архивные таблицы для контроля записей
📊 Примеры использования UNIQUE в Oracle SQL (45 примеров)
- Уникальный email при создании таблицы:
CREATE TABLE clients (
client_id NUMBER,
email VARCHAR2(100) UNIQUE
);
- Добавление ограничения в ALTER:
ALTER TABLE clients ADD CONSTRAINT uq_email UNIQUE (email);
- Проверка ограничения через ALL_CONSTRAINTS:
SELECT constraint_name, table_name FROM user_constraints
WHERE constraint_type = 'U';
- Уникальное ограничение на два столбца:
ALTER TABLE orders ADD CONSTRAINT uq_order_client UNIQUE (order_id, client_id);
- Ошибка при вставке дубликата:
INSERT INTO clients (email) VALUES ('test@mail.com');
-- Повторный INSERT вызовет ORA-00001
- Создание таблицы с несколькими UNIQUE:
CREATE TABLE accounts (
id NUMBER,
username VARCHAR2(50) UNIQUE,
email VARCHAR2(100) UNIQUE
);
- Вставка уникального значения:
INSERT INTO clients (client_id, email) VALUES (1, 'a@b.com');
- Попытка дубликата вызывает ошибку:
-- Это вызовет ORA-00001, если 'a@b.com' уже есть
INSERT INTO clients (client_id, email) VALUES (2, 'a@b.com');
- UNIQUE с именем ограничения:
CREATE TABLE products (
id NUMBER,
sku VARCHAR2(20),
CONSTRAINT uq_sku UNIQUE (sku)
);
- UNIQUE в CREATE TABLE AS SELECT:
CREATE TABLE copy_clients AS SELECT * FROM clients WHERE 1=0;
ALTER TABLE copy_clients ADD CONSTRAINT uq_copy_email UNIQUE (email);
- Проверка наличия уникального ограничения:
SELECT column_name FROM user_cons_columns
WHERE constraint_name = 'UQ_EMAIL';
- Использование составного UNIQUE:
CREATE TABLE seats (
row_num NUMBER,
seat_num NUMBER,
CONSTRAINT uq_seat UNIQUE (row_num, seat_num)
);
- Удаление ограничения UNIQUE:
ALTER TABLE clients DROP CONSTRAINT uq_email;
- Проверка через DBA_CONSTRAINTS:
SELECT * FROM dba_constraints WHERE constraint_type = 'U';
- Уникальность через ALL_CONS_COLUMNS:
SELECT * FROM all_cons_columns WHERE constraint_name = 'UQ_SEAT';
- Слияние таблицы с проверкой UNIQUE:
MERGE INTO clients c
USING dual
ON (c.email = 'unique@domain.com')
WHEN NOT MATCHED THEN
INSERT (client_id, email) VALUES (3, 'unique@domain.com');
- Вставка с проверкой EXISTS:
BEGIN
IF NOT EXISTS (SELECT 1 FROM clients WHERE email = 'new@site.com') THEN
INSERT INTO clients (email) VALUES ('new@site.com');
END IF;
END;
- Уникальность с IGNORE_ROW_ON_DUPKEY_INDEX:
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(clients(email)) */
INTO clients (email) VALUES ('test@site.com');
- UNIQUE в подзапросе (создание временной таблицы):
CREATE TABLE temp_users (
id NUMBER,
login VARCHAR2(30) UNIQUE
);
- Уникальность и логика в представлении:
CREATE VIEW v_clients AS
SELECT DISTINCT email FROM clients;
- Обработка ошибки ORA-00001:
BEGIN
INSERT INTO clients (email) VALUES ('duplicate@domain.com');
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE('Дубликат!');
END;
- Использование в PL/SQL процедуры:
PROCEDURE add_user(p_email VARCHAR2) IS
BEGIN
INSERT INTO clients (email) VALUES (p_email);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN NULL;
END;
- Проверка наличия значения перед вставкой:
IF NOT EXISTS (SELECT 1 FROM clients WHERE email = 'mail@host.com') THEN
INSERT INTO clients (email) VALUES ('mail@host.com');
END IF;
- Уникальность с NULL (NULL считается уникальным):
INSERT INTO clients (email) VALUES (NULL); -- допустимо
INSERT INTO clients (email) VALUES (NULL); -- также допустимо
- Сравнение с PRIMARY KEY:
-- PRIMARY KEY = NOT NULL + UNIQUE
-- UNIQUE = допускает NULL
- Создание временной таблицы с UNIQUE:
CREATE GLOBAL TEMPORARY TABLE tmp_users (
id NUMBER,
username VARCHAR2(30) UNIQUE
) ON COMMIT DELETE ROWS;
- Создание MATERIALIZED VIEW с UNIQUE:
CREATE MATERIALIZED VIEW mv_clients
BUILD IMMEDIATE AS SELECT DISTINCT email FROM clients;
- Использование UNIQUE в логике авторизации:
SELECT COUNT(*) FROM users WHERE login = 'john'; -- ожидается 0 или 1
- Уникальность через ASSERT:
-- Псевдокод
ASSERT(SELECT COUNT(*) FROM users WHERE email = 'x') <= 1;
- Уникальность с внешним ключом:
CREATE TABLE profiles (
profile_id NUMBER PRIMARY KEY,
user_id NUMBER,
CONSTRAINT uq_profile_user UNIQUE (user_id)
);
- Проверка уникального индекса:
SELECT * FROM user_indexes WHERE uniqueness = 'UNIQUE';
- Имя ограничения и индекс:
-- Oracle создаёт индекс под капотом
-- Имя можно задать вручную
- Автоматическая генерация уникального логина:
INSERT INTO users (login)
SELECT 'user_' || TO_CHAR(SYSDATE, 'HH24MISS') FROM dual
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE login = 'user_' || TO_CHAR(SYSDATE, 'HH24MISS')
);
- Использование CREATE INDEX для UNIQUE:
CREATE UNIQUE INDEX idx_unique_email ON clients (email);
- Импорт данных с проверкой UNIQUE:
-- Через внешние таблицы или SQL*Loader с контрольным флагом
- Использование в тестировании:
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO test_table (val) VALUES (''unique'')';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
- Отображение всех уникальных ограничений:
SELECT * FROM user_constraints WHERE constraint_type = 'U';
- UNIQUE в фильтре EXISTS:
SELECT * FROM clients c
WHERE EXISTS (
SELECT 1 FROM dual WHERE c.email IS NOT NULL
);
- Уникальность через NOT EXISTS:
INSERT INTO clients (email)
SELECT 'x@domain.com' FROM dual
WHERE NOT EXISTS (SELECT 1 FROM clients WHERE email = 'x@domain.com');
- Проверка количества уникальных email:
SELECT COUNT(DISTINCT email) FROM clients;
- Вложенный SELECT с UNIQUE:
SELECT * FROM (
SELECT DISTINCT email FROM clients
) WHERE ROWNUM <= 10;
- Удаление дубликатов:
DELETE FROM clients c
WHERE ROWID NOT IN (
SELECT MIN(ROWID) FROM clients GROUP BY email
);
- Преобразование таблицы с дубликатами в уникальную:
CREATE TABLE clients_clean AS
SELECT email FROM clients GROUP BY email;
- Защита логики авторизации:
-- Один email = один пользователь
-- UNIQUE обязательно
- Создание уникальной последовательности действий:
INSERT INTO action_log (action_id, email)
VALUES (action_seq.NEXTVAL, 'unique@domain.com');
📆 Заключение: зачем использовать UNIQUE в Oracle SQL
Ограничение UNIQUE — важный инструмент контроля данных. Оно предотвращает дубликаты в ключевых столбцах и обеспечивает надежную логику идентификации записей. UNIQUE повышает доверие к данным и упрощает поддержку системы.
Применяя его, ты гарантируешь, что важные атрибуты (email, код, логин) будут уникальны, как и должны быть в реальности.
🕸️ Следующая статья:
UID в Oracle SQL — как получить идентификатор пользователя