可以说我有一张桌子:
Column | Type | Notes
---------+------------ +----------------------------------------------------------
id | integer | An ID that's FK to some other table
seq | integer | Each ID gets its own seq number
data | text | Just some text, totally irrelevant.
Run Code Online (Sandbox Code Playgroud)
id+ seq是组合键.
我想看到的是:
ID | SEQ | DATA
----+------ +----------------------------------------------
1 | 1 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
1 | 2 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
1 | 3 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
1 | 4 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
2 | 1 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
3 | 1 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
3 | 2 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
3 | 3 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
3 | 4 | Quick brown fox, lorem ipsum, lazy dog, etc etc.
Run Code Online (Sandbox Code Playgroud)
如您所见,组合id和seq独特.
我不知道如何设置我的表(或插入语句?)来做到这一点.我想插入,id并data导致seq依赖于子序列id.
Jay*_*nek 22
没问题!我们将让两个表,things和stuff.stuff将是您在问题中描述的表格,并且things是它所引用的表格:
CREATE TABLE things (
id serial primary key,
name text
);
CREATE TABLE stuff (
id integer references things,
seq integer NOT NULL,
notes text,
primary key (id, seq)
);
Run Code Online (Sandbox Code Playgroud)
然后我们将设置things一个触发器,每次创建一行时都会创建一个新序列:
CREATE FUNCTION make_thing_seq() RETURNS trigger
LANGUAGE plpgsql
AS $$
begin
execute format('create sequence thing_seq_%s', NEW.id);
return NEW;
end
$$;
CREATE TRIGGER make_thing_seq AFTER INSERT ON things FOR EACH ROW EXECUTE PROCEDURE make_thing_seq();
Run Code Online (Sandbox Code Playgroud)
现在,我们将结束与thing_seq_1,thing_seq_2等,等...
现在是另一个触发器,stuff以便每次使用正确的序列:
CREATE FUNCTION fill_in_stuff_seq() RETURNS trigger
LANGUAGE plpgsql
AS $$
begin
NEW.seq := nextval('thing_seq_' || NEW.id);
RETURN NEW;
end
$$;
CREATE TRIGGER fill_in_stuff_seq BEFORE INSERT ON stuff FOR EACH ROW EXECUTE PROCEDURE fill_in_stuff_seq();
Run Code Online (Sandbox Code Playgroud)
这将确保当行进入时stuff,该id列用于查找要调用的正确序列nextval.
这是一个演示:
test=# insert into things (name) values ('Joe');
INSERT 0 1
test=# insert into things (name) values ('Bob');
INSERT 0 1
test=# select * from things;
id | name
----+------
1 | Joe
2 | Bob
(2 rows)
test=# \d
List of relations
Schema | Name | Type | Owner
--------+---------------+----------+----------
public | stuff | table | jkominek
public | thing_seq_1 | sequence | jkominek
public | thing_seq_2 | sequence | jkominek
public | things | table | jkominek
public | things_id_seq | sequence | jkominek
(5 rows)
test=# insert into stuff (id, notes) values (1, 'Keychain');
INSERT 0 1
test=# insert into stuff (id, notes) values (1, 'Pet goat');
INSERT 0 1
test=# insert into stuff (id, notes) values (2, 'Family photo');
INSERT 0 1
test=# insert into stuff (id, notes) values (1, 'Redundant lawnmower');
INSERT 0 1
test=# select * from stuff;
id | seq | notes
----+-----+---------------------
1 | 1 | Keychain
1 | 2 | Pet goat
2 | 1 | Family photo
1 | 3 | Redundant lawnmower
(4 rows)
test=#
Run Code Online (Sandbox Code Playgroud)
Joe*_*lli 17
您可以使用窗口函数来分配SEQ值,例如:
INSERT INTO YourTable
(ID, SEQ, DATA)
SELECT ID, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY DATA), DATA
FROM YourSource
Run Code Online (Sandbox Code Playgroud)
如果seq反映(或应该反映)插入行的顺序,我宁愿使用timestamp自动填充并在使用row_number()以下方法选择行时动态生成序列号:
create table some_table
(
id integer not null,
inserted_at timestamp not null default current_timestamp,
data text
);
Run Code Online (Sandbox Code Playgroud)
要获取seq列,您可以执行以下操作:
select id,
row_number() over (partition by id order by inserted_at) as seq,
data
from some_table
order by id, seq;
Run Code Online (Sandbox Code Playgroud)
然而,与使用持久seq列(尤其是在 上有索引的情况下id, seq)相比,选择会慢一点。
如果这成为一个问题,您可以考虑使用物化视图,或者添加seq列然后定期更新它(出于性能原因,我不会在触发器中这样做)。
SQLFiddle 示例:http ://sqlfiddle.com/#!15/db69b/1
| 归档时间: |
|
| 查看次数: |
9674 次 |
| 最近记录: |