Firebird + Lazarus+ GUID

Модератор: Модераторы

Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Firebird + Lazarus+ GUID

Сообщение wofs »

Доброго дня.
Собственно как хранить в БД/обрабатывать на клиенте?
Если хранить на сервере как VARCHAR(32), то довольно накладно для первичного ключа (беспокоит размер индекса).
Если хранить в домене:

Код: Выделить всё

CREATE DOMAIN GUID AS 
CHAR(16) CHARACTER SET OCTETS
COLLATE OCTETS;

То совершенно непонятно как обрабатывать на клиенте (например, апдейт записи).

Использую стандартный SQLQuery, запросы формирую с параметрами.

Добавлено спустя 5 минут 30 секунд:
Читал статейку: http://www.ibase.ru/test2/, но там предлагается переворачивать GUID после генерации для хранения с целью уменьшения размера индекса, но как то совсем велосипед...
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

32 символа жирновато... https://firebirdsql.org/refdocs/langref ... _uuid.html
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

wadman писал(а):32 символа жирновато... https://firebirdsql.org/refdocs/langref ... _uuid.html

Согласен, но при хранении как CHAR(16) совершенно непонятно как использовать его на клиенте (например, для апдейта записи).

wofs писал(а):Если хранить в домене:

Код: Выделить всё
CREATE DOMAIN GUID AS
CHAR(16) CHARACTER SET OCTETS
COLLATE OCTETS;


То совершенно непонятно как обрабатывать на клиенте (например, апдейт записи).
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

Оказалось, что в той статье как раз об этом. :)

Гуид вообще сам по себе велосипед, который обычно применяют при репликации.
Чем bigint не угодил?

Добавлено спустя 1 минуту 27 секунд:
wofs писал(а):например, для апдейта записи

Как обычно: при вставке сгенерировал, сконвертировал и вставил. Далее работаешь как с обычным ключевым полем без каких-либо конвертаций.
При необходимости (для отображения человеку) - можно и вернуть в обратный вид на лету (обратной функцией).
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

wadman писал(а):Чем bigint не угодил?

Несколько автономных клиентов с периодической синхронизацией с головной БД. Нужна уникальность ключей при добавлении записей в оффлайн.
wadman писал(а):Как обычно: при вставке сгенерировал, сконвертировал и вставил. Далее работаешь как с обычным ключевым полем без каких-либо конвертаций.

Проблема в том, что если хранить GUID на сервере в CHAR(16), то при выборке на клиенте получаем белиберду вроде

Код: Выделить всё

SELECT * FROM TABLE
aDataSet.FieldByName('ID').AsString

//return: ????K??m2(?

И я не могу передать это в параметр запроса на изменение обновить запись

Код: Выделить всё

UPDATE TABLE SET NAME=:NAME WHERE ID=:ID

точнее передать то могу, только запись не обновиться.
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

wofs писал(а): то при выборке на клиенте получаем белиберду вроде

База в юникоде? Я таким не занимался, но на лицо проблема с кодировкой.
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

wadman писал(а):База в юникоде? Я таким не занимался, но на лицо проблема с кодировкой.

Да, UTF8.
Суть проблемы я уловил и она такова - при конвертации

Код: Выделить всё

SELECT * FROM TABLE
aDataSet.FieldByName('ID').AsString

датасет честно пытается конвертировать 16 байт

Код: Выделить всё

// GUID хранится в БД так:
157 252 250 150 230 170 75 170 190 240 109 50 40 178 139 142

в строку и получаем, что получаем.

Добавлено спустя 27 минут 27 секунд:
Единственное, что получилось - хранить как CHAR(32)

Код: Выделить всё

CREATE DOMAIN GUID AS
CHAR(32) CHARACTER SET OCTETS
COLLATE OCTETS;

и генерировать GUID в триггере:

Код: Выделить всё

   IF (NEW.ID IS NULL) THEN
    NEW.ID = REPLACE(UUID_TO_CHAR(GEN_UUID()),'-','');
// return: A626FF232E03427D948D65A39155DCB7


Тогда работа с GUID ничем не отличается от работой со строками. Придется смириться с бОльшим размером индекса.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

wofs
Ещё вот здесь про GUID упоминали:
http://www.firebirdsql.org/manual/ru/mi ... es-ru.html
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

Vadim писал(а):wofs
Ещё вот здесь про GUID упоминали:

Это я видел. Тот вариант не отличается от моего (CHAR(32)).
Аватара пользователя
serbod
постоялец
Сообщения: 449
Зарегистрирован: 16.09.2016 10:03:02
Откуда: Минск
Контактная информация:

Сообщение serbod »

А почему decimal или int64 не подходят? int64 это не так уж и мало, даже очень дохрена на самом деле. Особенно, если не рандомно генерить, а по алгоритму.
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

serbod писал(а):А почему decimal или int64 не подходят? int64 это не так уж и мало, даже очень дохрена на самом деле. Особенно, если не рандомно генерить, а по алгоритму.

Нужна уникальность номера при условии генерации оного на оффлайн клиентах.
---
ps. Куда-то Виталий пропал с балалайкой...
Аватара пользователя
serbod
постоялец
Сообщения: 449
Зарегистрирован: 16.09.2016 10:03:02
Откуда: Минск
Контактная информация:

Сообщение serbod »

wofs писал(а):Нужна уникальность номера при условии генерации оного на оффлайн клиентах.

1-2 байта на номер клиента (филиала, экземпляра) и остальные 6 байтов - синтетический автоинкремент. Перед началом работы делаешь запрос максимального номера для данного экземпляра и от него дальше танцуешь.
olegy123
долгожитель
Сообщения: 1643
Зарегистрирован: 25.02.2016 11:10:20

Сообщение olegy123 »

Я разбивал на два int64 так как (UUID) is a 128-bit number.
это двух 64битное число можно индексировать.

Добавлено спустя 1 минуту 57 секунд:
wofs писал(а):Нужна уникальность номера при условии генерации оного на оффлайн клиентах.
Генерация UUID дает уникальность всегда.

Добавлено спустя 4 минуты 56 секунд:
вообще любые данные можно сериализовать -> перевести данные в виде потока данных,
два int64 подходят для упаковки данных GUUID без потери, так же можно восстановить GUUID из двух int64 .

Добавлено спустя 2 минуты 50 секунд:
serbod писал(а):1-2 байта на номер клиента (филиала, экземпляра) и остальные 6 байтов - синтетический автоинкремент. Перед началом работы делаешь запрос максимального номера для данного экземпляра и от него дальше танцуешь.
не всегда это подходит, бывает когда данные создаются без привязки к чему либо.. но нужно обеспечить уникальность в рамках земного шара/вселенной.
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3071
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

olegy123 писал(а):не всегда это подходит, бывает когда данные создаются без привязки к чему либо.. но нужно обеспечить уникальность в рамках земного шара/вселенной.
Универсальное правило - не множить сущности. Закладывать в программе возможности выхода на межгалактический рынок - не самая удачная идея... :D
Аватара пользователя
wofs
постоялец
Сообщения: 379
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань
Контактная информация:

Сообщение wofs »

Спасибо всем за информацию к размышлению.
Ответить