Python - 将日期时间参数传递给 SQL 命令
Python - Passing datetime parameters into a SQL Command
我正在尝试在 Python、
中做这样的事情
SQLCommand = ("Delete From %s where [Date] >= %s and [Date] <= %s", (calendar_table_name, required_starting_date, required_ending_date))
cursor.execute(SQLCommand)
calendar_table_name
是一个 string
变量
required_starting_date
是一个 datetime
变量
required_ending_date
是一个 datetime
变量
尝试这个给我一个错误:
The first argument to execute must be a string or unicode query.
试过这个,它给了我同样的错误:
SQLCommand = ("Delete From " + calendar_table_name + " where [Date] >= %s and [Date] <= %s", ( required_starting_date, required_ending_date))
cursor.execute(SQLCommand)
编辑:
type(required_ending_date)
Out[103]: pandas._libs.tslibs.timestamps.Timestamp
type(required_starting_date)
Out[103]: pandas._libs.tslibs.timestamps.Timestamp
这对我来说适用于 SSMS,
delete from [table_test] where [Date] >= '2007-01-01' and [Date] <= '2021-01-01';
更新:-这是我正在尝试使用的代码
Delete_SQLCommand = f"Delete FROM [{calendar_table_name}] WHERE [Date]>=? And [Date]<=?"
params = (required_starting_date, required_ending_date)
required_starting_date & required_ending_date 是 "TimeStamp" 格式
calendar_tbl_connection = pyodbc.connect(driver=driver, server=required_server, database=database_name,
trusted_connection='yes')
calendar_tbl_cursor = calendar_tbl_connection.cursor()
calendar_tbl_cursor.execute(Delete_SQLCommand,params)
calendar_tbl_connection.commit
calendar_tbl_connection.close()
这段代码有 3 个(至少)不同的问题:
- 您正在使用 pandas 时间戳类型而不是预期的 python 日期时间类型。 Roganosh answer explains that
- 您将 sql 标识符(table 名称)与 sql 值(日期)混合在一起。您只能将值作为参数传递给
cursor.execute
。 see chepner's answer.
- 您调用
cursor.execute
的参数不正确。
cursor.execute
需要两个参数。由于您的 SQLCommand
变量是一个元组,因此您可以在调用 cursor.execute
.
时使用 *
将查询字符串和变量解压缩为两个参数
SQLCommand = (
"DELETE FROM table_name WHERE date >= %s",
(datetime.date(2019, 08, 23),)
)
cursor.execute(*SQLCommand)
请注意,您不能将 sql 标识符(例如 table 名称)作为参数传递给 cursor.execute
方法。 The Python Database API Specification 未指定如何使用动态标识符(例如列或 table 名称)构建查询。
您没有说明您使用哪个库进行 SQL 访问,但这是一个使用 psycopg
.
的安全示例
from psycopg2 import sql
cmd = sql.SQL("delete from {} where date >= %s and date <= %s")
table_name = sql.Identifier(calendar_table_name)
cur.execute(
cmd.format(table_name),
[required_starting_date, required_ending_date]
)
请注意,这 不是 str.format
被调用,而是 SQL.format
。该库确保 calendar_table_name
是正确的列名,并且 SQL.format
确保它在生成有效的参数化查询之前正确地合并到您的命令模板中。
如果没有适当的库支持,您将需要执行一些 类动态查询生成。它应该是 restricted 排序,不过,限制越多越好。最安全的方法是从查找 table 硬编码查询开始:
queries = {
'name1': 'delete from name1 where ... ',
'name2': 'delete from name2 where ...',
}
这样,您不能为任意table名称构建查询,只能select一个预先构建的查询。
第二种方法是将构造函数包装在一个首先检查有效 table 名称的函数中。例如,
def generate_query(table_name):
if table_name not in ['name1', 'name2', ...]:
raise ValueError("Invalid table name")
return "delete from {} where ...".format(table_name)
pyodbc 可以毫无问题地处理 pandas' Timestamp
值作为正确 参数化查询的输入:
# test data
calendar_table_name = "#calendar_table"
crsr.execute(f"CREATE TABLE [{calendar_table_name}] ([Date] date)")
crsr.execute(f"INSERT INTO [{calendar_table_name}] VALUES ('2019-08-22'),('2019-08-24')")
df = pd.DataFrame(
[(datetime(2019, 8, 23, 0, 0), datetime(2019, 8, 25, 0, 0))],
columns=['required_starting_date', 'required_ending_date'])
required_starting_date = df.iloc[0][0]
required_ending_date = df.iloc[0][1]
print(type(required_starting_date)) # <class 'pandas._libs.tslibs.timestamps.Timestamp'>
# test
sql = f"DELETE FROM [{calendar_table_name}] WHERE [Date]>=? AND [Date]<=?"
params = (required_starting_date, required_ending_date)
crsr.execute(sql, params)
cnxn.commit()
#verify
rows = crsr.execute(f"SELECT * FROM [{calendar_table_name}]").fetchall()
print(rows) # [(datetime.date(2019, 8, 22), )]
我正在尝试在 Python、
中做这样的事情SQLCommand = ("Delete From %s where [Date] >= %s and [Date] <= %s", (calendar_table_name, required_starting_date, required_ending_date))
cursor.execute(SQLCommand)
calendar_table_name
是一个 string
变量
required_starting_date
是一个 datetime
变量
required_ending_date
是一个 datetime
变量
尝试这个给我一个错误:
The first argument to execute must be a string or unicode query.
试过这个,它给了我同样的错误:
SQLCommand = ("Delete From " + calendar_table_name + " where [Date] >= %s and [Date] <= %s", ( required_starting_date, required_ending_date))
cursor.execute(SQLCommand)
编辑:
type(required_ending_date)
Out[103]: pandas._libs.tslibs.timestamps.Timestamp
type(required_starting_date)
Out[103]: pandas._libs.tslibs.timestamps.Timestamp
这对我来说适用于 SSMS,
delete from [table_test] where [Date] >= '2007-01-01' and [Date] <= '2021-01-01';
更新:-这是我正在尝试使用的代码
Delete_SQLCommand = f"Delete FROM [{calendar_table_name}] WHERE [Date]>=? And [Date]<=?"
params = (required_starting_date, required_ending_date)
required_starting_date & required_ending_date 是 "TimeStamp" 格式
calendar_tbl_connection = pyodbc.connect(driver=driver, server=required_server, database=database_name,
trusted_connection='yes')
calendar_tbl_cursor = calendar_tbl_connection.cursor()
calendar_tbl_cursor.execute(Delete_SQLCommand,params)
calendar_tbl_connection.commit
calendar_tbl_connection.close()
这段代码有 3 个(至少)不同的问题:
- 您正在使用 pandas 时间戳类型而不是预期的 python 日期时间类型。 Roganosh answer explains that
- 您将 sql 标识符(table 名称)与 sql 值(日期)混合在一起。您只能将值作为参数传递给
cursor.execute
。 see chepner's answer. - 您调用
cursor.execute
的参数不正确。
cursor.execute
需要两个参数。由于您的 SQLCommand
变量是一个元组,因此您可以在调用 cursor.execute
.
*
将查询字符串和变量解压缩为两个参数
SQLCommand = (
"DELETE FROM table_name WHERE date >= %s",
(datetime.date(2019, 08, 23),)
)
cursor.execute(*SQLCommand)
请注意,您不能将 sql 标识符(例如 table 名称)作为参数传递给 cursor.execute
方法。 The Python Database API Specification 未指定如何使用动态标识符(例如列或 table 名称)构建查询。
您没有说明您使用哪个库进行 SQL 访问,但这是一个使用 psycopg
.
from psycopg2 import sql
cmd = sql.SQL("delete from {} where date >= %s and date <= %s")
table_name = sql.Identifier(calendar_table_name)
cur.execute(
cmd.format(table_name),
[required_starting_date, required_ending_date]
)
请注意,这 不是 str.format
被调用,而是 SQL.format
。该库确保 calendar_table_name
是正确的列名,并且 SQL.format
确保它在生成有效的参数化查询之前正确地合并到您的命令模板中。
如果没有适当的库支持,您将需要执行一些 类动态查询生成。它应该是 restricted 排序,不过,限制越多越好。最安全的方法是从查找 table 硬编码查询开始:
queries = {
'name1': 'delete from name1 where ... ',
'name2': 'delete from name2 where ...',
}
这样,您不能为任意table名称构建查询,只能select一个预先构建的查询。
第二种方法是将构造函数包装在一个首先检查有效 table 名称的函数中。例如,
def generate_query(table_name):
if table_name not in ['name1', 'name2', ...]:
raise ValueError("Invalid table name")
return "delete from {} where ...".format(table_name)
pyodbc 可以毫无问题地处理 pandas' Timestamp
值作为正确 参数化查询的输入:
# test data
calendar_table_name = "#calendar_table"
crsr.execute(f"CREATE TABLE [{calendar_table_name}] ([Date] date)")
crsr.execute(f"INSERT INTO [{calendar_table_name}] VALUES ('2019-08-22'),('2019-08-24')")
df = pd.DataFrame(
[(datetime(2019, 8, 23, 0, 0), datetime(2019, 8, 25, 0, 0))],
columns=['required_starting_date', 'required_ending_date'])
required_starting_date = df.iloc[0][0]
required_ending_date = df.iloc[0][1]
print(type(required_starting_date)) # <class 'pandas._libs.tslibs.timestamps.Timestamp'>
# test
sql = f"DELETE FROM [{calendar_table_name}] WHERE [Date]>=? AND [Date]<=?"
params = (required_starting_date, required_ending_date)
crsr.execute(sql, params)
cnxn.commit()
#verify
rows = crsr.execute(f"SELECT * FROM [{calendar_table_name}]").fetchall()
print(rows) # [(datetime.date(2019, 8, 22), )]