Python 由于在形成SQL查询时不支持字符串替换,如何动态分配表名?
sqlite3还很陌生,所以请在这里耐心听我说 我希望有一个可以传递表名和要更新的值的函数 我最初是这样开始的:Python 由于在形成SQL查询时不支持字符串替换,如何动态分配表名?,python,sqlite,Python,Sqlite,sqlite3还很陌生,所以请在这里耐心听我说 我希望有一个可以传递表名和要更新的值的函数 我最初是这样开始的: def add_to_table(table_name, string): cursor.execute('INSERT INTO {table} VALUES ({var})' .format( table=table_name, var=string) ) 这是可行的,但进一步阅读sqlit
def add_to_table(table_name, string):
cursor.execute('INSERT INTO {table} VALUES ({var})'
.format(
table=table_name,
var=string)
)
这是可行的,但进一步阅读sqlite3表明,这是一种非常不安全的方式。但是,使用它们的?
语法,我无法传入一个名称来指定变量
我尝试添加一个?
来代替表,但这会引发语法错误
cursor.execute('INSERT INTO ? VALUES (?)', ('mytable','"Jello, world!"'))
>> >sqlite3.OperationalError: near "?": syntax error
sql语句中的
表
能否安全、动态地传递 问题不在于动态字符串替换本身。它的动态字符串替换为用户提供的字符串,这是一个大问题,因为这会使您面临SQL注入攻击。如果您完全100%确定tablename是您控制的安全字符串,那么将其拼接到SQL查询中是安全的
if some_condition():
table_name = 'TABLE_A'
else:
table_name = 'TABLE_B'
cursor.execute('INSERT INTO '+ table_name + 'VALUES (?)', values)
这就是说,像这样使用动态SQL肯定是一种代码味道,因此您应该仔细检查,看看是否可以找到一种没有动态生成的SQL字符串的更简单的替代方法。此外,如果您真的需要动态SQL,那么像SQLAlchemy这样的东西可能有助于确保生成的SQL格式正确。问题不在于动态字符串替换本身。它的动态字符串替换为用户提供的字符串,这是一个大问题,因为这会使您面临SQL注入攻击。如果您完全100%确定tablename是您控制的安全字符串,那么将其拼接到SQL查询中是安全的
if some_condition():
table_name = 'TABLE_A'
else:
table_name = 'TABLE_B'
cursor.execute('INSERT INTO '+ table_name + 'VALUES (?)', values)
这就是说,像这样使用动态SQL肯定是一种代码味道,因此您应该仔细检查,看看是否可以找到一种没有动态生成的SQL字符串的更简单的替代方法。此外,如果您真的想要动态SQL,那么像SQLAlchemy这样的东西可能有助于确保生成的SQL格式正确。使用字符串操作编写SQL语句是奇怪的,这不仅是因为安全问题,还因为字符串是“哑”对象。使用sqlalchemy核心(您甚至不需要ORM部分)几乎就像使用字符串一样,但是每个片段都会更加智能,并且允许更容易的组合。看一看这本书,了解一下我在说什么 例如,使用sqlsoup时,您的代码如下所示:
db = SQLSoup('sqlite://yourdatabase')
table = getattr(db, tablename)
table.insert(fieldname='value', otherfield=123)
db.commit()
另一个优点:代码独立于数据库-是否要迁移到oracle?更改连接字符串就完成了。使用字符串操作编写SQL语句很奇怪,这不仅是因为存在安全隐患,还因为字符串是“哑”对象。使用sqlalchemy核心(您甚至不需要ORM部分)几乎就像使用字符串一样,但是每个片段都会更加智能,并且允许更容易的组合。看一看这本书,了解一下我在说什么 例如,使用sqlsoup时,您的代码如下所示:
db = SQLSoup('sqlite://yourdatabase')
table = getattr(db, tablename)
table.insert(fieldname='value', otherfield=123)
db.commit()
另一个优点:代码独立于数据库-是否要迁移到oracle?更改连接字符串,您就完成了。我……真的看不到这方面的使用案例……我对您的动机感到困惑。通过这样做,您希望实现什么?您应该知道要将数据插入到哪个表中。使用类似sqlalchemy的ORM。您是否可以重构您的数据,以使您拥有(比如)带有类型列的食物表,而不是垃圾邮件表和鸡蛋表?(如果您不知道这个问题的答案,可以发布另一个带有精简模式的问题,并询问如何改进它,从而不需要动态表选择?)通常,当您认为需要这样的动态SQL时,答案是错误的数据模型。但是“通常”并不是“总是”,而且在你必须这样做的少数情况下,字符串格式是唯一的选择。我…真的看不到这方面的使用案例…我对你的动机感到困惑。通过这样做,您希望实现什么?您应该知道要将数据插入到哪个表中。使用类似sqlalchemy的ORM。您是否可以重构您的数据,以使您拥有(比如)带有类型列的食物表,而不是垃圾邮件表和鸡蛋表?(如果您不知道这个问题的答案,可以发布另一个带有精简模式的问题,并询问如何改进它,从而不需要动态表选择?)通常,当您认为需要这样的动态SQL时,答案是错误的数据模型。但“通常”并非“总是”,在极少数情况下,字符串格式是唯一的选择。表名和
值之间缺少空格。(这是字符串格式优于串联的许多原因之一。而且,由于OP在他的问题中使用了格式
,因此不必担心他不会理解它……)表名和值之间缺少空格。(这是字符串格式优于串联的众多原因之一。而且,由于OP在他的问题中使用了格式
,因此他不必担心自己不理解它……)