Как устранить проблему с «отсутствующей правой скобкой»?

#sql #oracle

#sql #Oracle

Вопрос:

Ниже приведен пример запроса, над которым я сейчас работаю:

 CREATE TABLE book (
    book_id       NUMBER(6) NOT NULL CHECK(book_id > 0),
    isbn          VARCHAR2(20) NOT NULL UNIQUE,
    title         VARCHAR2(100) NOT NULL,
    shelf_letter  VARCHAR2(2) NOT NULL CHECK(shelf_letter IN('A-Z')),
    call_number   NUMBER(3) NOT NULL CHECK(call_number IN (1-999)),
    no_of_pages   NUMBER(4),
    no_of_copies  NUMBER(3) NOT NULL CHECK(no_of_copies >= 1),
    date_arrived  DATE NOT NULL DEFAULT SYSDATE,
    publisher_id  NUMBER(4) NOT NULL,
    cat_id        NUMBER(2) NOT NULL,
    CONSTRAINT shelf_call UNIQUE(shelf_letter,call_number) 
);
  

При компиляции выдается ошибка «отсутствует правая скобка». Я проверил, но все скобки учтены. Кто-нибудь может мне помочь?

Комментарии:

1. Вопрос (не связанный с ошибкой и правильным ответом, который вы получили): Если shelf_letter должна быть одна заглавная буква (между A и Z), почему это тип данных столбца varchar2(2) , а не varchar2(1) ? Если «буква» полки на самом деле может состоять из двух символов, то вы должны более подробно объяснить, каковы допустимые значения.

Ответ №1:

Фактическая ошибка, которую вы видите, вызвана тем, что date_arrived столбец с NOT NULL помещается перед значением по умолчанию SYSDATE , тогда как оно должно быть после:

 date_arrived  DATE DEFAULT SYSDATE NOT NULL,
  

Кроме того, ограничения второй и третьей проверки, несмотря на технически корректный синтаксис, выглядят сомнительно:

 shelf_letter  VARCHAR2(2) NOT NULL CHECK(shelf_letter IN('A-Z')),
call_number   NUMBER(3) NOT NULL CHECK(call_number IN (1-999)),
  

Для проверки shelf_letter , предположительно, вы хотите обеспечить, чтобы это могли быть только заглавные буквы от A до Z. Если да, то используйте REGEXP_LIKE :

 shelf_letter  VARCHAR2(2) NOT NULL CHECK(REGEXP_LIKE(shelf_letter, '^[A-Z]$')),
  

Для проверки call_number используйте сравнение диапазона:

 call_number   NUMBER(3) NOT NULL CHECK(call_number BETWEEN 1 AND 999),
  

Собрав все это вместе, используйте следующую инструкцию create table:

 CREATE TABLE book (
    book_id       NUMBER(6) NOT NULL CHECK(book_id > 0),
    isbn          VARCHAR2(20) NOT NULL,
    title         VARCHAR2(100) NOT NULL,
    shelf_letter  VARCHAR2(2) NOT NULL CHECK(REGEXP_LIKE(shelf_letter, '^[A-Z]$')),
    call_number   NUMBER(6) NOT NULL CHECK(call_number BETWEEN 1 AND 999),
    no_of_pages   NUMBER(4),
    no_of_copies  NUMBER(3) NOT NULL CHECK(no_of_copies >= 1),
    date_arrived  DATE DEFAULT SYSDATE NOT NULL,
    publisher_id  NUMBER(4) NOT NULL,
    cat_id        NUMBER(2) NOT NULL,
    CONSTRAINT shelf_call UNIQUE(shelf_letter, call_number)
);
  

ДЕМОНСТРАЦИЯ

Комментарии:

1. Не должно вызывать ошибку, которую видит OP, верно? IN('A-Z') хотя, вероятно, это не то, что хочет OP, синтаксически правильно (я думаю)

2. Блин, конечно. Подсветка синтаксиса сбила меня с толку, и я подумал, что это строка.

3. Единственной синтаксической ошибкой является размещение предложения DEFAULT после ограничения NOT NULL. call_number IN (1-999) совершенно допустимо (хотя, очевидно, не то, что предполагалось в OP); - для чисел используется оператор вычитания.

4. @mathguy Да, и я понял это, когда настроил демо и обнаружил, что мои первоначальные «исправления» все еще оставляли синтаксическую ошибку. Вы очень хорошо разбираетесь в Oracle, если можете увидеть эту ошибку, просто взглянув на инструкцию create операционной системы.

5. Мой комментарий был адресован конкретно вашему комментарию (который вы сейчас удалили), в котором говорилось, что call_number IN (1-999) недопустимо в Oracle SQL. Кроме этого, я не знаю, насколько хорошо я разбираюсь в Oracle (возможно, я хорош), но да, я сразу увидел эту ошибку, просто взглянув на инструкцию CREATE TABLE . Я уже сталкивался с подобной ошибкой раньше; и моя память действительно очень хорошая, независимо от того, насколько хорошо я разбираюсь в Oracle.