Python中如何在SQL语句字符串中嵌入变量
正确嵌入数据库名到SQL语句的方法
首先,你原来的代码里,cur.execute("TRUNCATE TABLE {db}.my_table")这种写法不会替换{db},因为这是普通字符串,不是f-string。而你尝试的f-string写法能完成变量替换,但要注意直接用f-string嵌入标识符(数据库名、表名)存在SQL注入风险——不过如果db是从你自己维护的environment.yml读取的可信值,没有外部输入的话,这种方式是可以用的。
方法1:可信场景下使用f-string
如果确定db是安全可信的,直接把SQL字符串改成f-string即可:
config={} with open('environment.yml','r') as f: config = yaml.safe_load(f) db = config['database_name'] # TRUNCATE语句用f-string格式化 result = cur.execute(f"TRUNCATE TABLE {db}.my_table") # INSERT语句同理 result = cur.executemany(f'''INSERT INTO {db}.my_table (id, description, code) VALUES (?, ?, ?)''', [tuple(row) for row in co.values])
注意:这里的参数(?, ?, ?)仍然要用占位符,不能用f-string嵌入数据值,数据值必须通过参数化查询来防止注入。
方法2:更安全的标识符转义(推荐)
如果要完全避免风险,不管db来源如何,都应该用数据库驱动提供的标识符转义函数来处理数据库名/表名。不同驱动的实现不同,举几个常见例子:
- PostgreSQL(psycopg2):用
psycopg2.extensions.quote_identfrom psycopg2.extensions import quote_ident escaped_db = quote_ident(db, cur.connection) result = cur.execute(f"TRUNCATE TABLE {escaped_db}.my_table") - MySQL(mysql-connector):用
mysql.connector.conversion.MySQLConverter.escape_identifierfrom mysql.connector.conversion import MySQLConverter converter = MySQLConverter(cur.connection) escaped_db = converter.escape_identifier(db) result = cur.execute(f"TRUNCATE TABLE {escaped_db}.my_table") - SQLite:SQLite的标识符用双引号包裹,你可以手动转义内部的双引号:
escaped_db = db.replace('"', '""') result = cur.execute(f'TRUNCATE TABLE "{escaped_db}".my_table')
关键提醒
- 永远不要用f-string或字符串拼接嵌入数据值,数据值必须用
?(或驱动对应的占位符,比如%s、%())通过参数化查询传递,就像你代码里的INSERT语句那样。 - 只有标识符(数据库名、表名、列名)才需要用上述方式处理,数据值绝对不能这么做。
内容的提问来源于stack exchange,提问作者David Jackson
相关产品推荐
相关产品推荐

