在 SQLAlchemy 中,使用 :param
和 %s
作为占位符的方式有所不同,主要体现在以下几个方面:
1. SQLAlchemy 原生方式 (:param
)
特点:
- 使用
:param
作为占位符。 - 适用于 SQLAlchemy 的
text()
函数。 - 参数以字典形式传递。
示例:
from sqlalchemy import create_engine, text
engine = create_engine('mysql+pymysql://username:password@host/dbname')
query = text("SELECT * FROM table WHERE column = :value")
params = {"value": "example"}
with engine.connect() as connection:
result = connection.execute(query, params)
2. DB-API 兼容方式 (%s
)
特点:
- 使用
%s
作为占位符。 - 适用于底层数据库驱动,如 PyMySQL、psycopg2 等。
- 参数可以以元组或字典形式传递,具体取决于驱动的实现。
示例:
import pymysql
connection = pymysql.connect(host='host', user='username', password='password', db='dbname')
query = "SELECT * FROM table WHERE column = %s"
params = ("example",)
with connection.cursor() as cursor:
cursor.execute(query, params)
result = cursor.fetchall()
具体区别
-
占位符格式:
-
:param
是 SQLAlchemy 的原生格式,用于text()
函数。 -
%s
是 DB-API 兼容格式,用于底层数据库驱动。
-
-
参数传递方式:
-
:param
需要使用字典形式传递参数。 -
%s
可以使用元组或字典形式传递参数,具体取决于底层驱动。
-
-
使用场景:
-
:param
适用于 SQLAlchemy 的text()
函数以及 ORM 查询。 -
%s
适用于直接使用底层数据库驱动进行查询。
-
结合 SQLAlchemy 和 PyMySQL
如果你使用 SQLAlchemy 并通过 PyMySQL 连接 MySQL 数据库,推荐使用 SQLAlchemy 的 text()
函数和 :param
占位符,因为这符合 SQLAlchemy 的设计理念,并且更安全和易于维护。
示例代码
以下是使用 SQLAlchemy 和 :param
占位符的完整示例:
from sqlalchemy import create_engine, text
import pandas as pd
import numpy as np
# 假设你已经创建了数据库连接
engine = create_engine('mysql+pymysql://username:password@host/dbname')
def fetch_data(query, params):
with engine.connect() as connection:
result = connection.execute(text(query), params)
return pd.DataFrame(result.fetchall(), columns=result.keys())
def preprocess_data(df, date_column):
# 假设你有一个预处理函数
df[date_column] = pd.to_datetime(df[date_column])
return df
def calculate_index(code, industry, years):
year_report_str = ",".join([f"'{year}年报'" for year in years])
year_report_str_abstract = ",".join([f"'{year}1231'" for year in years])
df_zcfz = preprocess_data(fetch_data(
f"SELECT * FROM stock_zcfz WHERE `SECURITY_CODE` = :code AND REPORT_DATE_NAME IN ({year_report_str})",
{"code": code}
), 'REPORT_DATE')
df_lrb = preprocess_data(fetch_data(
f"SELECT * FROM stock_lrb WHERE `SECURITY_CODE` = :code AND REPORT_DATE_NAME IN ({year_report_str})",
{"code": code}
), 'REPORT_DATE')
df_xjll = preprocess_data(fetch_data(
f"SELECT * FROM stock_xjll WHERE `SECURITY_CODE` = :code AND REPORT_DATE_NAME IN ({year_report_str})",
{"code": code}
), 'REPORT_DATE')
df_abstract = preprocess_data(fetch_data(
f"SELECT * FROM stock_abstract WHERE `股票代码` = :code AND 报告期 IN ({year_report_str_abstract})",
{"code": code}
), '报告期')
df_wind = fetch_data(
"SELECT * FROM wind_data WHERE LEFT(`证券代码`, 6) = :code",
{"code": code}
).replace({None: np.nan})
df_abstract = df_abstract[df_abstract['营业总收入'] != 0].reset_index(drop=True)
# 继续处理数据和计算指标
# ...
return df_zcfz, df_lrb, df_xjll, df_abstract, df_wind
# 示例调用
code = '002582'
industry = '食品饮料'
years = ['2020', '2021', '2022', '2023']
calculate_index(code, industry, years)
通过这种方式,你可以确保参数传递的正确性和查询的安全性。