Создать UUID в Oracle [дубликат]

Если вы хотите заменить Unicode old pattern на new pattern, вы должны написать:

$text = preg_replace('/\bold pattern\b/u', 'new pattern', $text);

Таким образом, ключ здесь - u модификатор

Примечание: ваш сервер php version shoud будет как минимум PHP 4.3.5

, как указано здесь php.net | Модификаторы паттерна

u (PCRE_UTF8) Этот модификатор включает дополнительные функции PCRE, которые несовместимы с Perl. Строки шаблонов рассматриваются как UTF-8. Этот модификатор доступен с PHP 4.1.0 или выше в Unix и с PHP 4.2.3 на win32. UTF-8 справедливость шаблона проверяется с PHP 4.3.5.

Спасибо AgreeOrNot, которые дают мне этот ключ здесь preg_replace сопоставить целое слово в арабском

Я пробовал это, и он работал в localhost, но когда я пытаюсь его на удаленном сервере, это не сработало, и я обнаружил, что php.net начинает использовать модификатор u в PHP 4.3.5. , Я обновляю версию php и работает

. Важно знать, что этот метод очень полезен для арабских пользователей (عربي), потому что, как я считаю, unicode - лучший кодировщик для арабского языка, а замена не будет если вы не используете модификатор u, см. следующий пример, он должен работать с вами

$text = preg_replace('/\bمرحبا بك\b/u', 'NEW', $text);

15
задан jpaugh 27 October 2016 в 19:59
поделиться

8 ответов

Я использую это сейчас как обходной путь:

create or replace function random_uuid return RAW is
  v_uuid RAW(16);
begin
  v_uuid := sys.dbms_crypto.randombytes(16);
  return (utl_raw.overlay(utl_raw.bit_or(utl_raw.bit_and(utl_raw.substr(v_uuid, 7, 1), '0F'), '40'), v_uuid, 7));
end random_uuid;

Функция требует dbms_crypto и utl_raw. Оба требуют гранта выполнения.

grant execute on sys.dbms_crypto to uuid_user;
8
ответ дан ceving 17 August 2018 в 09:29
поделиться
  • 1
    Не могли бы вы объяснить, что происходит, когда вы применяете функции utl_raw к выходу randombytes? – tribunal88 28 May 2015 в 14:34
  • 2
    @ tribunal88 Я бы сказал, что некоторые электроны плывут вокруг. ;-) – ceving 29 May 2015 в 13:36
  • 3
    Я имел в виду, почему мы должны применять любую пост-обработку вообще к выходу randombytes (16)? – tribunal88 4 June 2015 в 12:38
  • 4
    Сотрите это. Я понимаю, что вы делаете. Вы устанавливаете номер версии UUID в "4" в соответствии с разделом 4.1.3 RFC 4122. ietf.org/rfc/rfc4122.txt – tribunal88 8 June 2015 в 13:46

https://stackoverflow.com/a/10899320/1194307

Следующая функция использует sys_guid () и преобразует ее в формат uuid:

create or replace function random_uuid return VARCHAR2 is
  v_uuid VARCHAR2(40);
begin
  select regexp_replace(rawtohex(sys_guid()), '([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') into v_uuid from dual;
  return v_uuid;
end random_uuid;

Не нужно создавать пакет dbms_crypto и предоставлять его.

15
ответ дан Community 17 August 2018 в 09:29
поделиться
  • 1
    Спасибо, но regexp_replace звучит довольно дорого. Генерация UUID должна быть очень быстрой. – ceving 6 November 2013 в 11:11
  • 2
    Эта функция не будет случайной на всех платформах. Например, в Solaris при каждом выполнении изменения изменяются только один или два символа. – Jon Heller 24 February 2017 в 02:55

Самый простой и самый короткий способ получить Java-функцию для меня:

create or replace function random_uuid return varchar2 as
language java
name 'java.util.UUID.randomUUID() return String';

Я не могу полностью понять, почему он не компилируется, если я добавлю .toString().

2
ответ дан Derp 17 August 2018 в 09:29
поделиться

Вот полный пример, основанный на ответе @Pablo Santa Cruz и на вашем коде.

Не знаю, почему вы получили сообщение об ошибке. Вероятно, это проблема с SQL Developer. Все работает отлично, когда вы запускаете его в SQL * Plus и добавляете функцию:

   create or replace and compile
   java source named "RandomUUID"
   as
   public class RandomUUID
   {
      public static String create()
      {
              return java.util.UUID.randomUUID().toString();
      }
   }
   /
Java created.
   CREATE OR REPLACE FUNCTION RandomUUID
   RETURN VARCHAR2
   AS LANGUAGE JAVA
   NAME 'RandomUUID.create() return java.lang.String';
   /
Function created.
   select randomUUID() from dual;
RANDOMUUID()
--------------------------------------------------------------
4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc33

Но, если возможно, я придерживался SYS_GUID. Взгляните на ID 1371805.1 на поддержку моего Oracle - эта ошибка, предположительно, исправлена ​​в 11.2.0.3.

EDIT

Какой из них быстрее зависит от того, как используются функции.

Похоже, что версия Java немного быстрее при использовании в SQL. Однако, если вы собираетесь использовать эту функцию в контексте PL / SQL, PL / SQL-функция примерно в два раза быстрее. (Вероятно, потому что он позволяет избежать накладных расходов на переключение между двигателями.)

Вот краткий пример:

--Create simple table
create table test1(a number);
insert into test1 select level from dual connect by level <= 100000;
commit;

--SQL Context: Java function is slightly faster
--
--PL/SQL: 2.979, 2.979, 2.964 seconds
--Java: 2.48, 2.465, 2.481 seconds
select count(*)
from test1
--where to_char(a) > random_uuid() --PL/SQL
where to_char(a) > RandomUUID() --Java
;

--PL/SQL Context: PL/SQL function is about twice as fast
--
--PL/SQL: 0.234, 0.218, 0.234
--Java: 0.52, 0.515, 0.53
declare
    v_test1 raw(30);
    v_test2 varchar2(36);
begin
    for i in 1 .. 10000 loop
        --v_test1 := random_uuid; --PL/SQL
        v_test2 := RandomUUID; --Java
    end loop;
end;
/

Версии 4 GUID не полностью случайным образом. Предполагается, что некоторые из байтов будут исправлены. Я не уверен, почему это было сделано, или если это имеет значение, но согласно https://www.cryptosys.net/pki/uuid-rfc4122.html :

Процедура создания UUID версии 4 выглядит следующим образом:

Generate 16 random bytes (=128 bits)
Adjust certain bits according to RFC 4122 section 4.4 as follows:
    set the four most significant bits of the 7th byte to 0100'B, so the high nibble is "4"
    set the two most significant bits of the 9th byte to 10'B, so the high nibble will be one of "8", "9", "A", or "B".
Encode the adjusted bytes as 32 hexadecimal digits
Add four hyphen "-" characters to obtain blocks of 8, 4, 4, 4 and 12 hex digits
Output the resulting 36-character string "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"

Значения из версии Java соответствуют стандарту.

20
ответ дан Jon Heller 17 August 2018 в 09:29
поделиться
  • 1
    Как узнать, является ли вызов функции Java быстрее, чем использование пакета Oracles dbms_crypto, который я использовал в своей работе? – ceving 25 December 2012 в 12:06
  • 2
    UID в моей системе Solaris предсказуемы, и это не допускается для приложения. – ceving 25 December 2012 в 12:16
  • 3
    @Jon Heller Я попробовал SYS_GUID (), но результат не тот, который я ожидаю. Версия 4 UUID должна выглядеть как xxxxxxxxxxxxxx-4xxx-yxxx-xxxxxxxxxxxx или? – ZerOne 17 July 2018 в 08:50
  • 4
    @ZerOne SYS_GUID (), похоже, работает правильно, см. Редактирование. – Jon Heller 17 July 2018 в 19:34
  • 5
    @JonHeller благодарит за редактирование. может быть, я неправильно понимаю вас, но вы имеете в виду, что он работает правильно на своем собственном пути Oracle? потому что это не похоже на формат, который он должен иметь в соответствии с RFC – ZerOne 18 July 2018 в 14:21

Он может быть не уникальным, но генерировать случайную строку «GUID-like»:

 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 XSTR;
  END RANDOM_GUID;

Адаптировано из источника DBMS_RANDOM.STRING.

2
ответ дан marciel.deg 17 August 2018 в 09:29
поделиться
  • 1
    Вы можете добавить regexp_replace, например, пример @lonecat для форматирования. – marciel.deg 23 February 2017 в 22:13

Вы можете написать Java-процедуру и скомпилировать ее и запустить в Oracle. В этой процедуре вы можете использовать:

UUID uuid = UUID.randomUUID();
return uuid.toString();

Для генерации желаемого значения.

Здесь ссылка на то, как компилировать Java-процедуры в Oracle.

3
ответ дан Pablo Santa Cruz 17 August 2018 в 09:29
поделиться
  • 1
    Есть ли где-нибудь доступный пример? – ceving 19 December 2012 в 13:39
  • 2
    Да, взгляните на ссылку, которую я только что опубликовал. База данных Oracle имеет виртуальную машину Java в своем контексте для запуска такого рода Java-кода в своем контексте без необходимости запуска внешней программы . – Pablo Santa Cruz 19 December 2012 в 13:40
  • 3
    Не работает. Как только я пытаюсь использовать UUID, мой Oracle отказывается скомпилировать его: pastebin.com/kL4jB2KX – ceving 19 December 2012 в 14:24
  • 4
    Я спросил, как использовать java.util.UUID в PL / SQL в Oracle, но до сих пор нет ответа: forums.oracle.com/forums/… – ceving 19 December 2012 в 18:16

Согласно UUID версии 4 формат должен быть xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx. @lonecat ответ предоставит этот формат, также @ceving ответ частично предоставит требования версии 4.

После смешивания этих ответов и исправления части y код выглядит следующим образом:

create or replace function fn_uuid return varchar2 is
  /* UUID Version 4 must be formatted as xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal character (lower case only) and y is one of 8, 9, a, or b.*/

  v_uuid_raw raw(16);
  v_uuid     varchar2(36);
  v_y        varchar2(1);
begin

  v_uuid_raw := sys.dbms_crypto.randombytes(16);
  v_uuid_raw := utl_raw.overlay(utl_raw.bit_or(utl_raw.bit_and(utl_raw.substr(v_uuid_raw, 7, 1), '0F'), '40'), v_uuid_raw, 7);

  v_y := case round(dbms_random.value(1, 4))
            when 1 then
             '8'
            when 2 then
             '9'
            when 3 then
             'a'
            when 4 then
             'b'
           end;

  v_uuid_raw := utl_raw.overlay(utl_raw.bit_or(utl_raw.bit_and(utl_raw.substr(v_uuid_raw, 9, 1), '0F'), v_y || '0'), v_uuid_raw, 9);
  v_uuid     := regexp_replace(lower(v_uuid_raw), '([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');

  return v_uuid;
end fn_uuid;
0
ответ дан Uğur Yeşilyurt 17 August 2018 в 09:29
поделиться
1
ответ дан Leonid 6 September 2018 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: