【问题标题】:Limit characters returned in oracle sql queryoracle sql查询中返回的限制字符
【发布时间】:2017-03-24 12:22:16
【问题描述】:

我需要将此字段限制为 4000 个字符。如何将其限制在列表 agg 上?谢谢。

LISTAGG(ORDER_IMPRESSION.IMPRESSION, ',') WITHIN GROUP (ORDER BY ORDER_IMPRESSION.LINE) 

【问题讨论】:

标签: sql oracle


【解决方案1】:

只需要一点努力。像这样的:

select listagg((case when running_len < 4000 then oi.impression end), ',') within group (order by oi.line)
from (select oi.*,
             sum(length(oi.impression) + 1) over (partition by ?? order by oi.line) as running_len
      from order_impression oi
     ) oi
group by ??;

这会计算运行长度,并且只聚合不超过长度的值。 ?? 是您用于聚合的任何内容。这确实假设line 是唯一的,因此order by 是稳定的。

这将不包括超过长度的impression - 之后什么都没有。它不会切断印象。这种逻辑是可能的,但它确实使查询复​​杂化。

【讨论】:

    【解决方案2】:

    您可以计算字符串长度的总和(使用SUM(...) OVER (...) 解析函数),然后使用它来将字符串截断为 4000 个字符:

    SELECT LISTAGG(
             CASE
               WHEN prev_len >= 4000 THEN NULL
               WHEN prev_len + len <= 4000 THEN value
               ELSE SUBSTR( value, 1, 4000 - prev_len )
             END
           ) WITHIN GROUP ( ORDER BY line ) AS value
    FROM   (
      SELECT impression,
             line,
             LENGTH( impression ) AS len,
             COALESCE(
               SUM( 1 + LENGTH( impression ) )
                 OVER ( ORDER BY line ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ),
               0
             ) AS prev_len
      FROM   order_impression
    );
    

    【讨论】:

      【解决方案3】:

      您可以编写自定义聚合函数将VARCHAR2s 聚合成CLOB

      CREATE OR REPLACE TYPE CLOBAggregation AS OBJECT(
        value CLOB,
      
        STATIC FUNCTION ODCIAggregateInitialize(
          ctx         IN OUT CLOBAggregation
        ) RETURN NUMBER,
      
        MEMBER FUNCTION ODCIAggregateIterate(
          self        IN OUT CLOBAggregation,
          value       IN     VARCHAR2
        ) RETURN NUMBER,
      
        MEMBER FUNCTION ODCIAggregateTerminate(
          self        IN OUT CLOBAggregation,
          returnValue    OUT CLOB,
          flags       IN     NUMBER
        ) RETURN NUMBER,
      
        MEMBER FUNCTION ODCIAggregateMerge(
          self        IN OUT CLOBAggregation,
          ctx         IN OUT CLOBAggregation
        ) RETURN NUMBER
      );
      /
      
      CREATE OR REPLACE TYPE BODY CLOBAggregation
      IS
        STATIC FUNCTION ODCIAggregateInitialize(
          ctx         IN OUT CLOBAggregation
        ) RETURN NUMBER
        IS
        BEGIN
          ctx := CLOBAggregation( NULL );
          RETURN ODCIConst.SUCCESS;
        END;
      
        MEMBER FUNCTION ODCIAggregateIterate(
          self        IN OUT CLOBAggregation,
          value       IN     VARCHAR2
        ) RETURN NUMBER
        IS
        BEGIN
          IF value IS NULL THEN
            NULL;
          ELSIF self.value IS NULL THEN
            self.value := value;
          ELSE
            self.value := self.value || ',' || value;
          END IF;
          RETURN ODCIConst.SUCCESS;
        END;
      
        MEMBER FUNCTION ODCIAggregateTerminate(
          self        IN OUT CLOBAggregation,
          returnValue    OUT CLOB,
          flags       IN     NUMBER
        ) RETURN NUMBER
        IS
        BEGIN
          returnValue := self.value;
          RETURN ODCIConst.SUCCESS;
        END;
      
        MEMBER FUNCTION ODCIAggregateMerge(
          self        IN OUT CLOBAggregation,
          ctx         IN OUT CLOBAggregation
        ) RETURN NUMBER
        IS
        BEGIN
          IF self.value IS NULL THEN
            self.value := ctx.value;
          ELSIF ctx.value IS NULL THEN
            NULL;
          ELSE
            self.value := self.value || ',' || ctx.value;
          END IF;
          RETURN ODCIConst.SUCCESS;
        END;
      END;
      /
      
      CREATE FUNCTION CLOBAgg( value VARCHAR2 )
      RETURN CLOB
      PARALLEL_ENABLE AGGREGATE USING CLOBAggregation;
      /
      

      那么你可以这样做:

      SELECT DBMS_LOB.SUBSTR( CLOBAGG( IMPRESSION ), 4000 )
      FROM   (
        SELECT   IMPRESSION
        FROM     ORDER_IMPRESSION
        ORDER BY line
      )
      

      【讨论】:

        【解决方案4】:

        如果您是 12.2 的早期采用者,则可以使用 ON OVERFLOW TRUNCATE 子句...

        ON OVERFLOW TRUNCATE

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-28
          • 2018-01-18
          • 1970-01-01
          • 1970-01-01
          • 2010-10-03
          相关资源
          最近更新 更多