【问题标题】:How do I escape multiple query params for an IN() clause?如何为 IN() 子句转义多个查询参数?
【发布时间】:2015-11-17 08:17:23
【问题描述】:

我正在尝试使用 IN() 子句执行 SELECT 查询,并让 sqlalchemy 执行 参数为我转义。我使用 pyodbc 作为我的数据库连接器。

这是我目前写的代码:

tables = ['table1', 'table2', ... ]
sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN(:tables)"
result = session.execute(sql, {"tables": tables})

不幸的是,这失败并出现错误:

sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('Invalid parameter type.  param-index=0 param-type=list', 'HY105')

有什么方法可以让 sqlalchemy 转义整个参数列表并将它们与, 连接起来 无需为列表的每个项目手动添加 :tableX 占位符?

【问题讨论】:

    标签: python sql-server python-2.7 sqlalchemy


    【解决方案1】:

    试试这样的......

    DECLARE @string Varchar(100) = 'Table1,table2,table3'
    
      declare @xml xml
      set @xml = N'<root><r>' + replace(@string,',','</r><r>') + '</r></root>'
    
    
    SELECT * FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_NAME IN(  select
                         r.value('.','varchar(max)') as item
                        from @xml.nodes('//root/r') as records(r)
                        )
    

    【讨论】:

      【解决方案2】:

      出于充分的理由,无法按照您的意愿扩展参数列表。

      如果你真的想创建一个raw SQL query,那么你可以枚举你的列表并动态创建查询:

      vals = {"param{}".format(i): table for i, table in enumerate(tables)}
      keys = ", ".join([":{}".format(k) for k in vals])
      sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ({keys})".format(keys=keys)
      result = session.execute(sql, vals)
      
      for tbl in result:
          print(tbl)
      

      但您可以要求sqlalchemy 为您执行此操作。这里我们对INFORMATION_SCHEMA.tables 视图进行fake 映射,并使用sqlalchemy 工具集对其进行查询:

      # definition (done just once)
      class ISTable(Base):
          __tablename__ = 'tables'
          __table_args__ = {'schema': 'INFORMATION_SCHEMA'}
          _fake_id = Column(Integer, primary_key=True)
          table_catalog = Column(String)
          table_schema = Column(String)
          table_name = Column(String)
          table_type = Column(String)
      
      # actual usage
      result = session.query(
          ISTable.table_catalog, ISTable.table_schema,
          ISTable.table_name, ISTable.table_type,
      ).filter(
          ISTable.table_name.in_(tables))
      
      for tbl in result:
          print(tbl)
      

      一个问题:您不能查询整个映射类(例如query(ISTable)),因为primary_key 不存在并且会引发异常。但是只查询我们可以查询的列(如上所示)就足够了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 2019-08-23
        • 1970-01-01
        • 2018-06-18
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多