我有一个在 SQL 编辑器中运行良好的查询:
UPDATE users mu
JOIN (SELECT
min.user_id as user_id,
(max.total_followers - min.total_followers) as progression
FROM(select user_id, measurement_date, total_followers
from followers_totals ft
where measurement_date = (select max(measurement_date) from followers_totals as f where f.user_id = ft.user_id
and date_format(ft.measurement_date, '%%Y-%%m-%%d') >= date_format(date_sub(CURDATE(), interval 7 day), '%%Y-%%m-%%d'))) max
JOIN (select user_id, measurement_date, total_followers
from followers_totals ft
where measurement_date = (select min(measurement_date) from followers_totals as f where f.user_id = ft.user_id
and date_format(ft.measurement_date, '%%Y-%%m-%%d') >= date_format(date_sub(CURDATE(), interval 7 day), '%%Y-%%m-%%d'))) min
ON max.user_id = min.user_id
WHERE min.user_id = '123456' and max.user_id = '123456') progression
ON progression.user_id = mu.user_id
SET mu.followers_count_progress_7D = progression.progression
WHERE progression.user_id is not null;
Run Code Online (Sandbox Code Playgroud)
我尝试使用执行函数从 SQLAlchemy 执行相同的查询:
import sqlalchemy
from sqlalchemy import create_engine, Table, MetaData, exc
eng = create_engine('mysql://xxxxxxxxxxxxxxxxxxxxxxxxxxxx')
con = eng.connect()
try:
query = """UPDATE users mu
JOIN (SELECT
min.user_id as user_id,
(max.total_followers - min.total_followers) as progression
FROM(select user_id, measurement_date, total_followers
from followers_totals ft
where measurement_date = (select max(measurement_date) from followers_totals as f where f.user_id = ft.user_id
and date_format(ft.measurement_date, '%%Y-%%m-%%d') >= date_format(date_sub(CURDATE(), interval 7 day), '%%Y-%%m-%%d'))) max
JOIN (select user_id, measurement_date, total_followers
from followers_totals ft
where measurement_date = (select min(measurement_date) from followers_totals as f where f.user_id = ft.user_id
and date_format(ft.measurement_date, '%%Y-%%m-%%d') >= date_format(date_sub(CURDATE(), interval 7 day), '%%Y-%%m-%%d'))) min
ON max.user_id = min.user_id
WHERE min.user_id = '123456' and max.user_id = '123456') progression
ON progression.user_id = mu.user_id
SET mu.followers_count_progress_7D = progression.progression
WHERE progression.user_id is not null;"""
rs = con.execute(query)
print(rs)
except exc.SQLAlchemyError as e:
print (e)
Run Code Online (Sandbox Code Playgroud)
没有返回异常,并且 print(rs) 会按预期返回代理。但是,使用 SQL 编辑器更新数据库时,不会使用 SQLAlchemy 更新数据库。SQL Alchemy 是否不支持我的查询的某些部分?
我最初认为这将是日期格式中 % 的转义,但不同的测试表明,使用这种转义写入可以按预期运行更简单的查询。
编辑:按照上面的建议在引擎创建中使用 echo=True 后,我可以看到查询格式已保留,提交已完成。我将 echo 的输出复制粘贴到 sql 编辑器中,查询运行良好,但使用 sqlalchemy 时它根本不更新。
EDIT2:尝试添加 autocommit=True ,结果相同......日志显示:
2021-02-14 11:21:21,387 INFO sqlalchemy.engine.base.Engine ()
2021-02-14 11:21:21,389 INFO sqlalchemy.engine.base.Engine UPDATE users mu
JOIN (
SELECT min.user_id as user_id,
(max.total_followers - min.total_followers) as progression
FROM(
select user_id, measurement_date, total_followers
....
ON progression.user_id = mu.user_id
SET mu.followers_count_progress_7D = progression.progression
WHERE progression.user_id is not null;
2021-02-14 11:21:21,389 INFO sqlalchemy.engine.base.Engine ()
2021-02-14 11:21:21,393 INFO sqlalchemy.engine.base.Engine COMMIT
0
Run Code Online (Sandbox Code Playgroud)
用于连接的用户拥有所有权限:
GRANT ALL ON *.* TO 'user1'@'%';
Run Code Online (Sandbox Code Playgroud)
在 SQLAlchemy 上运行的更简单的更新查询实际上正在工作。
编辑3:有趣的是,这似乎只发生在某些ID上,但不是全部。依赖ID的东西怎么能远程工作而不是本地工作......?
由于调试打印似乎没有提供足够的信息来解决问题,我将假设这确实是实际向数据库提交更改的问题,所以,就像其他人在各种其他问题中提到的那样(例如如:在 mysql 中将 autocommit 设置为 1),您应该尝试显式使用autocommit=True.
您可以使用with以下语句对此进行测试:
with engine.connect().execution_options(autocommit=True) as conn:
conn.execute(query)
Run Code Online (Sandbox Code Playgroud)
或者只是附加.execution_options(autocommit=True)到您现有的代码:
conn.execute(query).execution_options(autocommit=True)
Run Code Online (Sandbox Code Playgroud)
请注意,虽然该execution_option参数autocommit在 SQLAlchemy 1.4 中将被弃用,并且替换将是设置事务隔离级别,如此处所示。
重申一下,MySQL 似乎在内部将自动提交值设置为 0,这意味着它使用需要进行编辑才能.commit()将其传播到数据库的事务。希望这能真正解决问题,因为我目前还没有准备在我的机器上测试这个问题。