1

我有 2 张桌子:

“客户”和“地址”。一个客户可以有多个地址,因此它们具有“n:m”关系。出于这个原因,我也有表“customer-addr”。

这就是我的表格的样子:

                    +---------------+       
+-----------+       | customer_addr |       
| customers |       +---------------+       +-----------+
+-----------+       | id            |       | addresses |
| id        | <---> | cid           |       +-----------+
| name      |       | aid           | <---> | id        |
+-----------+       +---------------+       | address   |
                                            +-----------+

我需要更新所有客户数据,包括。所有地址。出于这个原因,我考虑先删除所有现有地址,然后更新客户表,然后再创建每个新地址。

我的问题:如何有效地删除一位客户的所有现有地址?(我必须从 2 个表中删除行)。

有没有我可以使用的单一语句?(没有级联方法,这太冒险了)

或者我可以用 2 个语句而不使用子选择吗?

最好的方法是什么?

请注意,我正在使用 postgresql

编辑:

我的整个数据库设计更复杂,地址表不仅来自“客户”,还来自“供应商”、“bulkbuyers”、..

每个地址仅属于一位客户或一位供应商或一位大宗采购商。(没有地址被多个家长使用/没有地址共享)

曾经的客户/供应商/.. 可以有多个地址。

出于这个原因,来自 zebediah49 的编辑解决方案将不起作用,因为它还会删除每个供应商/bulkbuyer/...的所有地址

4

2 回答 2

2

我会在PostgreSQL 9.1 或更高版本中使用可写的 CTE,也称为数据修改 CTE :

WITH del AS (
   DELETE FROM customer_addr
   WHERE  cid = $kill_this_cid
   RETURNING aid
   )
DELETE FROM addresses a
USING  (SELECT DISTINCT aid FROM del) d
WHERE  a.id = d.aid;

这应该是最快和最安全的。

如果(cid, aid)在中定义UNIQUEcustomer_addr则不需要该DISTINCT步骤:

...
DELETE FROM addresses a
USING  del d
WHERE  a.id = d.aid;
于 2013-08-01T16:41:34.137 回答
1

编辑:

知道了; 这更安全,因为无论如何都有两个客户共享地址的风险:

DELETE FROM customer_addr WHERE cid = $TARGET_CID;
DELETE FROM addresses WHERE id NOT IN (SELECT aid FROM customer_addr);

首先,删除所有引用,然后删除所有未引用的地址。请注意,例如,您可以只执行第一步,稍后再运行“清理”第二步。


我建议两步交易:

DELETE FROM addresses WHERE id IN (SELECT ca.aid FROM customers c LEFT JOIN customer_addr ca ON ca.cid=c.id WHERE c.name='$NAME_TO_DELETE');
DELETE FROM customer_addr WHERE cid = (SELECT id FROM customers WHERE name='$NAME_TO_DELETE');

如果您已经有客户 ID(编辑:您有),您可以跳过大部分内容:

DELETE FROM addresses WHERE id IN (SELECT aid FROM customer_addr WHERE cid=$TARGET_CID);
DELETE FROM customer_addr WHERE cid = $TARGET_CID;

用适当的事务BEGIN/包装它们END,以确保您不会最终处于不一致的状态,并且您应该进行设置。

于 2013-08-01T16:18:05.423 回答