问题:是否可以使用变量作为表名而不必使用字符串构造函数来执行此操作?
信息:
我正在开展一个项目,目的是对我的星模拟数据进行编目。为此,我将所有数据加载到sqlite数据库中。它工作得很好,但我决定为我的数据库增加更多的灵活性,效率和可用性。我计划稍后在模拟中添加小行星,并希望每个星都有一个表格。这样我就不必在每个太阳系中查询一个20m的某些小行星的表格。
我被告知使用字符串构造函数很糟糕,因为它让我容易受到SQL注入攻击。虽然这不是什么大问题,因为我是唯一可以访问这些dbs的人,但我想遵循最佳实践。而且如果我做一个类似于公众开放的项目的项目,我知道该做什么。
目前我正在这样做:
cursor.execute("CREATE TABLE StarFrame"+self.name+" (etc etc)")
这有效,但我想做更多的事情:
cursor.execute("CREATE TABLE StarFrame(?) (etc etc)",self.name)
虽然我明白这可能是不可能的。虽然我会满足于像
这样的东西cursor.execute("CREATE TABLE (?) (etc etc)",self.name)
如果这根本不可能,我会接受这个答案,但如果有人知道如何做到这一点,请告诉我。 :)
我在python中编码。
答案 0 :(得分:37)
不幸的是,表格不能成为参数替换的目标(我没有找到任何明确的来源,但我在一些网络论坛上看到过它。)
如果您担心注入(您可能应该这样做),您可以编写一个在传递之前清除字符串的函数。由于您只是在寻找一个表名,因此您应该安全地接受字母数字,删除所有标点符号,例如)(][;,
和空格。基本上,只需保留A-Z a-z 0-9
。
def scrub(table_name):
return ''.join( chr for chr in table_name if chr.isalnum() )
scrub('); drop tables --') # returns 'droptables'
答案 1 :(得分:9)
我不会将数据分成多个表。如果您在星列上创建索引,则无法有效访问数据。
答案 2 :(得分:3)
对于那些寻求将表变成变量的人来说,我是从对相同问题here的另一个答复中得到的:
它说了以下内容,并且有效。全部引用 mhawke :
您不能使用参数替换表名称。您需要自己将表名称添加到查询字符串中。像这样:
query = 'SELECT * FROM {}'.format(table)
c.execute(query)
要注意的一件事是表名的值的来源。如果来自不可信来源,例如用户,则需要验证表名,以避免潜在的SQL注入攻击。一种方法可能是构造一个参数化查询,该查询从数据库目录中查找表名称:
import sqlite3
def exists_table(db, name):
query = "SELECT 1 FROM sqlite_master WHERE type='table' and name = ?"
return db.execute(query, (name,)).fetchone() is not None
答案 3 :(得分:1)
尝试字符串格式化:
sql_cmd = '''CREATE TABLE {}(id, column1, column2, column2)'''.format(
'table_name')
db.execute(sql_cmd)
将'table_name'
替换为您的愿望。
答案 4 :(得分:0)
您可以使用类似这样的内容
conn = sqlite3.connect()
createTable = '''CREATE TABLE %s (# );''' %dateNow)
conn.execute(createTable)
基本上,例如,如果我们想根据当前日期将数据分为几个表,则您想基于日期监视系统。
createTable ='''CREATE TABLE%s(#);'''%dateNow)意味着您创建了一个带有变量dateNow的表,根据您的编码语言,您可以将dateNow定义为变量以检索当前日期从您的编码语言开始。
答案 5 :(得分:0)
为了避免对表名进行硬编码,我使用了:
Swiper(
itemCount: widget.product.images.length,
itemBuilder: (BuildContext context, int index) {
return Image.network(
widget.product.images[index].src,
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
);
},
pagination: new SwiperPagination(),
control: new SwiperControl(),
),
答案 6 :(得分:-1)
正如在其他答案中所说的那样,"表不能成为参数替换的目标"但如果您发现自己处于无法选择的绑定中,则可以使用以下方法测试所提供的表名是否有效 注意:为了覆盖所有的基础,我已经把桌子名称变成了真正的猪。
import sys
import sqlite3
def delim(s):
delims="\"'`"
use_delim = []
for d in delims:
if d not in s:
use_delim.append(d)
return use_delim
db_name = "some.db"
db = sqlite3.connect(db_name)
mycursor = db.cursor()
table = 'so""m ][ `etable'
delimiters = delim(table)
if len(delimiters) < 1:
print "The name of the database will not allow this!"
sys.exit()
use_delimiter = delimiters[0]
print "Using delimiter ", use_delimiter
mycursor.execute('SELECT name FROM sqlite_master where (name = ?)', [table])
row = mycursor.fetchall()
valid_table = False
if row:
print (table,"table name verified")
valid_table = True
else:
print (table,"Table name not in database", db_name)
if valid_table:
try:
mycursor.execute('insert into ' +use_delimiter+ table +use_delimiter+ ' (my_data,my_column_name) values (?,?) ',(1,"Name"));
db.commit()
except Exception as e:
print "Error:", str(e)
try:
mycursor.execute('UPDATE ' +use_delimiter+ table +use_delimiter+ ' set my_column_name = ? where my_data = ?', ["ReNamed",1])
db.commit()
except Exception as e:
print "Error:", str(e)
db.close()
答案 7 :(得分:-1)
您可以将查询保存在 .sql 或 txt 文件中,并使用 open().replace() 方法在查询的任何部分使用变量。长期读者,但第一次发帖,所以如果这里有任何问题,我深表歉意。
```SQL in yoursql.sql```
Sel *
From yourdbschema.tablenm
```SQL to run```
tablenm = 'yourtablename'
cur = connect.cursor()
query = cur.execute(open(file = yoursql.sql).read().replace('tablenm',tablenm))
答案 8 :(得分:-3)
您可以将字符串作为SQL命令传递:
import sqlite3
conn = sqlite3.connect('db.db')
c = conn.cursor()
tablename, field_data = 'some_table','some_data'
query = 'SELECT * FROM '+tablename+' WHERE column1=\"'+field_data+"\""
c.execute(query)