2010-04-10 5 views
24

새 버전의 SQLite에는 외래 키 제약 조건을 적용 할 수있는 기능이 있지만 이전 버전과의 호환성을 위해 각 데이터베이스 연결마다 별도로 설정해야합니다.Sqlite/SQLAlchemy : 외래 키를 적용하는 방법?

sqlite> PRAGMA foreign_keys = ON; 

SQLAlchemy를 사용하고 있습니다. 어떻게 항상 켜져 있는지 확인하려면 어떻게해야합니까? 내가 시도 무엇 은 이것이다 :

engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True) 
engine.execute('pragma foreign_keys=on') 

... 그것은하지만 작동하지 않습니다 ... 나는 무엇을 놓치고있다!?

편집 : 내 진짜 문제는 SQLite가 하나 이상 설치되어 있고 파이썬이 최신 버전을 사용하고 있지 않다는 것입니다.

>>> import sqlite3 
>>> print sqlite3.sqlite_version 
3.3.4 

방금 ​​3.6.23을 다운로드하고 프로젝트 디렉토리에 exe 파일을 넣습니다! 어떤 .exe가 사용 중인지 파악하고 변경할 수 있습니까?

최신 SQLite는 다운로드하여 전술 한 바와 같이 pysqlite2 빌드 : 올바른 버전이 파이썬에 의해 실행시에 사용하고 있는지 확인

답변

14

나는 지금이 작업을해야합니다.

import sqlite3 
import pysqlite2 
print sqlite3.sqlite_version # should be 3.6.23.1 
print pysqlite2.__path__  # eg C:\\Python26\\lib\\site-packages\\pysqlite2 

다음은 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()]) 

그런 다음 외래 키가 작동하는지 테스트하는 방법주의 : 여기 약간의 혼동이 있었다. sqlalchemy ORM을 사용하여 add() 작업을 수행 할 때 내 가져 오기 코드가 암시 적으로 관계 연결을 처리하므로 절대로 실패 할 수 없습니다. 일부 ForeignKey() 문에 'nullable = False'를 추가하면 여기에서 도움이되었습니다.

내가 SQLAlchemy의 SQLite는 외래 키 지원을 테스트하는 방법이 사용

이 선언 ORM 클래스에서 수동 삽입을하는 것입니다 :

여기
# 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) 

가 'wall_id'와 'TYPE_ID'의) (모두 외래 키입니다 및 잘못된 fookys를 연결하려고하면 sqlite가 예외를 올바르게 throw합니다. 그래서 그것은 작동합니다! 리스너를 제거하면 sqlalchemy가 기꺼이 잘못된 항목을 추가합니다.

나는 주요 문제가 여러 sqlite3.dll (또는 .so) 주위에있을 수 있습니다 믿습니다.

+0

PRAGMA 문을 사용한 것과 같은 방법을 사용 했습니까? –

+0

고마워, 나는 너무 일하고있어. 사실, 문제는 내 컴퓨터에서 SQLite를 여러 개 복사하는 것이 었습니다.이를 수정하고 PoolListener를 사용하면 완벽하게 작동했습니다! –

+0

그것은 작동합니다! 그러나 그것과 함께 작동하도록 만드는 방법 ... – 42n4

3

외래 키 제약 조건을 가진 스크립트가 통과했지만 actuall 제약 조건은 sqlite 엔진에 의해 강제 적용되지 않았습니다. 그것은 해결되었다 :

  1. 다운로드, 건물과 여기에서 SQLite는의 최신 버전을 설치 : sqlite-sqlite-amalgamation; 이 전에는 우분투 컴퓨터에서 sqlite 3.6.16을 사용했습니다. 아직 외래 키를 지원하지 않았다. 작동하도록하려면 3.6.19 이상이어야합니다.

  2. 여기에서 pysqlite의 최신 버전을 설치 : 그 후 pysqlite-2.6.0

내가 외래 키 제약 조건이

희망이 도움이 실패 할 때마다 예외를 받기 시작, 당신이 필요한 경우

+0

나는 이미 SQLite 3.6.23과 pysqlite 2.6.0 (그리고 새로운 SQLAlchemy)을 가지고있다. SQLite doc은 명시 적으로 FK 적용을 켜야한다고 말한다. 귀하의 경험에 따르면, 그것이 시행되었을 때, 그 PRAGMA 것을 사용 했습니까? –

+0

예, "PRAGMA foreign_keys = ON;" 내 코드 –

2

에 관하여 모든 연결에서 설정을 위해 무언가를 실행하려면 PoolListener을 사용하십시오. 최신 버전 (SQLAlchemy의 ~ 0.7)을 SQLAlchemy homepage를 들어

+0

감사합니다 - PoolListener 시도하고 각 데이터베이스 연결에 대한 pragma 실행할 수있게했다! 완전한! ... 그 pragma가 여전히 작동하지 않는다는 것 말고는! SQLite 엔진은 여전히 ​​외래 키를 시행하지 않습니다! ... 아직 퍼즐 조각이 누락되었습니다. 아마 내가 윈도우에 있기 때문 일까? SQLite 워드 프로세서는 빌드 된 "빌드 옵션"에 대해 다음과 같이 말합니다. 그러나 Windows 용 표준 설치가 있습니다 ... 중요한지 확실하지 않습니까? –

37

는 말한다 :

PoolListener가되지 않습니다. PoolEvents을 참조하십시오.

그런 다음 CarlS에 의해 예된다 : 간단한 방법으로

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) 
+0

conny의 대답은 최신 버전의 sqlalchemy에 적합합니다. 그걸 써! 중재자는이 사실을 올바른 것으로 선택해야합니다. –

3

세션 생성이 (오히려 직접 SQLA 엔진을 노출보다) 파이썬 도우미 함수 뒤에 집중되어있는 경우, 당신은 "단지 문제 수 새롭게 생성 된 세션을 반환하기 전에 session.execute ('pragma foreign_keys = on')를 호출하십시오.

응용 프로그램의 임의의 부분에서 데이터베이스에 대해 SQLA 세션을 만들 수있는 경우에만 풀 수신기 방법이 필요합니다. SQLite dialect page에서

+0

간단하고 좋은 답변입니다! 이 작품은 나를 위해 위대한 –

6

: 테이블에 대한 CREATE 문을 방출 할 때

SQLite는하지만 기본적으로 이러한 제약은 테이블의 작동에 영향을주지 않습니다, FOREIGN KEY 구문을 지원합니다. SQLite는의 3.6.19 사용

  • SQLite는 libary에 있어야합니다

    • 적어도 버전 활성화 SQLITE_OMIT_FOREIGN_KEY 또는 SQLITE_OMIT_TRIGGER 문자없이 컴파일해야합니다 SQLite는에 확인

      제약은 세 가지 전제 조건이있다.

    • PRAGMA foreign_keys = ON 문은 사용하기 전에 모든 연결에서 방출되어야합니다. 프라 그마 문이 이벤트의 사용을 통해 새로운 연결을 자동으로 배출 될 수 있도록

    SQLAlchemy의 허용 :

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

    건물 코니와 shadowmatter의 대답에, 여기에 있는지 확인합니다 코드는 PRAGMA 문을 방출하기 전에 SQLite3을 사용하고 있습니다.

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

    고마워. 이는'db = SQLAlchemy (app) '접근 방식을 선호하는 사람들에게도 효과적입니다. –

    관련 문제