通过SQLAlchemy使用Postgresql执行多个语句不会保留更改

时间:2017-07-27 10:05:09

标签: python postgresql sqlalchemy

这不起作用 - 更新无效:

command = "select content from blog where slug = 'meow'; update account_balance set balance=200 where id=1; select 1 from blog;"
content = db.engine.scalar(command)

切换语句会执行更新并成功选择:

command = "update account_balance set balance=200 where id=1; select content from blog where slug = 'meow';"
content = db.engine.scalar(command)

为什么第一个不起作用?它适用于Pgadmin。我启用了Flask-Sqlalchemy的自动提交。

我正在做一个关于SQL注入的研讨会,所以请不要重写解决方案!

3 个答案:

答案 0 :(得分:4)

SQLAlchemy的自动提交工作方式是检查已发布的语句,尝试detect whether or not data is modified

  

...,SQLAlchemy实现了自己的“自动提交”功能,该功能在所有后端中完全一致。这是通过检测表示数据更改操作的语句(即INSERT,UPDATE,DELETE)以及数据定义语言(DDL)语句(如CREATE TABLE,ALTER TABLE),然后在没有事务正在进行时自动发出COMMIT来实现的。 。检测基于语句中autocommit=True执行选项的存在。如果该语句是纯文本语句且未设置标志,则使用正则表达式来检测INSERT,UPDATE,DELETE以及特定后端的各种其他命令

自SQLAlchemy级别的multiple result sets are not supported以来,在第一个示例中,检测只是省略了发出COMMIT,因为 first 语句是SELECT,而在第二个示例中它是UPDATE。不会尝试从多个语句中检测数据修改语句。

如果您查看PGExecutionContext.should_autocommit_text(),就会发现regex matchAUTOCOMMIT_REGEXP进行了How to filter a Java String to get only alphabet characters?。换句话说,它仅匹配文本的开头。

答案 1 :(得分:0)

如果要使用SELECT INTO创建表:

如上所述,engine.execute('select * into a from b')不起作用。相反,您可以执行以下操作:

conn = engine.raw_connection()
cursor = conn.cursor()

cursor.execute('select * into a from b')
conn.commit() 

答案 2 :(得分:-1)

如果你想执行所有事情并且只获得第一行,你应该使用db.engine.execute(...).first()