【问题标题】:ORA-01795: maximum number of expressions in a list is 1000ORA-01795: 列表中的最大表达式数为 1000
【发布时间】:2011-07-12 08:24:08
【问题描述】:

在 c# 中,我们正在为 NHibernate 构建一个包含“in 语句”的查询。表达式的数量超过 5000。如果我执行查询,我会收到错误消息。

我需要找到一种打破大型字符串构建器并将它们存储在字符串构建器数组中的好方法,并在需要时执行多个查询以获得所需的输出。我们只有一个帐户的记录超过 5000 条,其余的都低于 100 条。有人可以提出解决此问题的方法吗?

【问题讨论】:

    标签: c# arrays stringbuilder


    【解决方案1】:

    您可以创建一个临时表,用 IN 列表中的项目填充它,然后加入它。

    【讨论】:

    • 不能创建存储过程或临时表。无法访问任何数据库。代码必须可以使用 nUnit 进行测试,并且需要有 CI。
    【解决方案2】:

    您可以将每个选择中的 1000 个 IN 合并在一起。性能不如创建临时表,但它适用于即席查询。

    SELECT A, B, C from BLAH WHERE A IS IN (
        0 - 999
    )
    
    UNION
    
    SELECT A, B, C from BLAH WHERE A IS IN (
        1000 - 1999
    )
    

    【讨论】:

    • 我会试试这个,让你知道结果如何。从这个角度来看,一个查询就足以获得所需的输出。
    【解决方案3】:

    当 where 子句中有这么多项目时,可能是时候考虑重构了。

    您可以创建一个接受逗号分隔值字符串的存储过程。然后,存储过程可以从该 csv 生成一个表,您可以与其他表进行内部连接以生成记录。

    查看此链接以了解如何创建一个接收 csv 并返回表的函数,以便您可以对其进行查询。

    how to convert csv to table in oracle 要么 How to best split csv strings in oracle 9i

    【讨论】:

      【解决方案4】:

      您可以使用此技巧将 IN 转换为 JOIN

      SELECT * FROM maintable
      JOIN (
          SELECT v1 a FROM DUAL UNION ALL
          SELECT v2 a FROM DUAL UNION ALL
          SELECT v3 a FROM DUAL UNION ALL
          ...
          SELECT v2000 a FROM DUAL) tmp
      
          on tmp.a = maintable.id
      

      此查询与

      相同
      SELECT * FROM maintable 
      WHERE id IN (v1, v2, v3, ...., v2000)
      

      我知道它会增加查询中的“文本量”,但不会影响性能,因为无论如何都使用临时结果集,而无需创建全局临时表。

      【讨论】:

        【解决方案5】:

        我使用的解决方案是将INOR 分开。

        where A in (a,b,c,d,e,f)
        

        变成

        where (A in (a,b,c) OR a in (d,e,f)) ...
        

        这很简单,对查询的格式没有特殊要求。

        在我看来,这比其他一些建议的解决方案更容易在您的字符串构建器(SQLQuerybuilder 或在您的情况下调用的任何东西)中实现。

        【讨论】:

          【解决方案6】:

          原来的帖子问题已经老了,但我最近多次遇到这个问题,并找到了可能对其他人有帮助的解决方案。而且,由于上述答案都没有给出 NHibernate 代码的答案,我也认为这与帖子有关。

          在我们的软件产品中,用户在用户界面中进行选择。然后前端将对应的 id 列表传递给后端进行数据查询和操作。

          首先,我需要一个函数来将元素列表拆分为 1000 个元素的分区。

          注意,这是 VB.NET,但函数本身在 C# 的 StackOverflow 上的其他地方找到:

          Public Shared Iterator Function Partition(Of T)(source As IList(Of T), Optional size As Int32 = 1000) As IEnumerable(Of List(Of T))
                  For i As Integer = 0 To CInt(Math.Ceiling(source.Count / CDbl(size)))
                      Yield New List(Of T)(source.Skip(size * i).Take(size))
                  Next
          End Function
          

          这个函数我用过好几种方式。一种方法是遍历列表分区以修改 QueryOver 以将所有部分结果合并,如下所示:

          Dim allPartitions As IEnumerable(Of List(Of Integer)) = Partition(idList, SplitSize)
                  Dim foundObjects As IEnumerable(Of MyEntity) = New List(Of MyEntity)
          
                  For Each part As List(Of Integer) In allPartitions
                      foundObjects = foundObjects.Union(
                          _session.QueryOver(Of MyEntity) _
                               WhereRestrictionOn(Function(x) x.ID).IsIn(part).Future())
                  Next
          

          我使用的另一种方法是创建一个限制,可以在 QueryOvers 中应用。以下函数创建了这样一个限制(ICriterion):

          Public Shared Function GetRestrictionOnIds(ids As List(Of Integer), propertyName As String) As ICriterion
          
                  Dim allParts As IEnumerable(Of List(Of Integer)) = Partition(ids, SplitSize)
          
                  Dim restriction As Disjunction = Restrictions.Disjunction()
                  For Each part As List(Of Integer) In allParts
                      restriction.Add(Restrictions.In(propertyName, part))
                  Next
          
                  Return Restrictions.Conjunction().Add(restriction)
          
              End Function
          

          我这样称呼那个函数:

          Dim wellIdRestriction As ICriterion = GetRestrictionOnIds(wellIdsList, "WellId") 
          Dim bleedOffs As IList(Of BleedOff) = _session.QueryOver(Of BleedOff)() _
                          .Where(wellIdRestriction) _
                          .Where(..... more restrictions...) _
                          .And(...yet more restrictions....) _
                          .List().GroupBy(...some function...) _
                          .ToDictionary(.. key-function, value-function...)
          

          【讨论】:

          • 我投了赞成票:从一个声誉低下的用户那里看到这么好的答案是相当不寻常的。尼尔斯干得好!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-28
          • 2018-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-20
          • 2013-07-24
          相关资源
          最近更新 更多