我有一个 Flask 应用程序,其数据库后端是 MS SQL Server。我正在尝试编写一个查询。
active_with_schools = db.query(
Registration.id,
Registration.uuid,
Registration.last_name,
Registration.first_name,
Registration.email,
Registration.phone,
Registration.date_added,
Registration.other_heard_from,
Registration.other_feedback,
func.coalesce(
Registration.date_expired,
datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S')
),
func.coalesce(
Registration.expired_by, ''
),
func.count(School.registration_id)
).join(
User,
User.email == Registration.email
).join(
School,
School.registration_id == Registration.id,
isouter=True
).filter(
func.coalesce(
Registration.date_expired,
datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S')
) < datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S')
).group_by(
Registration.id,
Registration.uuid,
Registration.last_name,
Registration.first_name,
Registration.email,
Registration.phone,
Registration.date_added,
Registration.other_heard_from,
Registration.other_feedback,
func.coalesce(
Registration.date_expired,
datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S')
),
func.coalesce(
Registration.expired_by, ''
)
).having(
func.count(
func.coalesce(
School.registration_id, -1
)
) > 0
).order_by(
Registration.date_added.desc()
).all()
这会引发“ProgrammingError”异常(稍作编辑):
(pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC Driver
18 for SQL Server][SQL Server]Column 'MySchema.registration.date_expired'
is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause. (8120) (SQLExecDirectW);
[42000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Column
'MySchema.registration.date_expired' is invalid in the select list because
it is not contained in either an aggregate function or the GROUP BY clause.
(8120); [42000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]
Statement(s) could not be prepared. (8180)")
[SQL: SELECT [MySchema].registration.id AS [MySchema_registration_id],
[MySchema].registration.uuid AS [MySchema_registration_uuid],
[MySchema].registration.last_name AS [MySchema_registration_last_name],
[MySchema].registration.first_name AS [MySchema_registration_first_name],
[MySchema].registration.email AS [MySchema_registration_email],
[MySchema].registration.phone AS [MySchema_registration_phone],
[MySchema].registration.date_added AS [MySchema_registration_date_added],
[MySchema].registration.other_heard_from AS [MySchema_registration_other_heard_from],
[MySchema].registration.other_feedback AS [MySchema_registration_other_feedback],
coalesce([MySchema].registration.date_expired, ?) AS coalesce_1,
coalesce([MySchema].registration.expired_by, ?) AS coalesce_3,
count([MySchema].school.registration_id) AS count_1
FROM [MySchema].registration
JOIN [MySchema].[user]
ON [MySchema].[user].email = [MySchema].registration.email
LEFT OUTER JOIN [MySchema].school
ON [MySchema].school.registration_id = [MySchema].registration.id
WHERE coalesce([MySchema].registration.date_expired, ?) < ?
GROUP BY [MySchema].registration.id,
[MySchema].registration.uuid,
[MySchema].registration.last_name,
[MySchema].registration.first_name,
[MySchema].registration.email,
[MySchema].registration.phone,
[MySchema].registration.date_added,
[MySchema].registration.other_heard_from,
[MySchema].registration.other_feedback,
coalesce([MySchema].registration.date_expired, ?),
coalesce([MySchema].registration.expired_by, ?)
HAVING count(coalesce([MySchema].school.registration_id, ?)) > ?
ORDER BY [MySchema].registration.date_added DESC]
[parameters: (
'2024-05-16 16:36:39',
'',
'2024-05-16 16:36:39',
'2024-05-16 16:36:39',
'2024-05-16 16:36:39',
'',
-1,
0
)]
(Background on this error at: https://sqlalche.me/e/20/f405)
但是,如果我在 PyCharm 中打开数据库控制台窗口;将SQL粘贴到异常中;并添加有效的参数值:
SELECT [MySchema].registration.id AS [MySchema_registration_id],
[MySchema].registration.uuid AS [MySchema_registration_uuid],
[MySchema].registration.last_name AS [MySchema_registration_last_name],
[MySchema].registration.first_name AS [MySchema_registration_first_name],
[MySchema].registration.email AS [MySchema_registration_email],
[MySchema].registration.phone AS [MySchema_registration_phone],
[MySchema].registration.date_added AS [MySchema_registration_date_added],
[MySchema].registration.other_heard_from AS [MySchema_registration_other_heard_from],
[MySchema].registration.other_feedback AS [MySchema_registration_other_feedback],
COALESCE([MySchema].registration.date_expired, '2024-05-16 16:36:39') AS coalesce_1,
COALESCE([MySchema].registration.expired_by, '') AS coalesce_3,
COUNT([MySchema].school.registration_id) AS count_1
FROM [MySchema].registration
JOIN [MySchema].[user]
ON [MySchema].[user].email = [MySchema].registration.email
LEFT OUTER JOIN [MySchema].school
ON [MySchema].school.registration_id = [MySchema].registration.id
WHERE COALESCE([MySchema].registration.date_expired, '2024-05-16 16:36:39') < '2024-05-16 16:36:39'
GROUP BY [MySchema].registration.id,
[MySchema].registration.uuid,
[MySchema].registration.last_name,
[MySchema].registration.first_name,
[MySchema].registration.email,
[MySchema].registration.phone,
[MySchema].registration.date_added,
[MySchema].registration.other_heard_from,
[MySchema].registration.other_feedback,
COALESCE([MySchema].registration.date_expired, '2024-05-16 16:36:39'),
COALESCE([MySchema].registration.expired_by, '')
HAVING COUNT(COALESCE([MySchema].school.registration_id, -1)) > 0
ORDER BY [MySchema].registration.date_added DESC
我把 SqlAlchemy 弄乱了什么?
我把 SqlAlchemy 弄乱了什么?
什么也没有。您遇到了 SQL Server ODBC 中参数化查询的限制。它已在 GitHub here 上进行了讨论。
为了证明这不是 SQLAlchemy 或 pyodbc 的错误,这里是 VBA 中的重现代码。
Const default_expiry = "2024-05-16 16:36:39"
cmd.CommandText = _
"SELECT id, COALESCE(registration.date_expired, ?) AS coalesce_1 " & _
"FROM registration " & _
"GROUP BY id, COALESCE(registration.date_expired, ?)"
cmd.Parameters.Append cmd.CreateParameter("", adVarChar, adParamInput, 30, default_expiry)
cmd.Parameters.Append cmd.CreateParameter("", adVarChar, adParamInput, 30, default_expiry)
Dim rst As ADODB.Recordset
Set rst = cmd.Execute
失败
列“registration.date_expired”在选择列表中无效,因为它未包含在聚合函数或 GROUP BY 子句中。
但是,这段代码运行时没有错误:
cmd.CommandText = _
"SELECT id, COALESCE(registration.date_expired, '2024-05-16 16:36:39') AS coalesce_1 " & _
"FROM registration " & _
"GROUP BY id, COALESCE(registration.date_expired, '2024-05-16 16:36:39')"
Dim rst As ADODB.Recordset
Set rst = cmd.Execute
将第一个查询转换为 SqlAlchemy
default_expiry = "2024-05-16 16:36:39"
qry = select(
Registration.id,
func.coalesce(Registration.date_expired, default_expiry).label(
"coalesce_1"
),
).group_by(
Registration.id, func.coalesce(Registration.date_expired, default_expiry)
)
产生错误,但使用子查询可以正常工作
default_expiry = "2024-05-16 16:36:39"
subq = select(
Registration.id,
func.coalesce(Registration.date_expired, default_expiry).label(
"coalesce_1"
),
).subquery()
qry = select(subq.c.id, subq.c.coalesce_1).group_by(
subq.c.id, subq.c.coalesce_1
)