PyQt, SQLAlchemy, SQLite - странный сбой при вставке - PullRequest
0 голосов
/ 09 марта 2012

Я пытаюсь преобразовать xml в sqlite и получаю странную ошибку:

Traceback (most recent call last):
File "C:\Temp\xxx\scripts\xml_to_db.py", line 212, in <module> 
win = Test(a)
File "C:\Temp\xxx\scripts\xml_to_db.py", line 20, in __init__
self.testdb()
File "C:\Temp\xxx\scripts\xml_to_db.py", line 133, in testdb
row = connection.execute(t_id)
File "C:\Temp\PortablePython\App\lib\site-packages\sqlalchemy\engine\base.py", line 1405, in execute 
params)
File "C:\Temp\PortablePython\App\lib\site-packages\sqlalchemy\engine\base.py", line 1538, in _execute_clause
element
compiled_sql, distilled_params
File "C:\Temp\PortablePython\App\lib\site-packages\sqlalchemy\engine\base.py", line 1646, in _execute_context 
context)
File "C:\Temp\PortablePython\App\lib\site-packages\sqlalchemy\engine\base.py", line 1639, in _execute_context 
context)
File "C:\Temp\PortablePython\App\lib\site-packages\sqlalchemy\engine\default.py", line 330, in do_execute
cursor.execute(statement, parameters)
InterfaceError: (InterfaceError) Error binding parameter 0 - probably unsupported type. u'SELECT temperatures.id \nFROM temperatures \nWHERE temperatures.temperature = ?' ('50',)

, где строка 130 соответствует

t_id = select([tb_temperatures.c.id], tb_temperatures.c.temperature == temp)

Вот весь код

def testdb(self):
    db_file = "C:/Temp/xxx/data/xxx/db.sqlite"

    file=QFile(db_file)
    if file.exists():
        file.remove()

    db = create_engine('sqlite:///' + db_file)
    connection = db.connect()

    metadata = MetaData()

    tb_materials = Table('materials', metadata,
        Column('id', Integer, primary_key=True),
        Column('material', String)
        )

    tb_temperatures = Table('temperatures', metadata,
        Column('id', Integer, primary_key=True),
        Column('temperature', String)
        )

    tb_mat_data = Table('mat_data', metadata,
        Column('id', Integer, primary_key=True),
        Column('mat_id', None, ForeignKey('materials.id', onupdate="CASCADE", ondelete="CASCADE")),
        Column('temp_id', None, ForeignKey('temperatures.id', onupdate="CASCADE", ondelete="CASCADE")),
        Column('density', String),
        Column('elasticity', String),
        Column('stress', String)
        )

    auto_assign(metadata, db)
    metadata.create_all(db)

    for m in ['SS 316']:
        data = tb_materials.insert().values(material = m)
        connection.execute(data)

    for t in ['25', '38', '50', '150']:
        data = tb_temperatures.insert().values(temperature = t)
        connection.execute(data)

    materials = ['SS 316']
    for material in materials:
        m_id = select([tb_materials.c.id], tb_materials.c.material == material)
        row = connection.execute(m_id)
        data = row.fetchone()
        m_id_key = data[0]
        temps = ['25', '38', '50', '150']
        for temp in temps:
            QMessageBox.about(self,"",temp)
            t_id = select([tb_temperatures.c.id], tb_temperatures.c.temperature == temp)
            row = connection.execute(t_id)
            data = row.fetchone()
            t_id_key = data[0]
            z = tb_mat_data.insert().values(mat_id = m_id_key, temp_id = t_id_key)
            connection.execute(z)

    connection.close()
    quit()

, который падает при третьем значении temp = '50'.

Я полностью озадачен и не могу найти, что с ним не так.

1 Ответ

1 голос
/ 09 марта 2012

Я понятия не имею, что именно там происходит, но это определенно связано с Connection.Я предполагаю, что существует ошибка , связанная с тем, что параметры не очищаются должным образом при подготовке оператора перед следующим выполнением.

Например, если вы замените connection.execute(z) на db.execute(z) (выполнение без установления соединения; в основном используется другое соединение), это, вероятно, будет работать очень хорошо, поскольку оператор, выполняемый между ними (row = connection.execute(m_id)), имееттолько 1 параметр.

Кроме того, если вы используете повсеместное выполнение без установления соединения (прямой вызов engine/db.execute(...)), все также работает отлично (поскольку для каждого запроса будет использоваться новое соединение).

SingleОператор SQL: Помимо этой проблемы / ошибки? Вы фактически можете выполнить вставку в mat_data в одном операторе SQL INSERT, используя тип запроса Correlated Update :

QMessageBox.about(self,"",temp)
s = select([tb_temperatures.c.id], tb_temperatures.c.temperature == temp).limit(1)
z = tb_mat_data.insert().values(mat_id = m_id_key, temp_id = s)
connection.execute(z)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...