【问题标题】:postgres: Delete rows that has foreign key while not deleting data of the foreign key tablepostgres:删除有外键的行,不删除外键表的数据
【发布时间】:2014-02-09 19:49:32
【问题描述】:

我有 postgres 数据库,我的应用程序是使用 django 构建的,我使用 south migration 来维护数据库架构。我有以下情况:

user_tableuserclickstream_stream 具有外键关系,userclickstream_click 与 user_stream_table 具有外键关系。

我想删除userclickstream_streamuserclickstream_click 中的所有记录。但我不想删除 user_table 中的任何记录。实现这一目标的最佳方法是什么?

这是我的 user_stream_table 的样子:

                                    Table "public.userclickstream_stream"
   Column    |           Type           |                              Modifiers                              
-------------+--------------------------+---------------------------------------------------------------------
 id          | integer                  | not null default nextval('userclickstream_stream_id_seq'::regclass)
 session_key | character varying(40)    | not null
 ip_address  | character varying(40)    | not null
 referrer    | text                     | 
 create_date | timestamp with time zone | not null
 last_update | timestamp with time zone | not null
 user_id     | integer                  | 
Indexes:
    "userclickstream_stream_pkey" PRIMARY KEY, btree (id)
    "userclickstream_stream_session_key_key" UNIQUE CONSTRAINT, btree (session_key)
    "userclickstream_stream_user_id" btree (user_id)
Foreign-key constraints:
    "user_id_refs_id_773d100c" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
Referenced by:
    TABLE "userclickstream_click" CONSTRAINT "stream_id_refs_id_4c08df60" FOREIGN KEY (stream_id) REFERENCES userclickstream_stream(id) DEFERRABLE INITIALLY DEFERRED

这是 User_click_table 的方式

                                    Table "public.userclickstream_click"
   Column    |           Type           |                             Modifiers                              
-------------+--------------------------+--------------------------------------------------------------------
 id          | integer                  | not null default nextval('userclickstream_click_id_seq'::regclass)
 stream_id   | integer                  | not null
 url         | text                     | not null
 path        | text                     | not null
 create_date | timestamp with time zone | not null
Indexes:
    "userclickstream_click_pkey" PRIMARY KEY, btree (id)
    "userclickstream_click_stream_id" btree (stream_id)
Foreign-key constraints:
    "stream_id_refs_id_4c08df60" FOREIGN KEY (stream_id) REFERENCES userclickstream_stream(id) DEFERRABLE INITIALLY DEFERRED

如果有一个很好的 SQL 方法来解决这个问题,而不是走南迁移路线,那就太好了。如果不是,我正在考虑执行以下操作:

我在想只是删除南迁移历史表中的记录并使用南重新构建架构我不确定这是否是正确的方法。但要做到这一点,我需要先删除这两个表。由于外键关系,我可能无法删除表。

假设我放弃它,那么我可能能够执行以下操作,因为南迁移历史表没有这两个表的任何记录。

./manage.py schemamigration userclickstream --initial
./manage.py migrate userclickstream

【问题讨论】:

  • 您对表格的描述与表格名称不匹配。请更正一下。
  • @MikeSherrill'Catcall' 完成,谢谢,
  • 除了级联删除之外,您真的需要做任何事情吗? Django syntax

标签: sql database django postgresql django-south


【解决方案1】:

看这里:

http://www.postgresql.org/docs/9.3/static/ddl-constraints.html

限制和级联删除是两个最常见的选项。 RESTRICT 防止删除引用的行。 NO ACTION 表示如果在检查约束时仍然存在任何引用行,则会引发错误;如果您不指定任何内容,这是默认行为。 (这两种选择之间的本质区别在于 NO ACTION 允许将检查推迟到事务的后期,而 RESTRICT 不允许。) CASCADE 指定当一个引用的行被删除时,引用它的行应该被自动删除也是。还有两个其他选项:SET NULL 和 SET DEFAULT。当被引用的行被删除时,这些会导致引用行中的引用列被分别设置为空值或它们的默认值。请注意,这些并不能成为您遵守任何约束的借口。例如,如果某个操作指定了 SET DEFAULT,但默认值不满足外键约束,则操作将失败。

与 ON DELETE 类似,还有一个 ON UPDATE,它在引用的列被更改(更新)时被调用。可能的动作是一样的。在这种情况下,CASCADE 意味着应将引用列的更新值复制到引用行中。

通常,如果引用行的任何引用列为空,则引用行不需要满足外键约束。如果将 MATCH FULL 添加到外键声明中,则仅当引用行的所有引用列都为 null 时,引用行才会满足约束(因此保证 null 和非 null 值的混合会导致 MATCH FULL 约束失败)。如果您不希望引用行能够避免满足外键约束,请将引用列声明为 NOT NULL。

外键必须引用作为主键或形成唯一约束的列。这意味着被引用的列总是有一个索引(主键或唯一约束的基础);因此检查引用行是否匹配将是有效的。由于从引用表中删除行或更新引用列将需要扫描引用表以查找与旧值匹配的行,因此索引引用列通常也是一个好主意。因为这并不总是需要,而且有很多关于如何索引的选择,外键约束的声明不会自动在引用列上创建索引。

似乎您只需要设置一个最适合您的情况的正确 ON DELETE 操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    相关资源
    最近更新 更多