Jak wygenerować GUID w Oracle?

90

Czy jest możliwe automatyczne generowanie identyfikatora GUID w instrukcji Insert?

Jakiego typu pola należy użyć do przechowywania tego identyfikatora GUID?

Acibi
źródło

Odpowiedzi:

139

Możesz użyć funkcji SYS_GUID (), aby wygenerować identyfikator GUID w instrukcji insert:

insert into mytable (guid_col, data) values (sys_guid(), 'xxx');

Preferowanym typem danych do przechowywania identyfikatorów GUID jest RAW (16).

Jak odpowiada Gopinath:

 select sys_guid() from dual
 union all
 select sys_guid() from dual
 union all 
 select sys_guid() from dual

Dostajesz

88FDC68C75DDF955E040449808B55601
88FDC68C75DEF955E040449808B55601
88FDC68C75DFF955E040449808B55601

Jak mówi Tony Andrews, różni się tylko jedną postacią

88FDC68C75D D F955E040449808B55601
88FDC68C75D E F955E040449808B55601
88FDC68C75D F F955E040449808B55601

Może przydatne: http://feuerthoughts.blogspot.com/2006/02/watch-out-for-sequential-oracle-guids.html

Tony Andrews
źródło
Dziwne, sys_guid () zawsze daje mi ten sam identyfikator GUID. Czy muszę podać ziarno do funkcji, czy?
Acibi
11
Czy na pewno są dokładnie takie same? Ma tendencję do zwracania bardzo podobnych (ale różnych) wartości - np. Kiedy właśnie spróbowałem, otrzymałem 88FDC68C75DEF955E040449808B55601 i 88FDC68C75DFF955E040449808B55601, które różnią się tylko przy 12 znaku!
Tony Andrews
Spróbuj wybrać sys_guid () z dual i porównaj wartości. Zmodyfikuj odpowiedź na ten temat.
Kiquenet
26

Możesz również domyślnie dołączyć guid do instrukcji tworzenia tabeli, na przykład:

create table t_sysguid
( id     raw(16) default sys_guid() primary key
, filler varchar2(1000)
)
/

Zobacz tutaj: http://rwijk.blogspot.com/2009/12/sysguid.html

TTT
źródło
Dziękuję za powiadomienie mnie o użytecznej funkcji Oracle, o której nie wiedziałem.
SteveT
7

Nie jest jasne, co masz na myśli przez automatyczne generowanie przewodnika w instrukcji wstawiania, ale myślę, że próbujesz wykonać coś takiego:

INSERT INTO MY_TAB (ID, NAME) VALUES (SYS_GUID(), 'Adams');
INSERT INTO MY_TAB (ID, NAME) VALUES (SYS_GUID(), 'Baker');

W takim przypadku uważam, że kolumna ID powinna zostać zadeklarowana jako RAW (16);

Robię to od czubka głowy. Nie mam pod ręką instancji Oracle do przetestowania, ale myślę, że właśnie tego chcesz.

Kenneth Baltrinic
źródło
5

sys_guid () jest kiepską opcją, jak wspomniały inne odpowiedzi. Jednym ze sposobów generowania identyfikatorów UUID i unikania wartości sekwencyjnych jest samodzielne generowanie losowych ciągów szesnastkowych:

select regexp_replace(
    to_char(
        DBMS_RANDOM.value(0, power(2, 128)-1),
        'FM0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'),
    '([a-f0-9]{8})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{12})',
    '\1-\2-\3-\4-\5') from DUAL;
MikeWyatt
źródło
4
Nie gwarantuje się, że będą one wyjątkowe. Musisz połączyć to z czymś w rodzaju unikalnego ograniczenia, gdziekolwiek go przechowujesz, jeśli to przechowujesz. (i generowanie nowej liczby, jeśli napotkasz powtarzającą się wartość i naruszysz unikalne ograniczenie, chociaż jest to mało prawdopodobne)
James Daily,
2

Możesz uruchomić następujące zapytanie

 select sys_guid() from dual
 union all
 select sys_guid() from dual
 union all 
 select sys_guid() from dual
Gopinath Kotla
źródło
2

możesz użyć funkcji poniżej, aby wygenerować swój UUID

create or replace FUNCTION RANDOM_GUID
    RETURN VARCHAR2 IS

    RNG    NUMBER;
    N      BINARY_INTEGER;
    CCS    VARCHAR2 (128);
    XSTR   VARCHAR2 (4000) := NULL;
  BEGIN
    CCS := '0123456789' || 'ABCDEF';
    RNG := 15;

    FOR I IN 1 .. 32 LOOP
      N := TRUNC (RNG * DBMS_RANDOM.VALUE) + 1;
      XSTR := XSTR || SUBSTR (CCS, N, 1);
    END LOOP;

    RETURN SUBSTR(XSTR, 1, 4) || '-' ||
        SUBSTR(XSTR, 5, 4)        || '-' ||
        SUBSTR(XSTR, 9, 4)        || '-' ||
        SUBSTR(XSTR, 13,4)        || '-' ||
        SUBSTR(XSTR, 17,4)        || '-' ||
        SUBSTR(XSTR, 21,4)        || '-' ||
        SUBSTR(XSTR, 24,4)        || '-' ||
        SUBSTR(XSTR, 28,4);
END RANDOM_GUID;

Przykład identyfikatora GUID generowanego przez powyższą funkcję:
8EA4-196D-BC48-9793-8AE8-5500-03DC-9D04

BERGUIGA Mohamed Amine
źródło
SYS_GUID nie był wystarczająco losowy dla naszych potrzeb, ale wydaje się, że pompuje GUID, które są o wiele bardziej losowe.
ThePeter
1

Jeśli potrzebujesz niesekwencyjnych wskazówek, możesz wysłać sys_guid()wyniki za pomocą funkcji haszującej (patrz https://stackoverflow.com/a/22534843/1462295 ). Chodzi o to, aby zachować wyjątkowość oryginalnego dzieła i uzyskać coś z większą ilością przetasowanych fragmentów.

Na przykład:

LOWER(SUBSTR(STANDARD_HASH(SYS_GUID(), 'SHA1'), 0, 32))  

Przykład pokazujący domyślny sekwencyjny identyfikator guid vs wysyłanie go przez hash:

SELECT LOWER(SYS_GUID()) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SYS_GUID()) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SYS_GUID()) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SYS_GUID()) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SUBSTR(STANDARD_HASH(SYS_GUID(), 'SHA1'), 0, 32)) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SUBSTR(STANDARD_HASH(SYS_GUID(), 'SHA1'), 0, 32)) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SUBSTR(STANDARD_HASH(SYS_GUID(), 'SHA1'), 0, 32)) AS OGUID FROM DUAL
UNION ALL
SELECT LOWER(SUBSTR(STANDARD_HASH(SYS_GUID(), 'SHA1'), 0, 32)) AS OGUID FROM DUAL  

wynik

80c32a4fbe405707e0531e18980a1bbb
80c32a4fbe415707e0531e18980a1bbb
80c32a4fbe425707e0531e18980a1bbb
80c32a4fbe435707e0531e18980a1bbb
c0f2ff2d3ef7b422c302bd87a4588490
d1886a8f3b4c547c28b0805d70b384f3
a0c565f3008622dde3148cfce9353ba7
1c375f3311faab15dc6a7503ce08182c
BurnsBA
źródło
0

Polecam korzystanie z funkcji „dbms_crypto.randombytes” firmy Oracle.

Czemu? Ta funkcja zwraca wartość RAW zawierającą zabezpieczoną kryptograficznie pseudolosową sekwencję bajtów, której można użyć do wygenerowania losowego materiału na klucze szyfrowania.

select REGEXP_REPLACE(dbms_crypto.randombytes(16), '(.{8})(.{4})(.{4})(.{4})(.{12})', '\1-\2-\3-\4-\5') from dual;

Nie powinieneś używać funkcji "sys_guid", jeśli zmieni się tylko jeden znak.

ALTER TABLE locations ADD (uid_col RAW(16));

UPDATE locations SET uid_col = SYS_GUID();

SELECT location_id, uid_col FROM locations
   ORDER BY location_id, uid_col;

LOCATION_ID UID_COL
----------- ----------------------------------------------------------------
       1000 09F686761827CF8AE040578CB20B7491
       1100 09F686761828CF8AE040578CB20B7491
       1200 09F686761829CF8AE040578CB20B7491
       1300 09F68676182ACF8AE040578CB20B7491
       1400 09F68676182BCF8AE040578CB20B7491
       1500 09F68676182CCF8AE040578CB20B7491

https://docs.oracle.com/database/121/SQLRF/functions202.htm#SQLRF06120

Alex Fischer
źródło