Проверка уникальности UUID при добавлении в таблицу

Вопрос на тему хорошей практики в программировании:

Необходимо вставить запись в таблицу первичным ключом которой является UUID. Значение UUID даёт UUID.randomUUID. Пишут, что значения UUID невероятно уникальный.

Так вот...

  1. При таких начальных данных необходимо ли перед вставкой проверять есть ли в таблице запись с полученным UUID (как говорится раз в год и палка стреляет) или же UUID действительно достаточно уникален, что бы этого не делать.
  2. Если проверять необходимо, то как это правильно реализовать? т.е., например, некий бесконечный цикл, который прерывается, если записи с таким UUID не найдено в БД или как-то иначе (мозолит глаз вроде и невероятная, но теоретическая возможность зависнуть в цикле)?

Интересно, как подобное обычно грамотно оформляется на практике.


Ответы (3 шт):

Автор решения: Yitzhak Khabinsky
  1. GUID - это глобальный уникальный идентификатор.
  2. Вы можете создать UNIQUE индекс для этого столбца в базе данных. Индекс PK делает то же самое. Это предотвратит вставку неуникального значения, GUID или нет.
→ Ссылка
Автор решения: Akina

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

Всё. Больше ничего не нужно. Если представить себе тот невероятный случай, что сгенерированный UUID уже присутствует в таблице, вставить запись с ним всё равно не удастся. На то и первичный ключ - при попытке вставки дубликата возникнет ошибка дублирования.

А то, что ошибки следует перехватывать и обрабатывать (мало ли что), по-моему, очевидно...

→ Ссылка
Автор решения: 0xdb

[...] необходимо ли перед вставкой проверять, есть ли в таблице запись с полученным 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. 
→ Ссылка