Sqlite / SQLAlchemy: how to enforce Foreign Keys?
The new version of SQLite has the ability to enforce Foreign Key constraints, but for the sake of backwards-compatibility, you have to turn it on for each database connection separately!
sqlite> PRAGMA foreign_keys = ON;
I am using SQLAlchemy -- how can I make sure this always gets turned on?
What I have tried is this:
engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True)
engine.execute('pragma foreign_keys=on')
...but it is not working!...What am I missing?
EDIT:
I think my real problem is that I have more than one version of SQLite installed, and Python is not using the latest one!
>>> import sqlite3
>>> print sqlite3.sqlite_version
3.3.4
But I just downloaded 3.6.23 and put the exe in my project directory!
How can I figure out which .exe it's using, and change it?
python sqlite foreign-keys sqlalchemy
add a comment |
The new version of SQLite has the ability to enforce Foreign Key constraints, but for the sake of backwards-compatibility, you have to turn it on for each database connection separately!
sqlite> PRAGMA foreign_keys = ON;
I am using SQLAlchemy -- how can I make sure this always gets turned on?
What I have tried is this:
engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True)
engine.execute('pragma foreign_keys=on')
...but it is not working!...What am I missing?
EDIT:
I think my real problem is that I have more than one version of SQLite installed, and Python is not using the latest one!
>>> import sqlite3
>>> print sqlite3.sqlite_version
3.3.4
But I just downloaded 3.6.23 and put the exe in my project directory!
How can I figure out which .exe it's using, and change it?
python sqlite foreign-keys sqlalchemy
add a comment |
The new version of SQLite has the ability to enforce Foreign Key constraints, but for the sake of backwards-compatibility, you have to turn it on for each database connection separately!
sqlite> PRAGMA foreign_keys = ON;
I am using SQLAlchemy -- how can I make sure this always gets turned on?
What I have tried is this:
engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True)
engine.execute('pragma foreign_keys=on')
...but it is not working!...What am I missing?
EDIT:
I think my real problem is that I have more than one version of SQLite installed, and Python is not using the latest one!
>>> import sqlite3
>>> print sqlite3.sqlite_version
3.3.4
But I just downloaded 3.6.23 and put the exe in my project directory!
How can I figure out which .exe it's using, and change it?
python sqlite foreign-keys sqlalchemy
The new version of SQLite has the ability to enforce Foreign Key constraints, but for the sake of backwards-compatibility, you have to turn it on for each database connection separately!
sqlite> PRAGMA foreign_keys = ON;
I am using SQLAlchemy -- how can I make sure this always gets turned on?
What I have tried is this:
engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True)
engine.execute('pragma foreign_keys=on')
...but it is not working!...What am I missing?
EDIT:
I think my real problem is that I have more than one version of SQLite installed, and Python is not using the latest one!
>>> import sqlite3
>>> print sqlite3.sqlite_version
3.3.4
But I just downloaded 3.6.23 and put the exe in my project directory!
How can I figure out which .exe it's using, and change it?
python sqlite foreign-keys sqlalchemy
python sqlite foreign-keys sqlalchemy
edited Apr 13 '10 at 22:48
Nick Perkins
asked Apr 10 '10 at 21:07
Nick PerkinsNick Perkins
4,34153238
4,34153238
add a comment |
add a comment |
7 Answers
7
active
oldest
votes
I now have this working:
Download the latest sqlite and pysqlite2 builds as described above: make sure correct versions are being used at runtime by python.
import sqlite3
import pysqlite2
print sqlite3.sqlite_version # should be 3.6.23.1
print pysqlite2.__path__ # eg C:\Python26\lib\site-packages\pysqlite2
Next add a PoolListener:
from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
engine = create_engine(database_url, listeners=[ForeignKeysListener()])
Then be careful how you test if foreign keys are working: I had some confusion here. When using sqlalchemy ORM to add() things my import code was implicitly handling the relation hookups so could never fail. Adding 'nullable=False' to some ForeignKey() statements helped me here.
The way I test sqlalchemy sqlite foreign key support is enabled is to do a manual insert from a declarative ORM class:
# example
ins = Coverage.__table__.insert().values(id = 99,
description = 'Wrong',
area = 42.0,
wall_id = 99, # invalid fkey id
type_id = 99) # invalid fkey_id
session.execute(ins)
Here 'wall_id' and 'type_id' are both ForeignKey()'s and sqlite throws an exception correctly now if trying to hookup invalid fkeys. So it works! If you remove the listener then sqlalchemy will happily add invalid entries.
I believe the main problem may be multiple sqlite3.dll's (or .so) lying around.
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
add a comment |
For recent versions (SQLAlchemy ~0.7) the SQLAlchemy homepage says:
PoolListener is deprecated. Please refer to PoolEvents.
Then the example by CarlS becomes:
engine = create_engine(database_url)
def _fk_pragma_on_connect(dbapi_con, con_record):
dbapi_con.execute('pragma foreign_keys=ON')
from sqlalchemy import event
event.listen(engine, 'connect', _fk_pragma_on_connect)
2
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
add a comment |
Building on the answers from conny and shadowmatter, here's code that will check if you are using SQLite3 before emitting the PRAGMA statement:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
Thanks. This works for those of us who prefer thedb = SQLAlchemy(app)approach as well.
– Matthew Moisen
May 28 '16 at 20:13
this also does the magic forpandas.to_sqlas well, just copy it at the begining of the file that creates the session...
– toto_tico
Apr 23 '18 at 14:22
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
add a comment |
From the SQLite dialect page:
SQLite supports FOREIGN KEY syntax when emitting CREATE statements for tables, however by default these constraints have no effect on the operation of the table.
Constraint checking on SQLite has three prerequisites:
- At least version 3.6.19 of SQLite must be in use
- The SQLite libary must be compiled without the SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER symbols enabled.
- The PRAGMA foreign_keys = ON statement must be emitted on all connections before use.
SQLAlchemy allows for the PRAGMA statement to be emitted automatically for new connections through the usage of events:
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
add a comment |
As a simpler approach if your session creation is centralised behind a Python helper function (rather than exposing the SQLA engine directly), you can just issue "session.execute('pragma foreign_keys=on')" before returning the freshly created session.
You only need the pool listener approach if arbitrary parts of your application may create SQLA sessions against the database.
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
add a comment |
I had the same problem before (scripts with foreign keys constraints were going through but actuall constraints were not enforced by the sqlite engine); got it solved by:
downloading, building and installing the latest version of sqlite from here: sqlite-sqlite-amalgamation; before this I had sqlite 3.6.16 on my ubuntu machine; which didn't support foreign keys yet; it should be 3.6.19 or higher to have them working.
installing the latest version of pysqlite from here: pysqlite-2.6.0
after that I started getting exceptions whenever foreign key constraint failed
hope this helps, regards
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
add a comment |
If you need to execute something for setup on every connection, use a PoolListener.
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2614984%2fsqlite-sqlalchemy-how-to-enforce-foreign-keys%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
I now have this working:
Download the latest sqlite and pysqlite2 builds as described above: make sure correct versions are being used at runtime by python.
import sqlite3
import pysqlite2
print sqlite3.sqlite_version # should be 3.6.23.1
print pysqlite2.__path__ # eg C:\Python26\lib\site-packages\pysqlite2
Next add a PoolListener:
from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
engine = create_engine(database_url, listeners=[ForeignKeysListener()])
Then be careful how you test if foreign keys are working: I had some confusion here. When using sqlalchemy ORM to add() things my import code was implicitly handling the relation hookups so could never fail. Adding 'nullable=False' to some ForeignKey() statements helped me here.
The way I test sqlalchemy sqlite foreign key support is enabled is to do a manual insert from a declarative ORM class:
# example
ins = Coverage.__table__.insert().values(id = 99,
description = 'Wrong',
area = 42.0,
wall_id = 99, # invalid fkey id
type_id = 99) # invalid fkey_id
session.execute(ins)
Here 'wall_id' and 'type_id' are both ForeignKey()'s and sqlite throws an exception correctly now if trying to hookup invalid fkeys. So it works! If you remove the listener then sqlalchemy will happily add invalid entries.
I believe the main problem may be multiple sqlite3.dll's (or .so) lying around.
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
add a comment |
I now have this working:
Download the latest sqlite and pysqlite2 builds as described above: make sure correct versions are being used at runtime by python.
import sqlite3
import pysqlite2
print sqlite3.sqlite_version # should be 3.6.23.1
print pysqlite2.__path__ # eg C:\Python26\lib\site-packages\pysqlite2
Next add a PoolListener:
from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
engine = create_engine(database_url, listeners=[ForeignKeysListener()])
Then be careful how you test if foreign keys are working: I had some confusion here. When using sqlalchemy ORM to add() things my import code was implicitly handling the relation hookups so could never fail. Adding 'nullable=False' to some ForeignKey() statements helped me here.
The way I test sqlalchemy sqlite foreign key support is enabled is to do a manual insert from a declarative ORM class:
# example
ins = Coverage.__table__.insert().values(id = 99,
description = 'Wrong',
area = 42.0,
wall_id = 99, # invalid fkey id
type_id = 99) # invalid fkey_id
session.execute(ins)
Here 'wall_id' and 'type_id' are both ForeignKey()'s and sqlite throws an exception correctly now if trying to hookup invalid fkeys. So it works! If you remove the listener then sqlalchemy will happily add invalid entries.
I believe the main problem may be multiple sqlite3.dll's (or .so) lying around.
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
add a comment |
I now have this working:
Download the latest sqlite and pysqlite2 builds as described above: make sure correct versions are being used at runtime by python.
import sqlite3
import pysqlite2
print sqlite3.sqlite_version # should be 3.6.23.1
print pysqlite2.__path__ # eg C:\Python26\lib\site-packages\pysqlite2
Next add a PoolListener:
from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
engine = create_engine(database_url, listeners=[ForeignKeysListener()])
Then be careful how you test if foreign keys are working: I had some confusion here. When using sqlalchemy ORM to add() things my import code was implicitly handling the relation hookups so could never fail. Adding 'nullable=False' to some ForeignKey() statements helped me here.
The way I test sqlalchemy sqlite foreign key support is enabled is to do a manual insert from a declarative ORM class:
# example
ins = Coverage.__table__.insert().values(id = 99,
description = 'Wrong',
area = 42.0,
wall_id = 99, # invalid fkey id
type_id = 99) # invalid fkey_id
session.execute(ins)
Here 'wall_id' and 'type_id' are both ForeignKey()'s and sqlite throws an exception correctly now if trying to hookup invalid fkeys. So it works! If you remove the listener then sqlalchemy will happily add invalid entries.
I believe the main problem may be multiple sqlite3.dll's (or .so) lying around.
I now have this working:
Download the latest sqlite and pysqlite2 builds as described above: make sure correct versions are being used at runtime by python.
import sqlite3
import pysqlite2
print sqlite3.sqlite_version # should be 3.6.23.1
print pysqlite2.__path__ # eg C:\Python26\lib\site-packages\pysqlite2
Next add a PoolListener:
from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
engine = create_engine(database_url, listeners=[ForeignKeysListener()])
Then be careful how you test if foreign keys are working: I had some confusion here. When using sqlalchemy ORM to add() things my import code was implicitly handling the relation hookups so could never fail. Adding 'nullable=False' to some ForeignKey() statements helped me here.
The way I test sqlalchemy sqlite foreign key support is enabled is to do a manual insert from a declarative ORM class:
# example
ins = Coverage.__table__.insert().values(id = 99,
description = 'Wrong',
area = 42.0,
wall_id = 99, # invalid fkey id
type_id = 99) # invalid fkey_id
session.execute(ins)
Here 'wall_id' and 'type_id' are both ForeignKey()'s and sqlite throws an exception correctly now if trying to hookup invalid fkeys. So it works! If you remove the listener then sqlalchemy will happily add invalid entries.
I believe the main problem may be multiple sqlite3.dll's (or .so) lying around.
edited Apr 14 '10 at 1:30
answered Apr 11 '10 at 0:36
CarlSCarlS
38338
38338
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
add a comment |
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Did you use the PRAGMA the same way I have done?
– Nick Perkins
Apr 12 '10 at 23:10
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
Thanks, I got it working too. Indeed, the problem was multiple copies of SQLite on my machine...fixing that, and using the PoolListener have worked perfectly!
– Nick Perkins
Apr 21 '10 at 21:47
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
It works! But how to make it work with poolevent...
– 42n4
Sep 12 '14 at 18:02
add a comment |
For recent versions (SQLAlchemy ~0.7) the SQLAlchemy homepage says:
PoolListener is deprecated. Please refer to PoolEvents.
Then the example by CarlS becomes:
engine = create_engine(database_url)
def _fk_pragma_on_connect(dbapi_con, con_record):
dbapi_con.execute('pragma foreign_keys=ON')
from sqlalchemy import event
event.listen(engine, 'connect', _fk_pragma_on_connect)
2
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
add a comment |
For recent versions (SQLAlchemy ~0.7) the SQLAlchemy homepage says:
PoolListener is deprecated. Please refer to PoolEvents.
Then the example by CarlS becomes:
engine = create_engine(database_url)
def _fk_pragma_on_connect(dbapi_con, con_record):
dbapi_con.execute('pragma foreign_keys=ON')
from sqlalchemy import event
event.listen(engine, 'connect', _fk_pragma_on_connect)
2
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
add a comment |
For recent versions (SQLAlchemy ~0.7) the SQLAlchemy homepage says:
PoolListener is deprecated. Please refer to PoolEvents.
Then the example by CarlS becomes:
engine = create_engine(database_url)
def _fk_pragma_on_connect(dbapi_con, con_record):
dbapi_con.execute('pragma foreign_keys=ON')
from sqlalchemy import event
event.listen(engine, 'connect', _fk_pragma_on_connect)
For recent versions (SQLAlchemy ~0.7) the SQLAlchemy homepage says:
PoolListener is deprecated. Please refer to PoolEvents.
Then the example by CarlS becomes:
engine = create_engine(database_url)
def _fk_pragma_on_connect(dbapi_con, con_record):
dbapi_con.execute('pragma foreign_keys=ON')
from sqlalchemy import event
event.listen(engine, 'connect', _fk_pragma_on_connect)
edited Oct 27 '11 at 3:02
answered Oct 20 '11 at 4:36
connyconny
7,25553339
7,25553339
2
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
add a comment |
2
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
2
2
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
conny's answer is perfect for newer versions of sqlalchemy. Use it! Moderator should really pick this one as correct.
– David Parmenter
Feb 16 '13 at 12:14
add a comment |
Building on the answers from conny and shadowmatter, here's code that will check if you are using SQLite3 before emitting the PRAGMA statement:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
Thanks. This works for those of us who prefer thedb = SQLAlchemy(app)approach as well.
– Matthew Moisen
May 28 '16 at 20:13
this also does the magic forpandas.to_sqlas well, just copy it at the begining of the file that creates the session...
– toto_tico
Apr 23 '18 at 14:22
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
add a comment |
Building on the answers from conny and shadowmatter, here's code that will check if you are using SQLite3 before emitting the PRAGMA statement:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
Thanks. This works for those of us who prefer thedb = SQLAlchemy(app)approach as well.
– Matthew Moisen
May 28 '16 at 20:13
this also does the magic forpandas.to_sqlas well, just copy it at the begining of the file that creates the session...
– toto_tico
Apr 23 '18 at 14:22
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
add a comment |
Building on the answers from conny and shadowmatter, here's code that will check if you are using SQLite3 before emitting the PRAGMA statement:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
Building on the answers from conny and shadowmatter, here's code that will check if you are using SQLite3 before emitting the PRAGMA statement:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
answered Mar 21 '13 at 7:51
Kiran JonnalagaddaKiran Jonnalagadda
1,25811723
1,25811723
Thanks. This works for those of us who prefer thedb = SQLAlchemy(app)approach as well.
– Matthew Moisen
May 28 '16 at 20:13
this also does the magic forpandas.to_sqlas well, just copy it at the begining of the file that creates the session...
– toto_tico
Apr 23 '18 at 14:22
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
add a comment |
Thanks. This works for those of us who prefer thedb = SQLAlchemy(app)approach as well.
– Matthew Moisen
May 28 '16 at 20:13
this also does the magic forpandas.to_sqlas well, just copy it at the begining of the file that creates the session...
– toto_tico
Apr 23 '18 at 14:22
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
Thanks. This works for those of us who prefer the
db = SQLAlchemy(app) approach as well.– Matthew Moisen
May 28 '16 at 20:13
Thanks. This works for those of us who prefer the
db = SQLAlchemy(app) approach as well.– Matthew Moisen
May 28 '16 at 20:13
this also does the magic for
pandas.to_sql as well, just copy it at the begining of the file that creates the session...– toto_tico
Apr 23 '18 at 14:22
this also does the magic for
pandas.to_sql as well, just copy it at the begining of the file that creates the session...– toto_tico
Apr 23 '18 at 14:22
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
Thank you, this is the one to use. The reply by @CarlS (which I appreciate is from 2010) uses stuff that has now been deprecated (looking at SQLAlchemy v1.3) and hence does not work anymore.
– Ron Kalian
Dec 21 '18 at 16:06
add a comment |
From the SQLite dialect page:
SQLite supports FOREIGN KEY syntax when emitting CREATE statements for tables, however by default these constraints have no effect on the operation of the table.
Constraint checking on SQLite has three prerequisites:
- At least version 3.6.19 of SQLite must be in use
- The SQLite libary must be compiled without the SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER symbols enabled.
- The PRAGMA foreign_keys = ON statement must be emitted on all connections before use.
SQLAlchemy allows for the PRAGMA statement to be emitted automatically for new connections through the usage of events:
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
add a comment |
From the SQLite dialect page:
SQLite supports FOREIGN KEY syntax when emitting CREATE statements for tables, however by default these constraints have no effect on the operation of the table.
Constraint checking on SQLite has three prerequisites:
- At least version 3.6.19 of SQLite must be in use
- The SQLite libary must be compiled without the SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER symbols enabled.
- The PRAGMA foreign_keys = ON statement must be emitted on all connections before use.
SQLAlchemy allows for the PRAGMA statement to be emitted automatically for new connections through the usage of events:
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
add a comment |
From the SQLite dialect page:
SQLite supports FOREIGN KEY syntax when emitting CREATE statements for tables, however by default these constraints have no effect on the operation of the table.
Constraint checking on SQLite has three prerequisites:
- At least version 3.6.19 of SQLite must be in use
- The SQLite libary must be compiled without the SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER symbols enabled.
- The PRAGMA foreign_keys = ON statement must be emitted on all connections before use.
SQLAlchemy allows for the PRAGMA statement to be emitted automatically for new connections through the usage of events:
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
From the SQLite dialect page:
SQLite supports FOREIGN KEY syntax when emitting CREATE statements for tables, however by default these constraints have no effect on the operation of the table.
Constraint checking on SQLite has three prerequisites:
- At least version 3.6.19 of SQLite must be in use
- The SQLite libary must be compiled without the SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER symbols enabled.
- The PRAGMA foreign_keys = ON statement must be emitted on all connections before use.
SQLAlchemy allows for the PRAGMA statement to be emitted automatically for new connections through the usage of events:
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
answered Oct 7 '12 at 15:56
shadowmattershadowmatter
92411429
92411429
add a comment |
add a comment |
As a simpler approach if your session creation is centralised behind a Python helper function (rather than exposing the SQLA engine directly), you can just issue "session.execute('pragma foreign_keys=on')" before returning the freshly created session.
You only need the pool listener approach if arbitrary parts of your application may create SQLA sessions against the database.
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
add a comment |
As a simpler approach if your session creation is centralised behind a Python helper function (rather than exposing the SQLA engine directly), you can just issue "session.execute('pragma foreign_keys=on')" before returning the freshly created session.
You only need the pool listener approach if arbitrary parts of your application may create SQLA sessions against the database.
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
add a comment |
As a simpler approach if your session creation is centralised behind a Python helper function (rather than exposing the SQLA engine directly), you can just issue "session.execute('pragma foreign_keys=on')" before returning the freshly created session.
You only need the pool listener approach if arbitrary parts of your application may create SQLA sessions against the database.
As a simpler approach if your session creation is centralised behind a Python helper function (rather than exposing the SQLA engine directly), you can just issue "session.execute('pragma foreign_keys=on')" before returning the freshly created session.
You only need the pool listener approach if arbitrary parts of your application may create SQLA sessions against the database.
answered Feb 29 '12 at 4:40
ncoghlanncoghlan
26.8k85567
26.8k85567
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
add a comment |
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
Simpler and good answer! This work great for me
– Marco Herrarte
Apr 10 '14 at 20:54
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
This is a good and easy solution when controlling your session with a @contextmanager.
– Steven
Mar 17 '18 at 21:21
add a comment |
I had the same problem before (scripts with foreign keys constraints were going through but actuall constraints were not enforced by the sqlite engine); got it solved by:
downloading, building and installing the latest version of sqlite from here: sqlite-sqlite-amalgamation; before this I had sqlite 3.6.16 on my ubuntu machine; which didn't support foreign keys yet; it should be 3.6.19 or higher to have them working.
installing the latest version of pysqlite from here: pysqlite-2.6.0
after that I started getting exceptions whenever foreign key constraint failed
hope this helps, regards
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
add a comment |
I had the same problem before (scripts with foreign keys constraints were going through but actuall constraints were not enforced by the sqlite engine); got it solved by:
downloading, building and installing the latest version of sqlite from here: sqlite-sqlite-amalgamation; before this I had sqlite 3.6.16 on my ubuntu machine; which didn't support foreign keys yet; it should be 3.6.19 or higher to have them working.
installing the latest version of pysqlite from here: pysqlite-2.6.0
after that I started getting exceptions whenever foreign key constraint failed
hope this helps, regards
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
add a comment |
I had the same problem before (scripts with foreign keys constraints were going through but actuall constraints were not enforced by the sqlite engine); got it solved by:
downloading, building and installing the latest version of sqlite from here: sqlite-sqlite-amalgamation; before this I had sqlite 3.6.16 on my ubuntu machine; which didn't support foreign keys yet; it should be 3.6.19 or higher to have them working.
installing the latest version of pysqlite from here: pysqlite-2.6.0
after that I started getting exceptions whenever foreign key constraint failed
hope this helps, regards
I had the same problem before (scripts with foreign keys constraints were going through but actuall constraints were not enforced by the sqlite engine); got it solved by:
downloading, building and installing the latest version of sqlite from here: sqlite-sqlite-amalgamation; before this I had sqlite 3.6.16 on my ubuntu machine; which didn't support foreign keys yet; it should be 3.6.19 or higher to have them working.
installing the latest version of pysqlite from here: pysqlite-2.6.0
after that I started getting exceptions whenever foreign key constraint failed
hope this helps, regards
answered Apr 11 '10 at 23:27
serge_gubenkoserge_gubenko
17.2k24455
17.2k24455
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
add a comment |
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
I already have SQLite 3.6.23 and pysqlite 2.6.0 ( and new SQLAlchemy ) The SQLite doc says that you must explicitly turn on FK enforcement. In your experience, when it did enforce, did you use that PRAGMA thing?
– Nick Perkins
Apr 12 '10 at 23:08
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
yes, I have "PRAGMA foreign_keys = ON;" in my code
– serge_gubenko
Apr 13 '10 at 1:18
add a comment |
If you need to execute something for setup on every connection, use a PoolListener.
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
add a comment |
If you need to execute something for setup on every connection, use a PoolListener.
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
add a comment |
If you need to execute something for setup on every connection, use a PoolListener.
If you need to execute something for setup on every connection, use a PoolListener.
answered Apr 13 '10 at 5:56
Ants AasmaAnts Aasma
40k67484
40k67484
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
add a comment |
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
Thanks -- I tried the PoolListener, and it did allow me to execute the pragma for every database connection! Perfect! ...except that the pragma still does not work! The SQLite engine still does not enforce foreign keys!...I am still missing a piece of the puzzle. Maybe it's because I am on Windows? The SQLite docs say something about the "build options" that it was built with...but I just got the standard install for Windows...not sure if that matters?
– Nick Perkins
Apr 13 '10 at 17:57
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2614984%2fsqlite-sqlalchemy-how-to-enforce-foreign-keys%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown