可重用的 python 函数从 sqlite 表中检索数据的问题

Problem with a reusable python function to retrieve data from sqlite table

提问人:Z.Edibo 提问时间:11/16/2023 最后编辑:BarmarZ.Edibo 更新时间:11/16/2023 访问量:77

问:

你好,祝你们有美好的一天,无论你现在在哪里。我有一个关于python可重用函数的问题,用于从sqlite数据库中检索数据。我所说的可重用是指一个函数,我可以插入任何需要它的代码段。如果你有合适的名字,不要犹豫,教育我,我愿意向你学习。 无论如何,下面是代码。

def retrieve_data(self, table_name, columns="*", condition=""):
    try:
        # Construct the SELECT query
        select_query = f"SELECT {columns} FROM {table_name} {condition};"

        # Execute the select query
        cursor.execute(select_query)

        # Fetch all rows
        result = cursor.fetchall()

        return result

    except sqlite3.Error as e:
        print(f"Error retrieving data: {e}")
        return None

现在的问题是,当我在代码中调用上述函数时,它将从 wxpython 文本小部件获取的值作为列,而不是该列中的值,从而抛出列不存在错误。例如,列名是column_name,用户从文本小部件输入的值是value_in_column,它将value_in_column作为column_name。因此,它会抛出此错误 Error retriating data: no such column: the_text_gotten from the wxpython tet entry widget。

在下面查看我用于调用可重用函数的代码。

def add_subject(self, event):
    if self.subject_name_text.GetValue()!="":
        get_subject_list = SchoolManagementSystem.retrieve_data(SchoolManagementSystem, "subject", "subject_name", f"where subject_name = {self.subject_name_text.GetValue()}")

        subject_list = list(get_subject_list)
        if self.subject_name_text.GetValue() in subject_list:
            print(f"Class {self.subject_name_text.GetValue()} already exists.")
        else:
            subject_list.append(self.subject_name_text.GetValue())
            print(f"Subject {self.subject_name_text.GetValue()}")
            print(subject_list)
        SchoolManagementSystem.insert_row(SchoolManagementSystem, "subject", {"subject_name":self.subject_name_text.GetValue()})

我试过修补条件参数中的字符串,因为我怀疑这是我头痛的根源,但我没有成功。因此,我把它带到这里让专家帮助我。我期待您的有用回复。谢谢。

python 函数 sqlite

评论

1赞 Barmar 11/16/2023
所有函数都有可能重用,这就是定义它们的意义所在。
3赞 roganjosh 11/16/2023
你的尝试既太聪明又太愚蠢。 当你的函数甚至没有尝试考虑参数化时,是噩梦般的燃料。你不能现实地把你要做的事情归结为一个单一的“全能”功能。查找 SQL 注入f"SELECT {columns} FROM {table_name} {condition};"

答:

1赞 Barmar 11/16/2023 #1

您需要将输入的值放在引号中。

f"where subject_name = '{self.subject_name_text.GetValue()}'"

但是,像这样将值直接替换到查询字符串中并不是一个好主意(例如,如果值包含引号,则不起作用),您应该使用带有占位符和单独参数列表的查询。请参阅如何在 Python 的 SQL 语句中使用变量?

def retrieve_data(self, table_name, columns="*", condition="", values=()):
    try:
        # Construct the SELECT query
        select_query = f"SELECT {columns} FROM {table_name} {condition};"

        # Execute the select query
        cursor.execute(select_query, values)

        # Fetch all rows
        result = cursor.fetchall()

        return result

    except sqlite3.Error as e:
        print(f"Error retrieving data: {e}")
        return None

然后你这样称呼它:

get_subject_list = SchoolManagementSystem.retrieve_data(SchoolManagementSystem, "subject", "subject_name", "where subject_name = ?", (self.subject_name_text.GetValue(),))

评论

2赞 Barmar 11/16/2023
请不要浪费时间试图让它发挥作用。使用带参数的版本。
1赞 roganjosh 11/16/2023
我发现太多了。在这种情况下让它工作是一回事,但我会在代码审查中拒绝它。我不能称它为“神物”,但这太过分了。如果这是你的一般做法,那很好,但这不是我的。对我来说,连接对象应该传递给每个函数retrieve_data
1赞 Barmar 11/16/2023
我不是专业的 Python 程序员,我只是在 SO 上玩一个,所以我没有“一般做法”。但建议在查询中使用占位符。很多人喜欢编写这样的通用查询过程,我同意你的看法,它们并不是真正必要的,而是每个人自己的。
1赞 Barmar 11/16/2023
听起来您在调用函数时忘记了参数,因此它使用了默认值。(self.subject_name_text.GetValue(),)
1赞 Barmar 11/16/2023
我刚刚测试了我的代码,它有效。我把它简化为一个普通的函数而不是一个方法,因为我没有你的类结构,但这应该没有区别。
3赞 piotre10 11/16/2023 #2

如前所述,稍微改变一下概念可能会有所帮助。您可以尝试制作更具体的功能,例如:

def get_subject_by_name(self, subject_name: str):
    query = "SELECT col1 as col_alias1, col2 as col_alias2 FROM subject_table where subject_name = ?"
    cursor.execute(query, (subject_name, ))
    ...

然后:

SchoolManagmentSystem.get_subject_by_name(name_to_find)

不建议将用户提供的输入直接插入到查询中,因为可能会发生 SQL 注入攻击: https://www.w3schools.com/sql/sql_injection.asp

您可能还会考虑将 SqlAlchemy 与它的 ORM 一起使用,具体取决于用例: https://docs.sqlalchemy.org/en/20/index.html