传递基于“SELECT”的 SQL 查询是有效的。但是传递基于“DELETE”或“GRANT”的 SQL 在 python 中执行没有错误,但不会更改我的数据库(python 3.8,sqlalchemy 2.0.10)。这些“DELETE”和“GRANT”查询适用于 Python 3.6、sqlalchemy 1.3.23。我可能会遗漏一些东西,但我在 sqlalchemy 文档/更改注释中没有看到任何内容表明应该丢失此“删除”或“授予”功能。
这里有一个例子,可能会说明我哪里出错了。初始化引擎后(我使用 '' 表示任意输入):
from sqlalchemy import create_engine
from sqlalchemy import text
db_name = '<insert_db_name>'
port = ':<insert_port>/'
host = '<insert_host_endpoint>'
username = '<insert_username>'
password = '<insert_password>'
engine = create_engine('postgresql_psycopg2://'+username+':'+
password+'@'+host+port+db_name)
我可以通过connection.execute甚至pandas进行读写。像下面这样的东西就可以了(用 pandas 读取,用 pandas 写入,用 .execute 读取):
import pandas as pd
query_1 = "SELECT * from '<schema>'.'<table_name>'"
df = pd.read_sql(sql_query, engine)
df.to_sql(name = '<new_table_name>', con = engine, schema = <'schema'>)
with engine.connect() as con:
con.execute(text("SELECT * from schema.'<new_table_name>'))
通过 .execute 传递基于 GRANT 或 DELETE 的 SQL 在 Python 中运行不会出现错误,但数据库不会发生任何更改 - 就好像 Python 脚本从未运行过一样。以下示例在 Python 中运行没有错误,但在数据库中没有任何效果:
query_2 = "GRANT SELECT ON TABLE '<schema>'.'<table_name>' TO <'some_user'>"
query_3 = "DELETE FROM '<schema>'.'<table_name>' WHERE <some condition>"
with engine.connect() as con:
con.execute(text(query_2))
con.execute(text(query_3))
同样的代码可以在 Python 3.6/sqlalchemy 1.3.23 中运行(删除 sqlalchemy“text()”,因为在旧版本中不需要它,如 sqlalchemy 更改注释中所述)。
该问题与“SELECT”、“DELETE”或“GRANT”SQL 调用无关,而是(如评论中发布的)这是自动提交失败(事实证明它与 stackoverflow 有关) .com/a/76947751/2144390)。解决此问题的一种方法是在启动引擎时添加参数isolation_level = 'AUTOCOMMIT'。
继续上面的例子,这将是:
engine = create_engine('postgresql_psycopg2://'+username+':'+
password+'@'+host+port+db_name, isolation_level = 'AUTOCOMMIT')
参见 https://docs.sqlalchemy.org/en/20/core/connections.html#dbapi-autocommit