Python cx_oracle 将变量与项目列表绑定

Posted

技术标签:

【中文标题】Python cx_oracle 将变量与项目列表绑定【英文标题】:Python cx_oracle bind variable with a list of items 【发布时间】:2018-08-03 11:27:49 【问题描述】:

我有一个这样的查询:

SELECT prodId, prod_name , prod_type FROM mytable WHERE prod_type in (:list_prod_names)

我想获取一个产品的信息,根据可能的类型有:"day", "week", "weekend", "month"。根据日期的不同,它可能至少是这些选项中的一个,或者是所有选项的组合。

此信息(列表类型)由函数prod_names(date_search)返回

我正在使用 cx_oracle 绑定,代码如下:

def get_prod_by_type(search_date :datetime):

  query_path = r'./queries/prod_by_name.sql'
  raw_query = open(query_path).read().strip().replace('\n', ' ').replace('\t', ' ').replace('  ', ' ')

  print(sql_read_op)
  # Depending on the date the product types may be different
  prod_names(search_date)  #This returns a list with possible names
  qry_params = "list_prod_names": prod_names # See attempts bellow
  try:
      db = DB(username='username', password='pss', hostname="localhost")
      df = db.get(raw_query,qry_params)
  except Exception:
      exception_error = traceback.format_exc()
      exception_error = 'Exception on DB.get_short_cov_op2() : %s\n%s' % exception_error
      print(exception_error)
  return df

为此:qry_params = "list_prod_names": prod_names 我尝试了多种不同的方法,例如:

prod_names = ''.join(prod_names) 
prod_names = str(prod_names)
prod_names =." \'"+''.join(prod_names)+"\'"

我设法让它工作的唯一一件事就是这样做:

new_query = raw_query.format(list_prod_names=prodnames_for_date(search_date)).replace('[', '').replace(']','')

df = db.query(new_query)

我试图不使用.format(),因为对 sql 执行 .format 以防止攻击是不好的做法。

db.py 包含其他功能:

def get(self, sql, params=):
cur = self.con.cursor()
            cur.prepare(sql)
            try:
                cur.execute(sql, **params)
                df = pd.DataFrame(cur.fetchall(), columns=[c[0] for c in cur.description])
            except Exception:
                exception_error = traceback.format_exc()
                exception_error = 'Exception on DB.get() : %s\n%s' % exception_error
                print(exception_error)
                self.con.rollback()
            cur.close()
            df.columns = df.columns.map(lambda x: x.upper())
         return df

我希望能够进行类型绑定。

我正在使用:

python = 3.6 cx_oracle = 6.3.1

我已经阅读了以下文章,但我仍然无法找到解决方案:

Python cx_Oracle bind variables Python cx_Oracle SQL with bind string variable Search for name in cx_Oracle

【问题讨论】:

【参考方案1】:

不幸的是,除非将数组转换为 SQL 类型并使用子查询,否则无法直接绑定数组——这相当复杂。所以你需要做这样的事情:

inClauseParts = []
for i, inValue in enumerate(ARRAY_VALUE):
    argName = "arg_" + str(i + 1)
    inClauseParts.append(":" + argName)
clause = "%s in (%s)" % (columnName, ",".join(inClauseParts))

这很好用,但请注意,如果数组中的元素数量经常变化,使用此技术将创建一个单独的语句,必须针对每个元素数量进行解析。如果您知道(通常)数组中的元素不会超过(例如)10 个,那么最好将 None 附加到传入数组中,以便元素的数量始终为 10。

希望这已经足够清楚了!

【讨论】:

【参考方案2】:

我终于做到了。它可能不漂亮,但它有效。

我已经修改了我的 sql 查询以包含一个额外的选择,它返回我的描述符列表的值:

inner join (
   SELECT regexp_substr(:my_list_of_items, '[^,]+', 1, LEVEL) as mylist
   FROM dual
   CONNECT BY LEVEL <= length(:my_list_of_items) - length(REPLACE(:my_list_of_items, ',', '')) + 1
) d
on d.mylist= a.corresponding_columns

【讨论】:

以上是关于Python cx_oracle 将变量与项目列表绑定的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中使用 cx_Oracle 和 xlrd 列出列表的 executemany() 正在返回 TypeError

如何使用 cx_Oracle 在 Python 中返回 SQLPLUS 变量

Cx_oracle:在 python 中使用变量的 To_date

在windows下安装cx_Oracle问题

windows环境 python 与 cx_oracle 连接 记录

Python应用实战系列-如何通过Python来操作Oracle数据库:cx_Oracle