#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.