0

我正在实现一个学生数据库项目,它有多个表,如学生、班级、部分等

我写了一个 delete_table 函数,它接受参数表名和值来从特定表中删除一行,但我的代码中似乎存在某种语法错误:

def delete_tables(tab_name,attr,value):
    c.execute("delete from table=:tab_name where attribute=:attr is value=:value ",{'tab_name':tab_name, 'attr': attr, 'value': value})

输入:delete_tables('section','sec_name','S1')

错误文本:

c.execute("从表中删除=:tab_name 其中属性=:attr 是值=:value ",{'tab_name':tab_name, 'attr': attr, 'value': value})

sqlite3.OperationalError:靠近“表”:语法错误

我已经尝试了所有提到的答案,你们都建议的是,即使它成功了,它也会是不安全的。那么我是否必须编写函数来单独删除每个表,而不是使用一个函数,还有其他替代方法可以解决这个问题吗?我不需要继续为 n 个表编写 n 个函数??????提前致谢 :))

4

3 回答 3

0
def delete_tables(tab_name, attr, value):
    c.execute("delete from " + tab_name + "where " + attr + " = " + value)

我认为这样的事情会起作用,问题是您正在尝试修改属性但其名称始终attribute为 ,因为您希望将其设为参数以便正确处理它。

希望它有所帮助。

编辑:

检查这个SQLite python

c.execute 所做的是“执行”一个 SQL 查询,因此,c.execute("select * from clients")如果你有一个clients表,你可以做一些事情。

execute进行查询并为您提供结果集(如果是这种情况),因此如果您想使用普通 SQL 查询从表中删除,您可以在控制台中键入,delete from clients where client_id = 12该语句将删除 id 等于 12 的客户端。

现在,如果你在 python 中使用 SQLite,你会做

c.execute("delete from clients where client_id = 12")

但正如您希望它适用于任何表和任何字段(属性),它会输入表名、字段名和该字段的值作为变量。

tableName = "clients"
field = "client_id"
value = "12" #must be string because you would have to cast it from int in the execute
"""
if value is a varchar you must write
value = "'12'" because the '' are needed.
"""
c.execute("delete from " + tableName + " where " + field + " = " + value)

最重要的是,您希望它成为一个函数

def delete_tables(tableName, field, value):
    c.execute("delete from " + tableName+ "where " + field + " = " + value)

编辑2:

亚伦的评论是真的,它不安全,下一步你要做的是

def delete_tables(tab_name, attr, value):
    #no ':value' (it limits the value to characters)
    c.execute("delete from :tab_name where :attr = :value",
        {'tab_name': tab_name, 'attr': attr, 'value':value})

这是来自Vatsal的回答

于 2020-04-01T04:02:08.070 回答
0

您需要查看将在 python 方法中执行的确切 SQL 命令。对于方法调用 delete_tables('section', 'sec_name', 'S1'),将生成的 SQL 命令将是

delete from table=section where attribute=sec_name is value=S1

这将是 SQL 中的无效命令。正确的命令应该是

delete from section where sec_name='S1'

所以你需要相应地改变你的python函数。需要进行的更改应如下所示:

def delete_tables(tab_name, attr, value):
    c.execute("delete from :tab_name where :attr = ':value'",
        {'tab_name': tab_name, 'attr': attr, 'value':value})
于 2020-04-01T04:35:30.820 回答
0

问题是您不能:tab_name对值以外的事物使用参数化查询(即)(?不确定我使用的术语是否正确):表名、列名和 SQL 关键字是禁止的。

  • where age > :max_age没关系。
  • where :some_col > :max_age不是。
  • where age :comparison_operator :max_age不行。

现在,您可以使用字符串连接或 f 字符串构建自己的查询,但是……这是一个巨大的 SQL 注入风险。请参阅Bobby 表 更不用说当您必须处理字符、数字或 None 时,将值连接到 SQL 查询字符串中会很快遇到问题。(无 => NULL,字符需要引号,数字不需要)。

您可以使用仅接受表名和列名的已知值的字符串替换来构建查询,然后使用参数化查询来驱动删除条件值:value

(虽然这似乎有限制,但让随机调用者确定要删除哪些表是不安全的)。

就像是:

delete_tables(tab_name,attr,value):

   safe_tab_name = my_dict_of_known_table_names[tab_name]

   safe_attr = my_dict_of_known_column_names[attr]

                         # you have to `=`, not `is` here 
   qry = f"delete from {safe_tab_name} where {safe_attr} = :value "

   # not entirely sure about SQLite's bind/parametrized syntax.
   # look it up if needed.
   c.execute(qry, dict(value = value))

假设用户只直接输入值,那么至少可以防止 SQL 注入。

于 2020-04-01T05:30:23.253 回答