3

在创建引用序列的外键时遇到问题,请参见下面的代码示例。
但是在创建表时,我收到以下错误。
“详细信息:关键列“产品”和“id”的类型不兼容:整数和 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));
4

3 回答 3

4
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伪类型创建序列,就会发生这种情况。

于 2013-02-28T14:17:29.703 回答
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 的 create 序列的名称应该是products_id_seq.

希望这可以帮助。

于 2013-02-28T14:24:34.593 回答
2

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

您的 DDL 非常有效,但根本不是您认为的那样。

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

你打算做什么

根据另一个答案,您打算这样定义 id 字段:

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

你做了什么

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

CREATE SEQUENCE testseq;

然后假设我\d testseq在 Pg 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 中实际上非常强大,但充满了意想不到的角落(例如,not null 和检查约束在嵌套数据类型中无法按预期工作)。我一般不推荐嵌套数据类型,但值得知道 PostgreSQL 可以做到这一点,并且很乐意接受 SQL 命令来做到这一点而不会发出警告。

于 2013-02-28T15:31:26.950 回答