如何添加到 table 然后将 id 用于不同的查询?
How do I add to a table and then use the id for a different query?
我有三个 tables,我用这些查询创建的:
create table parents(
rowid serial primary key,
display_name varchar,
unique(display_name)
);
create table clients(
rowid serial primary key,
parent int,
display_name varchar,
foreign key (parent) references parents(rowid),
unique(display_name, parent)
);
create table datapoints(
rowid serial primary key,
client int,
val float8,
foreign key (client) references clients(rowid)
);
我正在获取包含 parent 名称、客户名称和一些值的数据。每次获取此数据时,我都想向数据点 table 添加行。我还想向客户端和 parents table 添加行,但前提是我收到的数据具有无法识别的名称。
例如,我可能会得到这个数据:
"parent1-client1-123.0"
我想要实现的是(在查询中)以这种方式处理此数据:
如果需要,在“parents”table 中插入一行。
如果需要,使用适当的 parent ID(在上一步中获得?)向“客户”table 插入一行。
使用适当的客户端 ID(在上一步中获得?)向“数据点”插入一行 table。
我如何通过查询来管理它?我的程序员想写:
- 如果需要,插入 parents。将合适的parent的id保存在变量“current_parent”
中
- 如果需要,使用“current_parent”变量插入客户端。将适当客户端的 ID 保存在变量“current_client”中。
- 使用上一个中的“current_client”变量插入数据点。步骤.
但显然这不是 sql 的工作方式,对吧?如果我有 5 个或 10 个而不是这三个“嵌套”table 怎么办?(!)
请帮忙
Postgres 可以 return 插入时生成的键。不幸的是,当它遇到现有的唯一键和 on constraint
子句时,它不会 return 现有的键。 (一个猜测,但你可能已经发现了这一点。)然而,你的程序员离你不远了。您不是 检索并保存 id,而是直接通过 select 检索 检索并使用 。如果需要进行后续操作你只需'repeat'检索即可。因此,对于 3 级,您可以为第二级(客户端)和第三级(数据点)检索第一级值(父 rowid)。最好的(恕我直言)只是创建一个处理 3 个级别的过程。此外,在调用过程之前将输入分解为组件。结果过程变为:
create or replace procedure establisth_parent_client_datapoint(
parent_name_in varchar
, client_name_in varchar
, val_in float8
)
language sql
as $$
insert into parents (display_name)
values (parent_name_in)
on conflict (display_name)
do nothing;
insert into clients(display_name, parent)
select client_name_in
, p.rowid
from parents p
where p.display_name = parent_name_in
on conflict (display_name, parent)
do nothing;
insert into datapoints(val, client)
select val_in, c.rowid
from parents p
join clients c
on ( c.parent = p.rowid)
where c.display_name = client_name_in
and p.display_name = parent_name_in;
$$;
由于我不知道您的开发语言,我将在 Postgres DO block
中提供示例。参见 demo here。
至于有 5-10 个嵌套表,您只需要为每个表重复基本过程。当然有 10 个嵌套表,我可能会质疑设计。
我有三个 tables,我用这些查询创建的:
create table parents(
rowid serial primary key,
display_name varchar,
unique(display_name)
);
create table clients(
rowid serial primary key,
parent int,
display_name varchar,
foreign key (parent) references parents(rowid),
unique(display_name, parent)
);
create table datapoints(
rowid serial primary key,
client int,
val float8,
foreign key (client) references clients(rowid)
);
我正在获取包含 parent 名称、客户名称和一些值的数据。每次获取此数据时,我都想向数据点 table 添加行。我还想向客户端和 parents table 添加行,但前提是我收到的数据具有无法识别的名称。
例如,我可能会得到这个数据:
"parent1-client1-123.0"
我想要实现的是(在查询中)以这种方式处理此数据:
如果需要,在“parents”table 中插入一行。
如果需要,使用适当的 parent ID(在上一步中获得?)向“客户”table 插入一行。
使用适当的客户端 ID(在上一步中获得?)向“数据点”插入一行 table。
我如何通过查询来管理它?我的程序员想写:
- 如果需要,插入 parents。将合适的parent的id保存在变量“current_parent” 中
- 如果需要,使用“current_parent”变量插入客户端。将适当客户端的 ID 保存在变量“current_client”中。
- 使用上一个中的“current_client”变量插入数据点。步骤.
但显然这不是 sql 的工作方式,对吧?如果我有 5 个或 10 个而不是这三个“嵌套”table 怎么办?(!)
请帮忙
Postgres 可以 return 插入时生成的键。不幸的是,当它遇到现有的唯一键和 on constraint
子句时,它不会 return 现有的键。 (一个猜测,但你可能已经发现了这一点。)然而,你的程序员离你不远了。您不是 检索并保存 id,而是直接通过 select 检索 检索并使用 。如果需要进行后续操作你只需'repeat'检索即可。因此,对于 3 级,您可以为第二级(客户端)和第三级(数据点)检索第一级值(父 rowid)。最好的(恕我直言)只是创建一个处理 3 个级别的过程。此外,在调用过程之前将输入分解为组件。结果过程变为:
create or replace procedure establisth_parent_client_datapoint(
parent_name_in varchar
, client_name_in varchar
, val_in float8
)
language sql
as $$
insert into parents (display_name)
values (parent_name_in)
on conflict (display_name)
do nothing;
insert into clients(display_name, parent)
select client_name_in
, p.rowid
from parents p
where p.display_name = parent_name_in
on conflict (display_name, parent)
do nothing;
insert into datapoints(val, client)
select val_in, c.rowid
from parents p
join clients c
on ( c.parent = p.rowid)
where c.display_name = client_name_in
and p.display_name = parent_name_in;
$$;
由于我不知道您的开发语言,我将在 Postgres DO block
中提供示例。参见 demo here。
至于有 5-10 个嵌套表,您只需要为每个表重复基本过程。当然有 10 个嵌套表,我可能会质疑设计。