¿Cómo generar un GUID en Oracle?

89

¿Es posible generar automáticamente un GUID en una instrucción Insert?

Además, ¿qué tipo de campo debo usar para almacenar este GUID?

Acibi
fuente

Respuestas:

138

Puede usar la función SYS_GUID () para generar un GUID en su declaración de inserción:

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

El tipo de datos preferido para almacenar GUID es RAW (16).

Como respuesta de Gopinath:

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

Usted obtiene

88FDC68C75DDF955E040449808B55601
88FDC68C75DEF955E040449808B55601
88FDC68C75DFF955E040449808B55601

Como dice Tony Andrews, difiere solo en un personaje

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

Quizás útil: http://feuerthoughts.blogspot.com/2006/02/watch-out-for-sequential-oracle-guids.html

Tony Andrews
fuente
Extraño, sys_guid () siempre me da el mismo GUID. ¿Necesito darle una semilla a la función o?
Acibi
10
¿Estás seguro de que son exactamente iguales? Tiende a devolver valores muy similares (pero diferentes); por ejemplo, cuando lo intenté, obtuve 88FDC68C75DEF955E040449808B55601 y 88FDC68C75DFF955E040449808B55601, ¡que solo difieren en el duodécimo carácter!
Tony Andrews
Intente seleccionar sys_guid () de dual y compare valores. Modifique la respuesta al respecto.
Kiquenet
26

También puede incluir el guid en la declaración de creación de la tabla como predeterminado, por ejemplo:

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

Ver aquí: http://rwijk.blogspot.com/2009/12/sysguid.html

TTT
fuente
Gracias por alertarme sobre una característica útil de Oracle que no conocía.
SteveT
7

No está claro qué quiere decir con generar automáticamente una guía en una declaración de inserción, pero supongo que está tratando de hacer algo como lo siguiente:

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

En ese caso, creo que la columna de ID debería declararse como RAW (16);

Estoy haciendo esto fuera de mi cabeza. No tengo una instancia de Oracle a la mano para probar, pero creo que eso es lo que quieres.

Kenneth Baltrinic
fuente
4

sys_guid () es una mala opción, como han mencionado otras respuestas. Una forma de generar UUID y evitar valores secuenciales es generar cadenas hexadecimales aleatorias usted mismo:

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
fuente
3
No se garantiza que esos sean únicos. Debería emparejarlo con algo así como una restricción única en el lugar donde lo esté almacenando, si lo está almacenando. (y generar un nuevo número si encuentra un valor repetido y viola la restricción única, por poco probable que sea)
James Daily
2

Puede ejecutar la siguiente consulta

 select sys_guid() from dual
 union all
 select sys_guid() from dual
 union all 
 select sys_guid() from dual
Gopinath Kotla
fuente
2

puede usar la función a continuación para generar su 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;

Ejemplo de GUID generado por la función anterior:
8EA4-196D-BC48-9793-8AE8-5500-03DC-9D04

BERGUIGA Mohamed Amine
fuente
SYS_GUID no fue lo suficientemente aleatorio para nuestras necesidades, pero esto parece bombear GUID que son mucho más aleatorios.
ThePeter
1

Si necesita guías no secuenciales, puede enviar los sys_guid()resultados a través de una función hash (consulte https://stackoverflow.com/a/22534843/1462295 ). La idea es mantener la singularidad que se usa de la creación original y obtener algo con más bits mezclados.

Por ejemplo:

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

Ejemplo que muestra la guía secuencial predeterminada frente a su envío a través de un 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  

salida

80c32a4fbe405707e0531e18980a1bbb
80c32a4fbe415707e0531e18980a1bbb
80c32a4fbe425707e0531e18980a1bbb
80c32a4fbe435707e0531e18980a1bbb
c0f2ff2d3ef7b422c302bd87a4588490
d1886a8f3b4c547c28b0805d70b384f3
a0c565f3008622dde3148cfce9353ba7
1c375f3311faab15dc6a7503ce08182c
BurnsBA
fuente
0

Recomendaría usar la función "dbms_crypto.randombytes" de Oracle.

¿Por qué? Esta función devuelve un valor RAW que contiene una secuencia de bytes pseudoaleatoria criptográficamente segura, que se puede utilizar para generar material aleatorio para claves de cifrado.

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

No debe utilizar la función "sys_guid" si sólo cambia un carácter.

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
fuente