sqlite中的变量表名

Nar*_*ser 36 python database sqlite

问题:是否可以使用变量作为表名而不必使用字符串构造函数来执行此操作?


信息:

我正在开展一个项目,目的是对我的星模拟数据进行编目.为此,我将所有数据加载到sqlite数据库中.它工作得很好,但我决定为我的数据库增加更多的灵活性,效率和可用性.我计划稍后在模拟中添加小行星,并希望每个星都有一个表格.这样我就不必在每个太阳系中查询一个20m的某些小行星的表格.

我被告知使用字符串构造函数很糟糕,因为它让我容易受到SQL注入攻击.虽然这不是什么大问题,因为我是唯一可以访问这些dbs的人,但我想遵循最佳实践.而且这种方式如果我做一个类似的情况,它向公众开放,我知道该怎么做.

目前我这样做:

cursor.execute("CREATE TABLE StarFrame"+self.name+" (etc etc)")
Run Code Online (Sandbox Code Playgroud)

这有效,但我想做更多的事情:

cursor.execute("CREATE TABLE StarFrame(?) (etc etc)",self.name)
Run Code Online (Sandbox Code Playgroud)

虽然我明白这可能是不可能的.虽然我愿意接受类似的东西

cursor.execute("CREATE TABLE (?) (etc etc)",self.name)
Run Code Online (Sandbox Code Playgroud)

如果这根本不可能,我会接受这个答案,但如果有人知道如何做到这一点,请告诉我.:)

我在python中编码.

Don*_*ner 38

不幸的是,表格不能成为参数替换的目标(我没有找到任何明确的来源,但我在一些网络论坛上看到过).

如果您担心注入(您可能应该这样做),您可以编写一个在传递字符串之前清除字符串的函数.由于您只是在寻找一个表名,因此您应该安全地接受字母数字,删除所有标点符号,例如)(][;,空格.基本上,只要保持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'
Run Code Online (Sandbox Code Playgroud)

  • 就个人而言,如果看到这样的字符,我会抛出异常.他们一定不能在那里,所以有些事情是错的,我宁愿知道. (17认同)
  • 所以这是不可能的.这就是我需要知道的.你建议的擦洗方法看起来非常好.谢谢! (2认同)
  • -1; 这个答案的细节似乎有缺陷.这是过于严格的限制(例如,不允许表名中的下划线,这是相当普遍的),正如@JanHudec所指出的,如果`scrub()`实际上删除了任何字符,那几乎肯定会打破查询; 这应该导致立即抛出异常而不是等待查询执行时间来查找. (2认同)
  • 问题是参数只能替换值,而不能替换其他标识符或 SQL 的一般位。这意味着将它们注入到查询的字节编码版本中很简单。更一般地说,替换需要重新编译查询(是的,即使只是更改表或列名称),因此 SQLite 引擎会说“不”,您需要使用外部语言来执行此操作。 (2认同)

jub*_*nna 10

对于寻找将表作为变量的方法的人们,我从这里对同一问题的另一个回复中得到了这个:

它说了以下内容并且有效。全部引用自mhawke:

您不能对表名使用参数替换。您需要自己将表名添加到查询字符串中。像这样的东西:

query = 'SELECT * FROM {}'.format(table)
c.execute(query)
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是表名值的来源。如果它来自不受信任的来源,例如用户,那么您需要验证表名以避免潜在的 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
Run Code Online (Sandbox Code Playgroud)


Ned*_*der 9

我不会将数据分成多个表.如果在星形列上创建索引,则无法有效地访问数据.

  • 您需要了解有关SQLite和所有关系数据库如何工作的更多信息.他们使用索引快速查找所需的行.你所描述的被称为"全表扫描",是的,它是可怕的.但它很容易避免.人们总是制作包含数百万行的表,而不必承担全表扫描的费用. (2认同)