Используйте функцию в качестве значения по умолчанию для столбца в Oracle11g - PullRequest
5 голосов
/ 23 июля 2011

Мы тестируем Oracle на моей работе и отвечаем за построение всех объектов базы данных (таблиц, процедур, триггеров и т. Д.) В Oracle, и в настоящее время мы используем Microsoft SQL Server 2008 R2. Мы используем уникальные идентификаторы почти во всех столбцах идентификаторов. Я использовал эту функцию для создания GUID:

CREATE OR REPLACE FUNCTION NEWID RETURN CHAR IS guid CHAR(36) ;
BEGIN
    SELECT SYS_GUID() INTO guid FROM DUAL;
    guid :=
               SUBSTR(guid,  1, 8) ||
        '-' || SUBSTR(guid,  9, 4) ||
        '-' || SUBSTR(guid, 13, 4) ||
        '-' || SUBSTR(guid, 17, 4) ||
        '-' || SUBSTR(guid, 21);
    RETURN guid;
END NEWID;
/

Но теперь я не могу понять, как использовать его в качестве значения по умолчанию для столбцов при создании таблиц. Вот нерабочий пример:

CREATE TABLE "NonWorkingExample"
(   
  "ID"                              CHAR(36)      NOT NULL DEFAULT   NEWID(),
  "UnitNumber"                      NUMBER(38)    NOT NULL,
  "StartDateTime"                   TIMESTAMP     NOT NULL,
  "EndDateTime"                     TIMESTAMP     NULL,

  CONSTRAINT PK_RentalAgreements  PRIMARY KEY ("ID")
);

И ошибка:

Error starting at line 1 in command:
CREATE TABLE "NonWorkingExample"
(   
  "ID"                          CHAR(36)      NOT NULL DEFAULT NEWID(),
  "UnitNumber"                  NUMBER(38)    NOT NULL,
  "StartDateTime"               TIMESTAMP     NOT NULL,
  "EndDateTime"                 TIMESTAMP     NULL,

  CONSTRAINT PK_RentalAgreements  PRIMARY KEY ("ID")
)
Error at Command Line:3 Column:58
Error report:
SQL Error: ORA-00907: missing right parenthesis
00907. 00000 -  "missing right parenthesis"
*Cause:    
*Action:

Любая помощь будет высоко ценится. Спасибо.

Ответы [ 6 ]

11 голосов
/ 23 июля 2011

Я полностью согласен с другими ответами, что если вы действительно хотите вызвать функцию, вам нужно использовать триггер или вам нужно встроить вызов функции в сам оператор INSERT. Встраивание вызова функции в оператор INSERT более эффективно, чем принуждение Oracle к выполнению триггера для каждой вставляемой строки.

Следует отметить, что вы можете использовать SYS_GUID() в качестве значения по умолчанию для столбца, не беспокоясь о триггере

SQL> create table foo (
  2    col1 varchar2(32) default sys_guid(),
  3    col2 number
  4  );

Table created.

SQL> insert into foo( col2 ) values( 1 );

1 row created.

SQL> select * from foo;

COL1                                   COL2
-------------------------------- ----------
7B64E8AE7404421C80A590F65873CD79          1

Вам действительно нужны дополнительные тире в значениях GUID? Не могли бы вы добавить штрихи только при отображении данных? Или, поскольку вы используете 11g, добавьте функциональный виртуальный столбец, который преобразует GUID без штрихов в GUID в формате, который вы предпочитаете?

И поскольку вы используете SQL Server, я должен отметить, что в Oracle было бы общепринятым использовать последовательность для заполнения синтетических первичных ключей вместо использования GUID. Использование последовательности для заполнения ключа обычно более эффективно, чем вызов SYS_GUID.

6 голосов
/ 23 июля 2011

Как и предполагалось @Kerri, вы не можете использовать функцию PLSQL в качестве значения по умолчанию в определении таблицы.Соответствующее утверждение в документации Oracle : «Выражение DEFAULT не может содержать ссылки на функции PL / SQL ...».

В дополнение к тому, что это единственный способ вставить отформатированный GUID,поскольку вы пытаетесь это сделать, триггер дает второе преимущество: в отличие от значения по умолчанию, значение, установленное триггером, не может быть переопределено неосторожным разработчиком.

Кроме того, вы должны действительно пересмотреть свойnewid функция для использования прямого назначения вместо select ... from dual:

CREATE OR REPLACE FUNCTION NEWID RETURN CHAR IS 
    guid VARCHAR(36);
BEGIN
    guid := SYS_GUID();
    guid :=
               SUBSTR(guid,  1, 8) ||
        '-' || SUBSTR(guid,  9, 4) ||
        '-' || SUBSTR(guid, 13, 4) ||
        '-' || SUBSTR(guid, 17, 4) ||
        '-' || SUBSTR(guid, 21);
    RETURN guid;
END NEWID;
/

Наконец, я бы посоветовал вам использовать varchar2 вместо char.Вопреки популярному мнению , у char нет преимуществ в плане хранения или эффективности, так что вы могли бы также использовать varchar2 для всего, просто ради простоты.

5 голосов
/ 23 июля 2011

Вы не можете использовать функцию для этого .Вы не видите этого, потому что ваш синтаксис неправильный (ПО УМОЛЧАНИЮ перед ОГРАНИЧЕНИЯМИ).У вас должно быть:

"ID"    CHAR(36)  DEFAULT NEWID()   NOT NULL ,

, и в этот момент вы получите следующее сообщение (11 г):

SQL> create table tt (id varchar2(36) default newid() not null);
create table tt (id varchar2(36) default newid() not null)
                                   *
ERROR at line 1:
ORA-04044: procedure, function, package, or type is not allowed here


SQL>

. Как заявляет @Kerri, для этого потребуется триггер,

5 голосов
/ 23 июля 2011

Предложение:

  • Вместо этого используйте триггеры.

Например:

CREATE TRIGGER SetGUIDforTableXYZ BEFORE INSERT ON TableXYZ
FOR EACH ROW
BEGIN
    :new.ID := NEWID();
END;

Это должно сработать (при условии, что я где-то не испортил синтаксис).

0 голосов
/ 06 июля 2018

Если Oracle SYS_GUID () несколько схожи / последовательные GUID беспокоит вас, вы можете обернуть java.util.UUID.randomUUID () в функцию pl / sql, чтобы получить менее предсказуемые значения:

CREATE OR REPLACE FUNCTION Java_Util_Random_UUID RETURN VARCHAR2 AS
language java
name 'java.util.UUID.randomUUID() return String';
0 голосов
/ 05 июня 2012

Как насчет удаления функции и триггерных зависимостей, попробовав что-то вроде этого:

CREATE TABLE "NonWorkingExample" 
(    
  "ID"                          CHAR(36)      NOT NULL DEFAULT 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'), 
  "UnitNumber"                  NUMBER(38)    NOT NULL, 
  "StartDateTime"               TIMESTAMP     NOT NULL, 
  "EndDateTime"                 TIMESTAMP     NULL, 

  CONSTRAINT PK_RentalAgreements  PRIMARY KEY ("ID") 
) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...