从另一个 table 插入值并使用返回值更新原始 table
Insert values from another table and update original table with returning values
我是 PostgreSQL(甚至是 Whosebug)的新手。
比如说,我有两个 tables Order
和 Delivery
:
Order
id product address delivery_id
--------------------------------------------------
1 apple mac street (null)
3 coffee java island (null)
4 window micro street (null)
Delivery
id address
----------------
Delivery.id
和 Order.id
是自动递增的序列列。
table Delivery
当前为空。
我想将 Order.address
移动到 Delivery.address
并将其 Delivery.id
移动到 Order.delivery_id
以达到此状态:
Order
id product address delivery_id
--------------------------------------------------
1 apple mac street 1
5 coffee java island 2
7 window micro street 3
Delivery
id address
---------------------
1 mac street
2 java island
3 micro street
然后我将删除 Order.address
。
我为 Oracle 找到了类似的问题,但未能将其转换为 PostgreSQL:
我仍然认为应该可以在 Postgres 中使用带有 RETURNING
子句的普通 SQL 语句和随后的 INSERT
。
我试过这个(以及一些变体):
WITH ids AS (
INSERT INTO Delivery (address)
SELECT address
FROM Order
RETURNING Delivery.id AS d_id, Order.id AS o_id
)
UPDATE Order
SET Delivery_id = d_id
FROM ids
WHERE Order.id = ids.o_id;
最近一次尝试失败:
ERROR: missing FROM-clause entry for table "Delivery" LINE 1: ...address Order RETURNING Delivery.id...
如何正确执行此操作?
首先,ORDER
是一个reserved word。不要将其用作标识符。假设 orders
为 table nae。
WITH ids AS (
INSERT INTO delivery (address)
SELECT DISTINCT address
FROM orders
ORDER BY address -- optional
RETURNING *
)
UPDATE orders o
SET delivery_id = i.id
FROM ids i
WHERE o.address = i.address;
您必须考虑 order.address
中可能的重复项。 SELECT DISTINCT
生成唯一地址。
在外部 UPDATE
我们现在可以在 address
上重新加入,因为 delivery.address
是独一无二的。您可能应该在该声明之外保持这种方式,并在该列上添加一个 UNIQUE
constraint。
有效地导致 delivery
和 orders
之间的一对多关系。 delivery
中的一行在 orders
中可以有许多对应的行。考虑通过相应地添加 FOREIGN KEY
constraint 来强制实施。
此语句享有从空 delivery
table 开始的好处。如果 delivery
不为空,我们将不得不使用 UPSERT 而不是 INSERT
。参见:
相关:
- Insert data in 3 tables at a time using Postgres
关于您收到的错误消息的原因:
如果可以,只使用合法的小写标识符。参见:
- Are PostgreSQL column names case-sensitive?
您不能在 CTE 查询的 RETURNING 子句中 return 来自 FROM 关系的列。您必须在游标中管理它,或者将 order_id 列添加到 Delivery table,像这样:
ALTER TABLE Delivery ADD COLUMNN order_id INTEGER:
INSERT INTO Delivery (address, order_id)
SELECT address, id
FROM Order
;
WITH q_ids AS
(
SELECT id, order_id
FROM Delivery
)
UPDATE Order
SET delivery_id = q_ids.id
FROM q_ids
WHERE Order.id = q_ids.order_id;
我是 PostgreSQL(甚至是 Whosebug)的新手。
比如说,我有两个 tables Order
和 Delivery
:
Order
id product address delivery_id
--------------------------------------------------
1 apple mac street (null)
3 coffee java island (null)
4 window micro street (null)
Delivery
id address
----------------
Delivery.id
和 Order.id
是自动递增的序列列。
table Delivery
当前为空。
我想将 Order.address
移动到 Delivery.address
并将其 Delivery.id
移动到 Order.delivery_id
以达到此状态:
Order
id product address delivery_id
--------------------------------------------------
1 apple mac street 1
5 coffee java island 2
7 window micro street 3
Delivery
id address
---------------------
1 mac street
2 java island
3 micro street
然后我将删除 Order.address
。
我为 Oracle 找到了类似的问题,但未能将其转换为 PostgreSQL:
我仍然认为应该可以在 Postgres 中使用带有 RETURNING
子句的普通 SQL 语句和随后的 INSERT
。
我试过这个(以及一些变体):
WITH ids AS (
INSERT INTO Delivery (address)
SELECT address
FROM Order
RETURNING Delivery.id AS d_id, Order.id AS o_id
)
UPDATE Order
SET Delivery_id = d_id
FROM ids
WHERE Order.id = ids.o_id;
最近一次尝试失败:
ERROR: missing FROM-clause entry for table "Delivery" LINE 1: ...address Order RETURNING Delivery.id...
如何正确执行此操作?
首先,ORDER
是一个reserved word。不要将其用作标识符。假设 orders
为 table nae。
WITH ids AS (
INSERT INTO delivery (address)
SELECT DISTINCT address
FROM orders
ORDER BY address -- optional
RETURNING *
)
UPDATE orders o
SET delivery_id = i.id
FROM ids i
WHERE o.address = i.address;
您必须考虑 order.address
中可能的重复项。 SELECT DISTINCT
生成唯一地址。
在外部 UPDATE
我们现在可以在 address
上重新加入,因为 delivery.address
是独一无二的。您可能应该在该声明之外保持这种方式,并在该列上添加一个 UNIQUE
constraint。
有效地导致 delivery
和 orders
之间的一对多关系。 delivery
中的一行在 orders
中可以有许多对应的行。考虑通过相应地添加 FOREIGN KEY
constraint 来强制实施。
此语句享有从空 delivery
table 开始的好处。如果 delivery
不为空,我们将不得不使用 UPSERT 而不是 INSERT
。参见:
相关:
- Insert data in 3 tables at a time using Postgres
关于您收到的错误消息的原因:
如果可以,只使用合法的小写标识符。参见:
- Are PostgreSQL column names case-sensitive?
您不能在 CTE 查询的 RETURNING 子句中 return 来自 FROM 关系的列。您必须在游标中管理它,或者将 order_id 列添加到 Delivery table,像这样:
ALTER TABLE Delivery ADD COLUMNN order_id INTEGER:
INSERT INTO Delivery (address, order_id)
SELECT address, id
FROM Order
;
WITH q_ids AS
(
SELECT id, order_id
FROM Delivery
)
UPDATE Order
SET delivery_id = q_ids.id
FROM q_ids
WHERE Order.id = q_ids.order_id;