这不起作用 - 更新无效:
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注入的研讨会,所以请不要重写解决方案!
答案 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 match对AUTOCOMMIT_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()
。