본문 바로가기
배움 로그/backend

sqlite3 에러 해결하기(sqlite3.OperationError, sqlite3.ProgrammingError)

by eple 2023. 1. 25.
728x90
반응형

 

목차

     

    In memory DB로 서버가 아니라
    응용 프로그램에 임베디드 되어 사용하는
    가벼운 데이터베이스 -
    SQLite 

    SQLite는 쓰기 작업 시
    데이터베이스를 잠그므로
    여러 동시 쓰기 작업이 실행되는 앱에서는
    성능 문제가 발생할 수 있어
    업무 자동화를 위한
    혼자만의 작업이라던가... 미니시스템으로
    SQL을 배우거나 할 때 사용해 보기 좋다.

    파이썬(3.11.0)에는 sqlite3라는
    패키지 이름으로 기포함되어 있다. 

    아래는 조금씩 활용하다가
    마주친 에러를 해결방법을 공유! 

     

        Task  -  XML 파일 파싱 후,  정규화(Normalization)하기 

    import xml.etree.ElementTree as ET
    import sqlite3
    
    conn = sqlite3.connect('trackdb.sqlite')
    cur = conn.cursor()
    
    # Make some fresh tables using executescript()
    cur.executescript('''
    DROP TABLE IF EXISTS Artist;
    DROP TABLE IF EXISTS Album;
    DROP TABLE IF EXISTS Track;
    DROP TABLE IF EXISTS Genre;
    
    CREATE TABLE Artist (
        id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
        name    TEXT UNIQUE
    );
    
    CREATE TABLE Genre (
        id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
        name    TEXT UNIQUE
    );
    
    CREATE TABLE Album (
        id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
        artist_id  INTEGER,
        title   TEXT UNIQUE
    );
    
    CREATE TABLE Track (
        id  INTEGER NOT NULL PRIMARY KEY 
            AUTOINCREMENT UNIQUE,
        title TEXT  UNIQUE,
        album_id  INTEGER,
        len INTEGER, rating INTEGER, count INTEGER, genre_id INTEGER 
    );
    ''')
    
    fname = 'Library.xml'
    
    def lookup(d, key):
        found = False
        for child in d:
            if found : return child.text
            if child.tag == 'key' and child.text == key :
                found = True
        return None
    
    stuff = ET.parse(fname)
    all = stuff.findall('dict/dict/dict')
    print('Dict count:', len(all))
    for entry in all:
        if ( lookup(entry, 'Track ID') is None ) : continue
    
        name = lookup(entry, 'Name')
        artist = lookup(entry, 'Artist')
        album = lookup(entry, 'Album')
        count = lookup(entry, 'Play Count')
        rating = lookup(entry, 'Rating')
        length = lookup(entry, 'Total Time')
        genre = lookup(entry, 'Genre')
    
        if name is None or artist is None or album is None : 
            continue
        
        print(name, artist, album, count, rating, length, genre)
    
        cur.execute('''INSERT OR IGNORE INTO Artist (name) 
            VALUES ( ? )''', ( artist, ) )
        cur.execute('SELECT id FROM Artist WHERE name = ? ', (artist, ))
        artist_id = cur.fetchone()[0]
    
        cur.execute('''INSERT OR IGNORE INTO Album (title, artist_id) 
            VALUES ( ?, ? )''', ( album, artist_id ) )
        cur.execute('SELECT id FROM Album WHERE title = ? ', (album, ))
        album_id = cur.fetchone()[0]
    
        cur.execute('''INSERT OR IGNORE INTO Genre (name) 
            VALUES ( ? )''', ( genre, ) )
        cur.execute('SELECT id FROM Genre WHERE name = ? ', (genre, ))
        genre_id = cur.fetchone()[0]
    
        cur.execute('''INSERT OR REPLACE INTO Track
            (title, album_id, len, rating, count, genre_id) 
            VALUES ( ?, ?, ?, ?, ?, ?)''', 
            ( name, album_id, length, rating, count, genre_id) )
    
        conn.commit()
    
    conn.close()

     

        sqlite3.OperationError : database is locked

    • genre 키 값에 따른 데이터를 DB에 저장해오려다 마주친 Error

    sqlite3.OperationError

    conn = sqlite3.connect('trackdb.sqlite')
    cur = conn.cursor()
    
    ....
    
    conn.close()
    • 위와 같이 DB와 Connection을 열었다면 재차 다시 돌리기 위해서는 Connection을 닫아줘야한다. 그럼 해결
    • 그런데도 해결이 안된다면 python에서 물고 있는 Connection을 끊을 수 있도록 Python을 재시작한다. 

     

        sqlite3.ProgrammingError : Cannot operate on a closed database

    • 반대로 conn.close()가 남발되서 생긴 Error다. 
    conn.close()

    sqlite3.ProgrammingError
    sqlite3.ProgrammingError

    • 잘못된 들여쓰기로 DB를 Close 하고 DB에 데이터를 넣으려해서 표시된 에러
    • 항상 Indentation(들여쓰기)를 주의하자 

     

     

    '배움 로그 > backend' 카테고리의 다른 글

    [DB/Oracle] 두 테이블 JOIN하기 - ① JOIN  (0) 2022.05.17

    댓글