문제

I have postgres database, I my application is build on using django and I used south migration to maintain the database schema. I have following scenario:

user_table has a foreign key relationship with userclickstream_stream and userclickstream_click has a foreign key relationship with user_stream_table.

I want to delete all the records in userclickstream_stream and userclickstream_click. But I don't want to delete any record in the user_table. What is the best way to accomplish this?

Here is how my user_stream_table looks like:

                                    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

Here is how the 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

It would be great if there is a good SQL way to take care of this rather than going the south migration route. If not I was thinking to do following:

I was thinking simply delete the record in south migration history table and re-build the schema using south I am not really sure if thats the right way to go. But to do that I need to drop the these two tables first. I might not be able to drop the table due to the foreign key relationship.

Lets say I drop it then I might be able to do the following since south migration history table doesn't have any record of these two tables.

./manage.py schemamigration userclickstream --initial
./manage.py migrate userclickstream
도움이 되었습니까?

해결책

See here:

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

Restricting and cascading deletes are the two most common options. RESTRICT prevents deletion of a referenced row. NO ACTION means that if any referencing rows still exist when the constraint is checked, an error is raised; this is the default behavior if you do not specify anything. (The essential difference between these two choices is that NO ACTION allows the check to be deferred until later in the transaction, whereas RESTRICT does not.) CASCADE specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well. There are two other options: SET NULL and SET DEFAULT. These cause the referencing column(s) in the referencing row(s) to be set to nulls or their default values, respectively, when the referenced row is deleted. Note that these do not excuse you from observing any constraints. For example, if an action specifies SET DEFAULT but the default value would not satisfy the foreign key constraint, the operation will fail.

Analogous to ON DELETE there is also ON UPDATE which is invoked when a referenced column is changed (updated). The possible actions are the same. In this case, CASCADE means that the updated values of the referenced column(s) should be copied into the referencing row(s).

Normally, a referencing row need not satisfy the foreign key constraint if any of its referencing columns are null. If MATCH FULL is added to the foreign key declaration, a referencing row escapes satisfying the constraint only if all its referencing columns are null (so a mix of null and non-null values is guaranteed to fail a MATCH FULL constraint). If you don't want referencing rows to be able to avoid satisfying the foreign key constraint, declare the referencing column(s) as NOT NULL.

A foreign key must reference columns that either are a primary key or form a unique constraint. This means that the referenced columns always have an index (the one underlying the primary key or unique constraint); so checks on whether a referencing row has a match will be efficient. Since a DELETE of a row from the referenced table or an UPDATE of a referenced column will require a scan of the referencing table for rows matching the old value, it is often a good idea to index the referencing columns too. Because this is not always needed, and there are many choices available on how to index, declaration of a foreign key constraint does not automatically create an index on the referencing columns.

Seems you just need to setup a proper ON DELETE action which is best suited for your case.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top