如何像SQLite一样捕获create.sql中的所有错误?

tktrz96b  于 2022-12-04  发布在  SQLite
关注(0)|答案(1)|浏览(162)

我有一个create.sql(和一个populate.sql),它创建了一个SQLite3数据库(并用一些虚拟数据填充它)。然后,我保存生成的数据库并做进一步的分析。我使用Python为几对sql文件自动化这个过程。

db_mem = sqlite3.connect(":memory:")
cur = db_mem.cursor()
try:
    with open(row['path']+'/' + 'create.sql') as fp:
        cur.executescript(fp.read())  
except:
    creates.append('C-error')
    continue
else:
    creates.append('Ok')
    try:
        with open(row['path']+'/' + 'populate.sql') as fp:
            cur.executescript(fp.read())  
    except sqlite3.Error as x:
        populates.append('P-error')
    else:
        populates.append('Ok')
        db_disk = sqlite3.connect(f'./SQL_Final/{index}_out.db')
        db_mem.backup(db_disk)

然而,我只能在创建时捕获1个错误,而不是从sqlite执行.read create.sql时输出的几个错误。我的问题是如何捕获所有错误?
对于再现性问题,这里有一个虚拟create.sql(生成错误):

DROP TABLE IF EXISTS Comp;
CREATE TABLE Comp (
    idComp INTEGER PRIMARY KEY,
    nomeComp TEXT,
    dataInicio TEXT,
    dataFim TEXT
);
DROP TABLE IF EXISTS Game;
DROP TABLE IF EXISTS Stade;
DROP TABLE IF EXISTS Club;
DROP TABLE IF EXISTS Squad;
CREATE TABLE Game (
    idGame INTEGER PRIMARY KEY,
    golosFora INTEGER,
    golosCasa INTEGER,
    data DATE,
    jornada INTEGER,
    duração TIME,
    nomeComp TEXT REFERENCES Comp,
    nomeStade TEXT REFERENCES Stade,
    nomeSquadFora TEXT REFERENCES Squad,
    nomeSquadCasa TEXT REFERENCES Squad,
    CONSTRAINT CHECK_Game_golosFora CHECK (Game_golosFora >= 0),
    CONSTRAINT CHECK_Game_golosCasa CHECK (Game_golosCasa >= 0),
    CONSTRAINT CHECK_Game_jornada CHECK (jornada > 0)
);
CREATE TABLE Stade (
    nomeStade TEXT PRIMARY KEY,
    local TEXT NOT NULL,
    idGame INTEGER REFERENCES Game
);
CREATE TABLE Club (
    nomeClub TEXT PRIMARY KEY,
    país TEXT NOT NULL
);
CREATE TABLE Squad (
    nomeSquad TEXT PRIMARY Key,
    nomeClub TEXT REFERENCES Club
);

如果我从SQLIte读取此文件(使用.read create.sql),则会出现以下错误:

Error: near line 2: in prepare, table "Comp" has more than one primary key (1)
Error: near line 13: in prepare, no such column: Game_golosFora (1)

然而,如果我从Python自动化,我只得到一个错误:

Error: table "Comp" has more than one primary key

有什么办法可以弥补吗?

des4xlb0

des4xlb01#

executescript()将运行整个sql文件,但在发生错误时将引发异常。
由于您希望不管错误如何都继续创建DB模式,因此可以通过对每个sql语句调用execute(),从使用executescript()切换到循环sql语句列表。
这个例子将演示当错误发生时处理继续进行。我们将尝试创建一个已经存在的表来模拟sqlite错误。

创建.sql

CREATE TABLE Stade (
    nomeStade TEXT PRIMARY KEY,
    local TEXT NOT NULL,
    idGame INTEGER REFERENCES Game
);

CREATE TABLE Stade (
    nomeStade TEXT PRIMARY KEY,
    local TEXT NOT NULL,
    idGame INTEGER REFERENCES Game
);

CREATE TABLE Stade2 (
    nomeStade TEXT PRIMARY KEY,
    local TEXT NOT NULL,
    idGame INTEGER REFERENCES Game
);

CREATE TABLE Stade2 (
    nomeStade TEXT PRIMARY KEY,
    local TEXT NOT NULL,
    idGame INTEGER REFERENCES Game
);

CREATE TABLE Stade3 (
    nomeStade TEXT PRIMARY KEY,
    local TEXT NOT NULL,
    idGame INTEGER REFERENCES Game
);

巨蟒

import traceback
import sqlite3
db_mem = sqlite3.connect(":memory:")
cur = db_mem.cursor()
try:
    with open('create.sql', 'r') as fp:
        text = fp.read().split(';')
        for sql in text:
            try:
                cur.execute(sql)
            except:
                print("exception at sql: {}, details: {}".format(sql, traceback.format_exc()))
                pass
except:
    print("exception, details: {}".format(traceback.format_exc()))
    pass
else:
    db_disk = sqlite3.connect('db.sqlite')
    db_mem.backup(db_disk)

运行它,我们可以看到2个错误消息,检查db.sqlite,我们也可以看到第3个表,即处理到达了最后一个sql。

相关问题