Python-从字符串列表生成SQL WHERE / IN子句

问题描述 投票:0回答:1

我得到了一个任意长度的Python列表,其中包含任意字符串。特别是,它可以具有带有嵌入式单引号和/或双引号的字符串。我无法控制输入,因此我必须接受给出的信息。

例如:

    valueList = [ "hello'world", 'foo"bar', 'my\'name"is', "see\'you\"soon" ]

    Python shell:
        >>> valueList = [ "hello'world", 'foo"bar', 'my\'name"is', "see\'you\"soon" ]
        >>>
        >>> valueList
        ["hello'world", 'foo"bar', 'my\'name"is', 'see\'you"soon']
        >>>
        >>> valueList[0]
        "hello'world"
        >>>
        >>> valueList[1]
        'foo"bar'
        >>>
        >>> valueList[2]
        'my\'name"is'
        >>>
        >>> valueList[3]
        'see\'you"soon'

由此,我需要生成一个SQL字符串,例如:

    "SELECT * FROM myTable as mt
        WHERE mt."colName" IN ("hello'world", 'foo"bar', 'my\'name"is', 'see\'you"soon')

任何解决方案都必须与SQLite和Postgres一起使用。

我已经尝试使用Python join生成子句的(...)部分,但最终只是用一个大的字符串将所有单引号转义了。例如:

    Python shell:
        >>> values = "','".join(valueList)
        >>> values
        'hello\'world\',\'foo"bar\',\'my\'name"is\',\'see\'you"soon'

        >>> values = "'" + "','".join(valueList) + "'"
        >>> values
        '\'hello\'world\',\'foo"bar\',\'my\'name"is\',\'see\'you"soon\''

附加信息:我继承的代码使用SQLAlchemy和Pandas。

        import pandas as pd
        ...cut...cut...cut...
        my_df = pd.read_sql(sql, my_conn);

我不想使用Pandas进行过滤。实际上,我的任务是删除现有的Pandas过滤器,并使用带有显式WHERE / IN过滤器的SQL替换它以提高速度。

例如,替换为:

    my_df = pd.read_sql("SELECT * FROM myTable", my_conn) <==== can return 10's of thousands of rows
    my_df = my_df[my_df.loc[:, 'colName'].isin(myList)] <==== ends up with a handful of rows

带有此:

    my_df = pd.read_sql("SELECT * FROM myTable as mt WHERE mt."colName" IN ("hello'world", 'foo"bar', ...)", my_conn)

SQL注入保护是一个加号,但在这一点上,我将对任何可行的解决方案感到满意。

python sql join code-injection quotation-marks
1个回答
0
投票

嗯,基于SQL规范,该规范将字符串文字定义为用单引号分隔,并且要包含单引号,则必须将字符串文字加倍(可以参考SqlitePostgreSQL的语法规范以确保它们符合该规范)这是我的尝试:

value_list = [ "hello'world", 'foo"bar', """my'name"is""", """see'you"soon""" ]
value_list_escaped = [f"""'{x.replace("'", "''")}'""" for x in value_list]
query_template = "SELECT * FROM myTable as mt WHERE mt.colName IN ({})"
query = query_template.format(", ".join(value_list_escaped))
print(query)

这就是您想要的吗?

© www.soinside.com 2019 - 2024. All rights reserved.