对序列列的引用 (PostgreSQL)

reference to a sequence column (postgresql)

提问人:D Jake 提问时间:2/28/2013 更新时间:6/1/2014 访问量:6164

问:

我在创建引用序列的外键时遇到了问题,请参阅下面的代码示例。
但是在创建表时,我收到以下错误。
“详细信息:关键列”product“和”id“的类型不兼容:integer 和 ownseq”
我已经为产品列尝试了不同的数据类型(如 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));
PostgreSQL 引用 序列

评论


答:

4赞 Clodoaldo Neto 2/28/2013 #1
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;

关键的变化是将其定义为 ,而不是 。如果使用伪类型创建序列,则会出现这种情况。idintegerownseqSERIAL

2赞 Claude 2/28/2013 #2

尝试

    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

希望这会有所帮助。

评论

0赞 Clodoaldo Neto 2/28/2013
primary key这意味着,后者是没有必要的。not null
0赞 Clodoaldo Neto 2/28/2013
是的,根据演员的版本,这是必要的。regclass
0赞 D Jake 12/4/2013
此语法是否在“create table”语句中创建序列?是否可以像原始语句一样设置最小值和最大值?
0赞 Claude 12/4/2013
@DJake 你是说语法吗?如果是,请参阅串行文档。它只是创建唯一标识符列的一种符号便利,其等效项是一系列语句。其中一个语句是 .此处似乎不可能有最小值或最大值。serialCREATE SEQUENCE tablename_colname_seq
2赞 Chris Travers 2/28/2013 #3

PostgreSQL 功能强大,您刚刚被一项高级功能所吸引。

你的DDL是相当有效的,但根本不是你想象的那样。

序列可以看作是用于为某些列生成下一个值的事务外简单表。

你打算做什么

您的意思是将 id 字段定义为这样,根据另一个答案:

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

你做了什么

您所做的实际上是为表定义嵌套数据结构。假设我创建了一个测试序列:

CREATE SEQUENCE testseq;

然后假设我在 Pg 9.1 上,我得到:\d testseq

           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中非常强大,但充满了意想不到的角落(例如,not null和check约束在嵌套数据类型中不能按预期工作)。我通常不推荐嵌套数据类型,但值得一提的是,PostgreSQL 可以做到这一点,并且很乐意接受 SQL 命令来做到这一点,而不会发出警告。