带游标的plsql函数

时间:2015-04-15 09:05:40

标签: plsql oracle11g

我正在编写一个plsql函数,在这个函数中我要添加一个游标。 cursor取决于其中一个表的值。 如果我在光标前写任何东西它给我错误。 怎么写。 以下是我的示例代码。

CREATE OR REPLACE FUNCTION F_ResolveValueExpression(inRowId NUMBER)
  RETURN VARCHAR2 IS
      isRangeValue     PLS_INTEGER;
      ExpressionValue  VARCHAR2(100);
      FinalRangeValue  VARCHAR2(100);
      g_ExchangeType   VARCHAR2(100) := 'BSE';
      g_TradeMode      VARCHAR2(100) := 'SQUP';
      rangeTypeNrageField        VARCHAR2(10);


      SELECT RANGE_TYPE || ' ' || Range_field
        INTO rangeTypeNrageField
        FROM Range_Header
       WHERE RANGE_ID = inRowId;


      CASE rangeTypeNrageField
        WHEN 'RL EXCHANGE' THEN
            CURSOR c_RangeValueDetails IS
            SELECT R.LOV_VALUE LOV_VALUE,
                   R.RANGE_VAL_TYPE RANGE_VAL_TYPE,
                   R.RANGE_VALUE RANGE_VALUE
              FROM Range_Value_Details R
             WHERE R.RANGE_ID = inRowId
                   AND R.LOV_VALUE = g_ExchangeType;


        WHEN 'RL TRDMODE' THEN
            CURSOR c_RangeValueDetails IS
            SELECT R.LOV_VALUE LOV_VALUE,
                   R.RANGE_VAL_TYPE RANGE_VAL_TYPE,
                   R.RANGE_VALUE RANGE_VALUE
              FROM Range_Value_Details R
             WHERE R.RANGE_ID = inRowId
                   AND R.LOV_VALUE = g_TradeMode;
      END CASE;

        BEGIN

          FOR i IN c_RangeValueDetails 
            LOOP
              IF i.RANGE_VAL_TYPE = 'R' THEN
                  ExpressionValue := F_ResolveValueExpression(i.RANGE_VALUE);
              ELSE
                  ExpressionValue := i.RANGE_VALUE;
              END IF;
            End Loop;

        RETURN FinalRangeValue;
        END;

如果我在光标工作之前提交select语句。 我的案例陈述取决于我的选择。 如何实现这一目标。 请帮忙。

1 个答案:

答案 0 :(得分:0)

您不能在select之前拥有casebegin;它们不属于声明部分。您可以在自己的子块中定义每个游标,但是您也必须在每个子块中重复循环代码。

您可以执行连接以决定要检查的列,而不是定义两个游标。像这样(未经测试):

CREATE OR REPLACE FUNCTION F_ResolveValueExpression(inRowId NUMBER)
  RETURN VARCHAR2 IS
      isRangeValue     PLS_INTEGER;
      ExpressionValue  VARCHAR2(100);
      FinalRangeValue  VARCHAR2(100);
      g_ExchangeType   VARCHAR2(100) := 'BSE';
      g_TradeMode      VARCHAR2(100) := 'SQUP';

      CURSOR c_RangeValueDetails IS
        SELECT R.LOV_VALUE LOV_VALUE,
               R.RANGE_VAL_TYPE RANGE_VAL_TYPE,
               R.RANGE_VALUE RANGE_VALUE
          FROM Range_Header H
          JOIN Range_Value_Details R
            ON R.RANGE_ID = H.RANGE_ID
           AND ((H.RANGE_TYPE = 'RL' AND H.Range_field = 'EXCHANGE' 
                 AND R.LOV_VALUE = g_ExchangeType)
            OR (H.RANGE_TYPE = 'RL' AND H.Range_field = 'TRDMODE'
                 AND R.LOV_VALUE = g_TradeMode))
         WHERE H.RANGE_ID = inRowId;

BEGIN
  FOR i IN c_RangeValueDetails
...

或者如果您愿意,因为除了过滤器值之外,您的两个原始游标是相同的,您可以(按照建议)单独执行选择,然后将该值传递给参数化游标:

CREATE OR REPLACE FUNCTION F_ResolveValueExpression(inRowId NUMBER)
  RETURN VARCHAR2 IS
      isRangeValue     PLS_INTEGER;
      ExpressionValue  VARCHAR2(100);
      FinalRangeValue  VARCHAR2(100);
      g_ExchangeType   VARCHAR2(100) := 'BSE';
      g_TradeMode      VARCHAR2(100) := 'SQUP';
      rangeTypeNrageField        VARCHAR2(10);

      CURSOR c_RangeValueDetails (c_rangeTypeNrageField varchar2) IS
        SELECT R.LOV_VALUE LOV_VALUE,
               R.RANGE_VAL_TYPE RANGE_VAL_TYPE,
               R.RANGE_VALUE RANGE_VALUE
          FROM Range_Value_Details R
         WHERE R.RANGE_ID = inRowId
           AND R.LOV_VALUE = CASE c_rangeTypeNrageField
                 WHEN 'RL EXCHANGE' THEN g_ExchangeType
                 WHEN 'RL TRDMODE' THEN g_TradeMode END;
BEGIN
    SELECT RANGE_TYPE || ' ' || Range_field
      INTO rangeTypeNrageField
      FROM Range_Header
     WHERE RANGE_ID = inRowId;

     FOR i IN c_RangeValueDetails (rangeTypeNrageField)
...

或者先用以下方法评估案例陈述:

...
      CURSOR c_RangeValueDetails (c_lov_value varchar2) IS
        SELECT R.LOV_VALUE LOV_VALUE,
               R.RANGE_VAL_TYPE RANGE_VAL_TYPE,
               R.RANGE_VALUE RANGE_VALUE
          FROM Range_Value_Details R
         WHERE R.RANGE_ID = inRowId
           AND R.LOV_VALUE = c_lov_value;
BEGIN
    SELECT RANGE_TYPE || ' ' || Range_field
      INTO rangeTypeNrageField
      FROM Range_Header
     WHERE RANGE_ID = inRowId;

     FOR i IN c_RangeValueDetails (CASE rangeTypeNrageField
                 WHEN 'RL EXCHANGE' THEN g_ExchangeType
                 WHEN 'RL TRDMODE' THEN g_TradeMode END)
...

您可以使用隐式游标进行循环而不是显式(在声明部分中)游标; see the documentation了解差异。