Sqlite / SQLAlchemy: how to enforce Foreign Keys?












30















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?










share|improve this question





























    30















    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?










    share|improve this question



























      30












      30








      30


      17






      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?










      share|improve this question
















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 13 '10 at 22:48







      Nick Perkins

















      asked Apr 10 '10 at 21:07









      Nick PerkinsNick Perkins

      4,34153238




      4,34153238
























          7 Answers
          7






          active

          oldest

          votes


















          15














          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.






          share|improve this answer


























          • 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



















          40














          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)





          share|improve this answer





















          • 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



















          27














          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()





          share|improve this answer
























          • 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











          • 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



















          9














          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()





          share|improve this answer































            5














            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.






            share|improve this answer
























            • 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



















            3














            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:




            1. 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.


            2. 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






            share|improve this answer
























            • 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



















            2














            If you need to execute something for setup on every connection, use a PoolListener.






            share|improve this answer
























            • 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












            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            15














            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.






            share|improve this answer


























            • 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
















            15














            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.






            share|improve this answer


























            • 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














            15












            15








            15







            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.






            share|improve this answer















            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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



















            • 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













            40














            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)





            share|improve this answer





















            • 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
















            40














            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)





            share|improve this answer





















            • 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














            40












            40








            40







            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)





            share|improve this answer















            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)






            share|improve this answer














            share|improve this answer



            share|improve this answer








            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














            • 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











            27














            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()





            share|improve this answer
























            • 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











            • 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
















            27














            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()





            share|improve this answer
























            • 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











            • 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














            27












            27








            27







            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()





            share|improve this answer













            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()






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Mar 21 '13 at 7:51









            Kiran JonnalagaddaKiran Jonnalagadda

            1,25811723




            1,25811723













            • 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











            • 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











            • 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

















            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











            9














            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()





            share|improve this answer




























              9














              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()





              share|improve this answer


























                9












                9








                9







                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()





                share|improve this answer













                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()






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Oct 7 '12 at 15:56









                shadowmattershadowmatter

                92411429




                92411429























                    5














                    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.






                    share|improve this answer
























                    • 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
















                    5














                    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.






                    share|improve this answer
























                    • 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














                    5












                    5








                    5







                    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.






                    share|improve this answer













                    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.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    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



















                    • 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











                    3














                    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:




                    1. 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.


                    2. 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






                    share|improve this answer
























                    • 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
















                    3














                    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:




                    1. 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.


                    2. 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






                    share|improve this answer
























                    • 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














                    3












                    3








                    3







                    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:




                    1. 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.


                    2. 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






                    share|improve this answer













                    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:




                    1. 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.


                    2. 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







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    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



















                    • 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











                    2














                    If you need to execute something for setup on every connection, use a PoolListener.






                    share|improve this answer
























                    • 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
















                    2














                    If you need to execute something for setup on every connection, use a PoolListener.






                    share|improve this answer
























                    • 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














                    2












                    2








                    2







                    If you need to execute something for setup on every connection, use a PoolListener.






                    share|improve this answer













                    If you need to execute something for setup on every connection, use a PoolListener.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    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



















                    • 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


















                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    List item for chat from Array inside array React Native

                    Thiostrepton

                    Caerphilly