Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make ON DELETE CASCADE work in sqlite 3.7.4?

Tags:

python

sql

sqlite

I checked the feature list several times, and it seems that cascading should work. When I execute this python script:

#!/usr/bin/env python3
import sqlite3

print(sqlite3.sqlite_version)

con = sqlite3.connect(':memory:')

a = "create table a (id integer primary key, name text)"
con.execute(a)

b = "create table b (id integer primary key, r integer, foreign key(r) references a(id) on delete cascade)"
con.execute(b)
con.commit()

a = "insert into a (name) values (\"abc\")"
con.execute(a)
con.commit()

print(con.execute("select * from a").fetchall())

a = "insert into b (r) values (1)"
con.execute(a)
con.commit()

print(con.execute("select * from b").fetchall())

a = "delete from a where id=1"
con.execute(a)
con.commit()

print(con.execute("select * from b").fetchall())
print(con.execute("select * from a").fetchall())

I get these results:

3.7.4
[(1, 'abc')]
[(1, 1)]
[(1, 1)]
[]

Which proves that cascading didn't happened. What I did wrong or what are the solutions to get same result as cascading?

like image 503
kravitz Avatar asked Dec 18 '10 08:12

kravitz


People also ask

How do you use cascading delete?

Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.

Is Cascade delete a good idea?

Why sql server cascade delete is bad? sql server cascade delete should not cause an unexpected loss of data. If a delete requires related records to be deleted, and the user needs to know that those records are going to go away, then cascading deletes should not be used.

What is on delete cascade and on update cascade?

1) ON DELETE CASCADE means if the parent record is deleted, then any referencing child records are also deleted. ON UPDATE defaults to RESTRICT, which means the UPDATE on the parent record will fail.


2 Answers

SQLite foreign keys are disabled for compatibility purposes. You need to enable them manually right after each connection to the database.

con.execute("PRAGMA foreign_keys = ON")

like image 69
Rosh Oxymoron Avatar answered Oct 12 '22 12:10

Rosh Oxymoron


There's a better answer by user Thibault J over in this question: Enable integrity checking with sqlite in django which says:

from django.db.backends.signals import connection_created
def activate_foreign_keys(sender, connection, **kwargs):
    """Enable integrity constraint with sqlite."""
    if connection.vendor == 'sqlite':
        cursor = connection.cursor()
        cursor.execute('PRAGMA foreign_keys = ON;')

connection_created.connect(activate_foreign_keys)
like image 35
slacy Avatar answered Oct 12 '22 13:10

slacy