Python连接MS SQL 2012编写SQL语句时如何动态使用当前日期
解决方案
完全可以实现SQL语句中当前日期的动态调用,你之前的注释写法无法运行,核心原因有两点:
- f-string中调用日期方法前没有提前导入
datetime模块,也没有定义对应的now变量,格式化时找不到对应值直接报错 - 直接把动态值拼接到SQL字符串的写法,容易触发日期格式不兼容问题,还存在SQL注入风险,不推荐使用
下面提供两种可直接落地的实现方式,按需选择即可:
方案1:使用SQL Server内置日期函数(写法最简单)
MS SQL 2012自带获取当前时间的内置函数,不需要在Python端做任何日期计算,直接写在查询条件中即可。该方法取的是数据库服务器所在系统的当前时间,如果数据库和脚本运行机器时区不一致,时间会存在偏差。
- 仅判断日期(精确到天,和你之前硬编码
'2022-06-14'的逻辑完全一致):用CAST(GETDATE() AS DATE) - 判断精确到时分秒的时间:直接用
GETDATE()
只需要替换原有conditions变量即可,不需要修改其他SQL拼接逻辑:
# 精确到天的条件 conditions = "app.Received > CAST(GETDATE() AS DATE) AND app.ClientID = 117" # 精确到时分秒的条件 # conditions = "app.Received > GETDATE() AND app.ClientID = 117"
方案2:参数化传入Python端获取的当前日期(生产环境推荐)
如果你需要取运行Python脚本的机器的当前时间,使用数据库驱动的参数化查询能力传值,既不会出现日期格式匹配错误,也能彻底避免SQL注入风险,是标准的安全写法。
完整修改后的可运行代码如下:
from datetime import datetime import pandas as pd #Pull data from exat SQL Server into dataframe with sscon.exat_connection() as conn: fields = "app.RecordID, app.IproAppealID, app.Received, app.CaseDue, pla.CompanyName, appi.AppealerAddress1,app.EnteredBy" table = "dbo.tblAppealInformation app LEFT OUTER JOIN dbo.tblPlanInformation pla ON (app.PlanID = pla.PlanID) LEFT OUTER JOIN dbo.tblAppealerInformation appi ON (app.AppealerID = appi.AppealerID)" # 动态值用?作为MSSQL驱动的参数占位符 conditions = "app.Received > ? AND app.ClientID = 117" order = "3" sql = (f"SELECT {fields} " f"FROM {table} " f"WHERE {conditions} " f"ORDER BY {order}") # 构造要传入的日期参数,精确到天 params = [datetime.now().date()] # 如果需要精确到时分秒,替换为 params = [datetime.now()] # 传入参数执行查询,直接返回DataFrame df = pd.read_sql(sql, conn, params=params)
注意:
fields、table、order属于固定SQL结构部分,用f-string拼接没有问题,但所有动态变化的过滤值,都必须通过params参数传入,禁止直接拼接到SQL字符串中。
你原有f-string写法的修正版(仅做原理说明,不推荐生产使用)
如果一定要用f-string直接拼接日期值,需要提前导入datetime模块,同时给日期值补上SQL语法要求的单引号:
from datetime import datetime conditions = f"app.Received > '{datetime.now():%Y-%m-%d}' AND app.ClientID = 117"
这种写法在数据库默认日期格式和拼接格式不匹配时,会触发隐式转换报错,仅适合本地临时调试使用。
内容的提问来源于stack exchange,提问作者mekcox
相关产品推荐
相关产品推荐

