Проверка уникальности UUID при добавлении в таблицу
Вопрос на тему хорошей практики в программировании:
Необходимо вставить запись в таблицу первичным ключом которой является UUID. Значение UUID даёт UUID.randomUUID. Пишут, что значения UUID невероятно уникальный.
Так вот...
- При таких начальных данных необходимо ли перед вставкой проверять есть ли в таблице запись с полученным UUID (как говорится раз в год и палка стреляет) или же UUID действительно достаточно уникален, что бы этого не делать.
- Если проверять необходимо, то как это правильно реализовать? т.е., например, некий бесконечный цикл, который прерывается, если записи с таким UUID не найдено в БД или как-то иначе (мозолит глаз вроде и невероятная, но теоретическая возможность зависнуть в цикле)?
Интересно, как подобное обычно грамотно оформляется на практике.
Ответы (3 шт):
- GUID - это глобальный уникальный идентификатор.
- Вы можете создать UNIQUE индекс для этого столбца в базе данных. Индекс PK делает то же самое. Это предотвратит вставку неуникального значения, GUID или нет.
Необходимо вставить запись в таблицу первичным ключом которой является UUID.
Всё. Больше ничего не нужно. Если представить себе тот невероятный случай, что сгенерированный UUID уже присутствует в таблице, вставить запись с ним всё равно не удастся. На то и первичный ключ - при попытке вставки дубликата возникнет ошибка дублирования.
А то, что ошибки следует перехватывать и обрабатывать (мало ли что), по-моему, очевидно...
[...] необходимо ли перед вставкой проверять, есть ли в таблице запись с полученным UUID?
Всегда надо проверять. И реализуется это так:
create table tab (uuid raw (16) primary key)
/
Тем самым дав указание БД: "перед вставкой проверь по уникальному индексу, созданому для первичного ключа, есть ли уже запись с этим UUID, если да, то вставку делать не надо, а вместо неё - вызови исключение с ошибкой".
как говорится раз в год и палка стреляет
Чтобы не ждать где-то 12 милионов лет, пока "выстрелит", добавил ещё одну вставку с последним UUID, т.е симулирую коллизию UUID, полученное при этом исключение следует обработать:
create or replace and compile java source named UuidInsert as
import java.sql.*;
import java.util.UUID;
public class UuidInsert
{
static PreparedStatement ps = null;
public static void exec (int rows) throws SQLException {
try {
Connection conn = DriverManager.getConnection ("jdbc:default:connection:");
ps = conn.prepareStatement ("insert into tab (uuid) values (hextoraw (?))");
for (int i = 0; i < rows; i++) {
ps.setString (1, UUID.randomUUID ().toString().replaceAll("-", ""));
ps.executeUpdate ();
}
ps.executeUpdate (); /*** коллизия UUID */
} catch (SQLException e) {
e.printStackTrace();
} finally { if (ps != null) ps.close(); }
}
}
/
create or replace procedure UuidInsert (rows number)
as language java name 'UuidInsert.exec (int)';
/
100 вставок + 1 последняя вставка с повторным UUID:
exec UuidInsert (100)
java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (ME.SYS_C0011488) violated
select uuid from tab
/
UUID
--------------------------------
[...]
16725295ED124B4B88760551FB5A262E
100 rows selected.