使用字典将参数传递给python中的postgresql语句[重复]

jpfvwuh4  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(2)|浏览(104)

此问题在此处已有答案

Passing table name as a parameter in psycopg2(10个答案)
How can I do a line break (line continuation) in Python (split up a long line of source code)?(10个答案)
11天前关闭
我已经定义了一个字典,其中包含几个参数和它们的值,这些参数和值最终将用于构建SQL查询

query_params = collections.OrderedDict(
        {'table_name':'publilc.churn_data',
         'date_from':'201712',
         'date_to':'201805',
         'class_target':'NPA'
      })

字符串
这些参数将用于以下查询:

sql_data_sample = str("""select * from %s # get value of table_name
                                    where dt = %s    #get value of date_from
                                    and target in ('ACTIVE')

                        ----------------------------------------------------
                        union all
                        ----------------------------------------------------
                        (select * from %s #get value of table_name
                                 where dt = %s #get value of date_to
                                 and target in (%s));""") #get value of class_target
                                    %("'"+.join(str(list(query_params.values())[0])) + "'" + 
                                    "'"+.join(list(query_params.values())[1]) + "'" + 
                                    "'"+.join(list(query_params.values())[2]) + "'" +
                                    "'"+.join(list(query_params.values())[3]) + "'" )


然而,这给了我一个缩进错误,如下所示:

get_ipython().run_line_magic('("\'"+.join(list(query_params.values())[0])', '+ "\'"')
    ^
IndentationError: unexpected indent


查询最终应该看起来像这样:

select *from public.churn_data
        where dt = '201712'
        and target in ('ACTIVE')

----------------------------------------------------
union all
----------------------------------------------------
 (select * from public.churn_data 
            where dt = '201805'
            and target in ('NPA'));


我无法找出错误的来源。是因为table_name中的public.吗?有人能帮我解决这个问题吗?

holgip5t

holgip5t1#

请使用文档中描述的参数化查询
既然你已经有了一个dict,你可以这样做:

sql_data_sample = """select * from %(table_name)s
           where dt = %(date_from)s
           and target in ('ACTIVE')
           ----------------------------------------------------
           union all
           ----------------------------------------------------
           (select * from %(table_name)s
           where dt = %(date_to)s
           and target in (%(class_target)s));"""

cur.execute(sql_data_sample, query_params)

字符串
我还没有测试过if是否能和有序的dict一起工作,但我认为应该可以。如果不能,你可以在把有序的dict作为参数Map传递之前把它变成一个常规的dict。

EDIT除非你以后需要你的参数是一个OrderedDict,否则使用一个常规的Dict。据我所知,你只选择了一个OrderedDict来保留list(query_params.values())[0]的值顺序。
EDIT2表名和字段名不能使用绑定传递。Antoine Dusséaux在this answer中指出,自2.7版本以来,psycopg2提供了一种或多或少的安全方式来实现这一点。

from psycopg2 import sql

sql_data_sample = """select * from {0}
           where dt = %(date_from)s
           and target in ('ACTIVE')
           ----------------------------------------------------
           union all
           ----------------------------------------------------
           (select * from {0}
           where dt = %(date_to)s
           and target in (%(class_target)s));"""

cur.execute(sql.SQL(sql_data_sample)
                .format(sql.Identifier(query_params['table_name'])), 
            query_params)


你可能需要从你的dict中删除table_name,我不确定psycopg2对参数dict中的附加项的React,我现在不能测试它。
应该指出的是,这仍然会带来SQL注入的风险,除非绝对必要,否则应该避免。通常情况下,表和字段名称是查询字符串中相当固定的一部分。
下面是sql模块的相关文档。

h7appiyu

h7appiyu2#

您可以使用以下代码来删除缩进错误

sql_data_sample = str("""
select * from %s
where dt = %s
and target in ('ACTIVE')
----------------------------------------------------
union all
----------------------------------------------------
(select * from %s
where dt = %s
and target in (%s));""" %(
    "'" + str(list(query_params.values())[0]) + "'" +
    "'" + list(query_params.values())[1] + "'" +
    "'" + list(query_params.values())[2] + "'" +
    "'" + list(query_params.values())[3] + "'"
))

字符串
但是你需要再传递一个参数,因为你使用了%s 5次,但是参数只有4个

相关问题