SQLAlchemy commit sql выполнение после итерации результатов с помощью метода fetchall - PullRequest
1 голос
/ 06 августа 2020

У меня возникают проблемы с чтением результатов, созданных с помощью операторов OUTPUT в SQLAlchemy. Изначально у меня возникла проблема с чтением primaryKey вставленной строки, но я смог заставить его работать, используя следующий код, устанавливающий autocommit на false:

sqlString = """ INSERT INTO workflow.{table}  ({columns})
                OUTPUT Inserted.{primaryKey}
                VALUES ({values})""".format(table=self.table, columns=columns, primaryKey=self.primaryKey, values=values)

    with self.dict_db['engine'].connect().execution_options(autocommit=False) as connection:
      result = connection.execute(sqlString)
      primaryKey = result.fetchone()[0]
      result.cursor.commit()

Теперь я пишу оператор удаления, в котором я хочу сделайте что-нибудь подобное, однако после итерации моих результатов объект курсора установлен на None, поэтому я больше не могу фиксировать. Я пробовал оба, используя для l oop, который повторяет results и results.fetchall(), и в обоих случаях я не могу зафиксировать, потому что курсор равен None. Вот мой код в его нынешнем виде:

    sqlString = """ DELETE FROM workflow.{table} OUTPUT Deleted.{primaryKey} {where} """.format(table=self.table, primaryKey=self.primaryKey, where=whereStatement)

    with self.dict_db['engine'].connect().execution_options(autocommit=False) as connection:
      result = connection.execute(sqlString)
      # cursor exists
      primaryKeyList = [item[0] for item in result.fetchall()]
      # cursor is now None
      result.cursor.commit()

Тот факт, что это не работает, заставляет меня переосмыслить оба выполнения БД. Я делаю здесь что-то совершенно неправильно или мне не хватает небольшого синтаксиса?

Примечание: self.dict_db['engine'] создается с помощью sqlalchemy create_engine

1 Ответ

0 голосов
/ 06 августа 2020

Создайте транзакцию с использованием соединения (используя connection.begin() и зафиксируйте это.

with self.dict_db['engine'].connect().execution_options(autocommit=False) as connection:
  txn = connection.begin()
  result = txn.execute(sqlString)
  # I'm not sure a cursor exists here, the result doesn't need one for fetchall()
  primaryKeyList = [item[0] for item in result.fetchall()]
  txn.commit()

Более того, объект, возвращаемый из connection.begin(), реализует протокол диспетчера контекста, поэтому вы можете использовать эту более простую версию и убедитесь, что транзакция зафиксирована, если нет исключения, или откат, если есть:

with self.dict_db['engine'].connect().begin() as connection: 
  # connection here is really a Transaction, but all the connection methods work the same
  result = connection.execute(sqlString)
  primaryKeyList = [item[0] for item in result.fetchall()]
  # transaction is committed as the with block exits

Подробнее см. Использование транзакций в документации SQLAlchemy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...