I encountered a problem when creating a foreign key referencing to a sequence, see the code example below.
But on creating the tables i recieve the following error.
"Detail: Key columns "product" and "id" are of incompatible types: integer and ownseq"
I've already tried different datatypes for the product column (like smallint, bigint) but none of them is accepted.

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));
有帮助吗?

解决方案

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;

The key change is that id is defined as an integer, rather than as ownseq. This is what would happen if you used the SERIAL pseudo-type to create the sequence.

其他提示

Try

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

or don't create the sequence ownseq and let postgres do it for you:

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

In the above case the name of the sequence postgres has create should be products_id_seq.

Hope this helps.

PostgreSQL is powerful and you have just been bitten by an advanced feature.

Your DDL is quite valid but not at all what you think it is.

A sequence can be thought of as an extra-transactional simple table used for generating next values for some columns.

What you meant to do

You meant to have the id field defined thus, as per the other answer:

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

What you did

What you did was actually define a nested data structure for your table. Suppose I create a test sequence:

CREATE SEQUENCE testseq;

Then suppose I \d testseq on Pg 9.1, I get:

           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

This is the definition of the type the sequence used.

Now suppose I:

 create table seqtest (test testseq, id serial);

I can insert into it:

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

I can then select from it:

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

Moreover I can expand test:

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)

This sort of thing is actually very powerful in PostgreSQL but full of unexpected corners (for example not null and check constraints don't work as expected with nested data types). I don't generally recommend nested data types, but it is worth knowing that PostgreSQL can do this and will be happy to accept SQL commands to do it without warning.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top