ссылка на столбец последовательности (postgresql)

Я столкнулся с проблемой при создании внешнего ключа, ссылающегося на последовательность, см. пример кода ниже.
Но при создании таблиц я получаю следующую ошибку.
"Подробности: ключевые столбцы "продукт" и "идентификатор" несовместимых типов: integer и ownseq"
Я уже пробовал разные типы данных для столбца product (например, smallint, bigint), но ни один из них не подходит.

CREATE SEQUENCE ownseq INCREMENET BY 1 MINVALUE 100 MAXVALUE 99999;  
CREATE TABLE products (  
id ownseq PRIMARY KEY,  
...);

CREATE TABLE basket (
basket_id SERIAL PRIMARY KEY,
product INTEGER FOREIGN KEY REFERENCES products(id));

person D Jake    schedule 28.02.2013    source источник


Ответы (3)


CREATE SEQUENCE ownseq INCREMENT BY 1 MINVALUE 100 MAXVALUE 99999;  
CREATE TABLE products (  
    id integer PRIMARY KEY default nextval('ownseq'),
    ...
);
alter sequence ownseq owned by products.id;

Ключевое изменение заключается в том, что id определяется как integer, а не как ownseq. Вот что произошло бы, если бы вы использовали псевдотип SERIAL для создания последовательности.

person Clodoaldo Neto    schedule 28.02.2013

Пытаться

    CREATE TABLE products (  
    id INTEGER DEFAULT nextval(('ownseq'::text)::regclass) NOT NULL PRIMARY KEY,  
    ...);

или не создавайте последовательность ownseq и позвольте postgres сделать это за вас:

    CREATE TABLE products (
    id SERIAL NOT NULL PRIMARY KEY
    ...);

В приведенном выше случае имя последовательности, созданной postgres, должно быть products_id_seq.

Надеюсь это поможет.

person Claude    schedule 28.02.2013
comment
primary key подразумевает not null, поэтому последнее не обязательно. - person Clodoaldo Neto; 28.02.2013
comment
И да, в зависимости от версии необходимо приведение к regclass. - person Clodoaldo Neto; 28.02.2013
comment
Создает ли этот синтаксис последовательность в операторе создания таблицы? И можно ли установить минимальное значение и максимальное значение, как в исходном заявлении? - person D Jake; 03.12.2013
comment
@DJake Вы имеете в виду синтаксис serial? Если да, см. документацию по серийному номеру. Это просто удобство нотации для создания столбцов уникальных идентификаторов, и его эквивалентом является ряд операторов. Одним из таких утверждений является CREATE SEQUENCE tablename_colname_seq. Минимальные или максимальные значения кажутся здесь невозможными. - person Claude; 04.12.2013

PostgreSQL мощен, и вас только что поразила расширенная функция.

Ваш DDL вполне действителен, но совсем не то, что вы думаете.

Последовательность можно рассматривать как простую внетранзакционную таблицу, используемую для генерации следующих значений для некоторых столбцов.

Что вы хотели сделать

Вы хотели, чтобы поле id было определено таким образом, как в другом ответе:

id integer PRIMARY KEY default nextval('ownseq'),

Что вы сделали

То, что вы сделали, это фактически определили вложенную структуру данных для вашей таблицы. Предположим, я создаю тестовую последовательность:

CREATE SEQUENCE testseq;

Тогда предположим, что я \d testseq на стр. 9.1, я получаю:

           Sequence "public.testseq"
    Column     |  Type   |        Value        
---------------+---------+---------------------
 sequence_name | name    | testseq
 last_value    | bigint  | 1
 start_value   | bigint  | 1
 increment_by  | bigint  | 1
 max_value     | bigint  | 9223372036854775807
 min_value     | bigint  | 1
 cache_value   | bigint  | 1
 log_cnt       | bigint  | 0
 is_cycled     | boolean | f
 is_called     | boolean | f

Это определение типа используемой последовательности.

Теперь предположим, что я:

 create table seqtest (test testseq, id serial);

Я могу вставить в него:

 INSERT INTO seqtest (id, test) values (default, '("testseq",3,4,1,133445,1,1,0,f,f)');

Затем я могу выбрать из него:

select * from seqtest;
               test               | id 
----------------------------------+----
 (testseq,3,4,1,133445,1,1,0,f,f) |  2

Более того, я могу расширить тест:

SELECT (test).* from seqtest;

select (test).* from seqtest;
 sequence_name | last_value | start_value | increment_by | max_value | min_value
 | cache_value | log_cnt | is_cycled | is_called 
---------------+------------+-------------+--------------+-----------+----------
-+-------------+---------+-----------+-----------
               |            |             |              |           |          
 |             |         |           | 
 testseq       |          3 |           4 |            1 |    133445 |         1
 |           1 |       0 | f         | f
(2 rows)

Такого рода вещи на самом деле очень эффективны в PostgreSQL, но полны неожиданных поворотов (например, не нуль и проверочные ограничения не работают должным образом с вложенными типами данных). Обычно я не рекомендую вложенные типы данных, но стоит знать, что PostgreSQL может это делать и будет рад принять команды SQL для этого без предупреждения.

person Chris Travers    schedule 28.02.2013