Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何使用select语句中的自定义函数作为游标来实现结果?_Sql_Oracle_Plsql - Fatal编程技术网

Sql 如何使用select语句中的自定义函数作为游标来实现结果?

Sql 如何使用select语句中的自定义函数作为游标来实现结果?,sql,oracle,plsql,Sql,Oracle,Plsql,我有以下游标: OPEN p_results FOR SELECT distinct S02.CONVERSATION_ID, S02.INTERNAL_USI, S02.PRN, S02.CRN, S01.EARLIEST_B_DATE "Bank Date", S01.EARLIEST_B_NARRATIVE||'DSEC' "BN", abs(S01.TOTAL_B_AMOUNT - S02.TOTAL_C_AMOUNT

我有以下游标:

OPEN p_results FOR
      SELECT distinct S02.CONVERSATION_ID, S02.INTERNAL_USI, S02.PRN,  S02.CRN, 
             S01.EARLIEST_B_DATE "Bank Date", S01.EARLIEST_B_NARRATIVE||'DSEC' "BN", 
             abs(S01.TOTAL_B_AMOUNT - S02.TOTAL_C_AMOUNT) "GA", 
             decode(S01.EXTRA_FLAG_4,1,'OP',2,'UP') "Batch Status", 
             (case 
                when S01.latest_b_date > S02.latest_c_date then S01.latest_b_date 
                else S02.latest_c_date 
              end ) Effective_Date, S02.ICC_ID,  
             S02.MATCH_METHOD,
             S01.TOTAL_B_AMOUNT                     
      FROM TTPAY S01,   
           TTCONT S02    
      Where S01.EXTRA_FLAG_4 in (1,2) 
      and   S02.EXTRA_FLAG_4 in (1,2) 
      and   S01.Match_no = 0 
      and   S02.Match_no = 0 
      and S01.PRN = S02.PRN;
对于这段代码,我必须做出更改,如果下面结果中的生效日期是假日或是周末,那么我需要添加+1,对于周六+2,否则我将使用结果,因为它在下面的代码中返回为生效日期

(case 
        when S01.latest_b_date > S02.latest_c_date then S01.latest_b_date 
        else S02.latest_c_date 
      end ) Effective_Date
我有一个名为WORKING_DAY的函数,它将一个日期作为参数,并在检查假日日历和周末后返回布尔值TRUE或FALSE

如何在上述代码段中有效地使用该函数来获取所需的日期

我有一个名为WORKING_DAY的函数,它将一个日期作为参数,并在检查假日日历和周末后返回布尔值TRUE或FALSE

如何在上述代码段中有效地使用该函数来获取所需的日期

不能在SQL语句中使用它,因为BOOLEAN是,并且在中不存在

如果您想在SQL中返回一个真实值,则返回一个文本,即0/1或“Y”/“N”等,并在需要时进行比较

因此,您的函数应该从只返回布尔PL/SQL数据类型更改为:

创建函数是工作日 日期中的dt 返回号码 是 工作日是否为布尔值; 开始 -做事。 如果你每天都在工作 返回1; 其他的 返回0; 如果结束; 终止 / 更新

更改函数后,如何在代码段中使用该函数来获取所需的生效日期

您不能使用该函数来确定需要添加多少天。该函数返回一个truthy值,因此,除非您要在连续的每一天进行迭代,并测试这是否是一个工作日,而这在SQL中很难做到,否则当前返回truthy值的方法将不起作用

相反,将逻辑移到一个函数中,该函数告诉您要添加多少天:

CREATE FUNCTION days_until_next_working_day(
  dt IN DATE
) RETURN INTEGER
IS
  current_day DATE := dt;
BEGIN
  WHILE NOT is_working_day( current_day ) LOOP
    current_day := current_day + INTERVAL '1' DAY;
  END LOOP;
  RETURN current_day - dt;
END;
/
可能有一种更有效的方法来编写此文件以计算下一个工作日,而不是在连续的每一天迭代,但我们不知道您是如何确定假期等,因此我们无法对其进行优化

然后,只需将返回值添加到SQL查询中,就可以跳过那么多天

我有一个名为WORKING_DAY的函数,它将一个日期作为参数,并在检查假日日历和周末后返回布尔值TRUE或FALSE

如何在上述代码段中有效地使用该函数来获取所需的日期

不能在SQL语句中使用它,因为BOOLEAN是,并且在中不存在

如果您想在SQL中返回一个真实值,则返回一个文本,即0/1或“Y”/“N”等,并在需要时进行比较

因此,您的函数应该从只返回布尔PL/SQL数据类型更改为:

创建函数是工作日 日期中的dt 返回号码 是 工作日是否为布尔值; 开始 -做事。 如果你每天都在工作 返回1; 其他的 返回0; 如果结束; 终止 / 更新

更改函数后,如何在代码段中使用该函数来获取所需的生效日期

您不能使用该函数来确定需要添加多少天。该函数返回一个truthy值,因此,除非您要在连续的每一天进行迭代,并测试这是否是一个工作日,而这在SQL中很难做到,否则当前返回truthy值的方法将不起作用

相反,将逻辑移到一个函数中,该函数告诉您要添加多少天:

CREATE FUNCTION days_until_next_working_day(
  dt IN DATE
) RETURN INTEGER
IS
  current_day DATE := dt;
BEGIN
  WHILE NOT is_working_day( current_day ) LOOP
    current_day := current_day + INTERVAL '1' DAY;
  END LOOP;
  RETURN current_day - dt;
END;
/
可能有一种更有效的方法来编写此文件以计算下一个工作日,而不是在连续的每一天迭代,但我们不知道您是如何确定假期等,因此我们无法对其进行优化


然后,只需将返回值添加到SQL查询中,就可以跳过那么多天。

在这种情况下,您拥有的函数几乎是无用的。你必须知道生效日期是否为

星期六或 星期日或 假日还是 这些都不是 因此,如果它返回TRUE或FALSE,则您不能对其执行任何操作。您需要一个新函数,它将返回VARCHAR2,例如sun或sat或hol或null,表示一个工作日。然后您可以在编写的查询中使用它。怎样一种简单的方法是将其用作内联视图,而不必接触已有的代码:

   OPEN p_results FOR
      SELECT conversation_id,
             CASE                                                 --> this is where you decide
                WHEN working_day_vc (effective_date) = 'sat'      --> whether day is SAT/SUN/HOLIDAY
                THEN
                   effective_date + 2
                WHEN working_day_vc (effective_date) IN ('sun', 'hol')
                THEN
                   effective_date + 1
                ELSE
                   effective_date
             END
                effective_date
        FROM (
              -- this is your current query
              SELECT DISTINCT
                     S02.CONVERSATION_ID,
                     S02.INTERNAL_USI,
                     S02.PRN,
                     S02.CRN,
                     S01.EARLIEST_B_DATE "Bank Date",
                     S01.EARLIEST_B_NARRATIVE || 'DSEC' "BN",
                     ABS (S01.TOTAL_B_AMOUNT - S02.TOTAL_C_AMOUNT) "GA",
                     DECODE (S01.EXTRA_FLAG_4,  1, 'OP',  2, 'UP')
                        "Batch Status",
                     (CASE
                         WHEN S01.latest_b_date > S02.latest_c_date
                         THEN
                            S01.latest_b_date
                         ELSE
                            S02.latest_c_date
                      END)
                        Effective_Date,
                     S02.ICC_ID,
                     S02.MATCH_METHOD,
                     S01.TOTAL_B_AMOUNT
                FROM TTPAY S01, TTCONT S02
               WHERE     S01.EXTRA_FLAG_4 IN (1, 2)
                     AND S02.EXTRA_FLAG_4 IN (1, 2)
                     AND S01.Match_no = 0
                     AND S02.Match_no = 0
                     AND S01.PRN = S02.PRN);

在这种情况下,您拥有的函数几乎是无用的。你必须知道生效日期是否为

星期六或 星期日或 假日还是 这些都不是 因此,如果它返回TRUE或FALSE,则您不能对其执行任何操作。您需要一个新函数,它将返回VARCHAR2,例如sun或sat或hol或null,表示一个工作日。然后您可以在编写的查询中使用它。怎样一种简单的方法是将其用作内联视图,而不必接触已有的代码:

   OPEN p_results FOR
      SELECT conversation_id,
             CASE                                                 --> this is where you decide
                WHEN working_day_vc (effective_date) = 'sat'      --> whether day is SAT/SUN/HOLIDAY
                THEN
                   effective_date + 2
                WHEN working_day_vc (effective_date) IN ('sun', 'hol')
                THEN
                   effective_date + 1
                ELSE
                   effective_date
             END
                effective_date
        FROM (
              -- this is your current query
              SELECT DISTINCT
                     S02.CONVERSATION_ID,
                     S02.INTERNAL_USI,
                     S02.PRN,
                     S02.CRN,
                     S01.EARLIEST_B_DATE "Bank Date",
                     S01.EARLIEST_B_NARRATIVE || 'DSEC' "BN",
                     ABS (S01.TOTAL_B_AMOUNT - S02.TOTAL_C_AMOUNT) "GA",
                     DECODE (S01.EXTRA_FLAG_4,  1, 'OP',  2, 'UP')
                        "Batch Status",
                     (CASE
                         WHEN S01.latest_b_date > S02.latest_c_date
                         THEN
                            S01.latest_b_date
                         ELSE
                            S02.latest_c_date
                      END)
                        Effective_Date,
                     S02.ICC_ID,
                     S02.MATCH_METHOD,
                     S01.TOTAL_B_AMOUNT
                FROM TTPAY S01, TTCONT S02
               WHERE     S01.EXTRA_FLAG_4 IN (1, 2)
                     AND S02.EXTRA_FLAG_4 IN (1, 2)
                     AND S01.Match_no = 0
                     AND S02.Match_no = 0
                     AND S01.PRN = S02.PRN);

如果这是某种报告,并且是在sql中执行的。比如说

with
  function wf_WORKING_DAY(p_Date date) return number is
  begin
    return case when WORKING_DAY(p_Date) then 1 else 0 end;
  end;
select wf_WORKING_DAY(date'2020-01-01')
  from dual
/

如果这是某种报告,并且是在sql中执行的。比如说

with
  function wf_WORKING_DAY(p_Date date) return number is
  begin
    return case when WORKING_DAY(p_Date) then 1 else 0 end;
  end;
select wf_WORKING_DAY(date'2020-01-01')
  from dual
/

非常感谢@MT0在这方面的帮助

我 死记硬背以下内容以减轻要求

CREATE OR REPLACE PACKAGE ACTUAL_DATE
IS
    FUNCTION IS_WORKING_DAY (IN_DATE IN DATE) RETURN BOOLEAN; 
    FUNCTION DAYS_UNTIL_NEXT_WORKING_DAY(IN_DATE IN DATE) RETURN NUMBER;
    FUNCTION GET_NEXT_BUSINESS_DAY(IN_DATE IN DATE) RETURN DATE;
END ACTUAL_DATE;
/
CREATE OR REPLACE PACKAGE BODY ACTUAL_DATE
IS
FUNCTION IS_WORKING_DAY (IN_DATE DATE) RETURN BOOLEAN
  IS
   HOLIDAYCOUNTER NUMBER :=0;
   DAYNUM POSITIVE;
  BEGIN
    -- CHECK DATE AGAINST NTBS_HOLIDAYS TABLE
    HOLIDAYCOUNTER :=0;
    SELECT COUNT(*) INTO HOLIDAYCOUNTER
    FROM HOLIDAY_CALENDAR
    WHERE HOLIDAY_DATE = TO_DATE(IN_DATE);  
    
    -- DETERMINE IF A WEEKDAY
    DAYNUM := TO_CHAR( IN_DATE, 'd');

    -- RETURN TRUE (1) ONLY IF A WEEKDAY AND NOT A NSW PPUBLIC HOLIDAY
    IF DAYNUM BETWEEN 2 AND 6 AND HOLIDAYCOUNTER = 0 THEN 
       RETURN TRUE;
    ELSE
       RETURN FALSE;
    END IF;
END IS_WORKING_DAY;

-- DETERMINE NO. OF DAYS TO ACHIEVE NEXT WORK DAY FOR GIVEN DATE
FUNCTION DAYS_UNTIL_NEXT_WORKING_DAY(
  IN_DATE IN DATE
) RETURN NUMBER
IS
  CURRENT_DAY DATE := IN_DATE;
  NUMBERS_OF_DAY NUMBER;
BEGIN
  WHILE NOT IS_WORKING_DAY( CURRENT_DAY ) LOOP
    CURRENT_DAY := CURRENT_DAY + INTERVAL '1' DAY;
  END LOOP;
  NUMBERS_OF_DAY := CURRENT_DAY - IN_DATE;
  RETURN NUMBERS_OF_DAY;
END;

-- ADD NO.OF DAYS TO GIVEN DATE TO GET ACTUAL EFFECTIVE DATE
FUNCTION GET_NEXT_BUSINESS_DAY(IN_DATE IN DATE) RETURN DATE
    IS
        BUSINESSDAY DATE := IN_DATE;
        ACTUAL_BUSINESSDAY DATE;
    BEGIN
        IF (IN_DATE IS NULL)
        THEN
            RAISE_APPLICATION_ERROR
            (
                -20999,
                'null date passed to get_next_business_day'
            );
        END IF;

        ACTUAL_BUSINESSDAY := BUSINESSDAY + DAYS_UNTIL_NEXT_WORKING_DAY(IN_DATE);
            
        RETURN ACTUAL_BUSINESSDAY;
    END;
END ACTUAL_DATE;
/

非常感谢@MT0在这方面的帮助

我写了下面的内容来减轻这个要求

CREATE OR REPLACE PACKAGE ACTUAL_DATE
IS
    FUNCTION IS_WORKING_DAY (IN_DATE IN DATE) RETURN BOOLEAN; 
    FUNCTION DAYS_UNTIL_NEXT_WORKING_DAY(IN_DATE IN DATE) RETURN NUMBER;
    FUNCTION GET_NEXT_BUSINESS_DAY(IN_DATE IN DATE) RETURN DATE;
END ACTUAL_DATE;
/
CREATE OR REPLACE PACKAGE BODY ACTUAL_DATE
IS
FUNCTION IS_WORKING_DAY (IN_DATE DATE) RETURN BOOLEAN
  IS
   HOLIDAYCOUNTER NUMBER :=0;
   DAYNUM POSITIVE;
  BEGIN
    -- CHECK DATE AGAINST NTBS_HOLIDAYS TABLE
    HOLIDAYCOUNTER :=0;
    SELECT COUNT(*) INTO HOLIDAYCOUNTER
    FROM HOLIDAY_CALENDAR
    WHERE HOLIDAY_DATE = TO_DATE(IN_DATE);  
    
    -- DETERMINE IF A WEEKDAY
    DAYNUM := TO_CHAR( IN_DATE, 'd');

    -- RETURN TRUE (1) ONLY IF A WEEKDAY AND NOT A NSW PPUBLIC HOLIDAY
    IF DAYNUM BETWEEN 2 AND 6 AND HOLIDAYCOUNTER = 0 THEN 
       RETURN TRUE;
    ELSE
       RETURN FALSE;
    END IF;
END IS_WORKING_DAY;

-- DETERMINE NO. OF DAYS TO ACHIEVE NEXT WORK DAY FOR GIVEN DATE
FUNCTION DAYS_UNTIL_NEXT_WORKING_DAY(
  IN_DATE IN DATE
) RETURN NUMBER
IS
  CURRENT_DAY DATE := IN_DATE;
  NUMBERS_OF_DAY NUMBER;
BEGIN
  WHILE NOT IS_WORKING_DAY( CURRENT_DAY ) LOOP
    CURRENT_DAY := CURRENT_DAY + INTERVAL '1' DAY;
  END LOOP;
  NUMBERS_OF_DAY := CURRENT_DAY - IN_DATE;
  RETURN NUMBERS_OF_DAY;
END;

-- ADD NO.OF DAYS TO GIVEN DATE TO GET ACTUAL EFFECTIVE DATE
FUNCTION GET_NEXT_BUSINESS_DAY(IN_DATE IN DATE) RETURN DATE
    IS
        BUSINESSDAY DATE := IN_DATE;
        ACTUAL_BUSINESSDAY DATE;
    BEGIN
        IF (IN_DATE IS NULL)
        THEN
            RAISE_APPLICATION_ERROR
            (
                -20999,
                'null date passed to get_next_business_day'
            );
        END IF;

        ACTUAL_BUSINESSDAY := BUSINESSDAY + DAYS_UNTIL_NEXT_WORKING_DAY(IN_DATE);
            
        RETURN ACTUAL_BUSINESSDAY;
    END;
END ACTUAL_DATE;
/

通过简化假设,您可以将此过程简化为单个查询。假设您可以定义最大连续关闭天数。假设给定一个业务日期,您将生成一个可能的下一个业务日期列表,然后从该列表中选择并返回假期表中未包含的最小日期。我已选择14天作为最长连续关闭天数。虽然查询本身并不过于复杂,也不过于简单,但我会将其隐藏在函数中。看

变成

next_business_day(S01.latest_b_date) Effective_Date, 

注意:刚刚注意到这实际上是一篇旧文章,但我最初看到的只是昨天。所以我想我就不谈了。

通过简化假设,您可以将此过程简化为单个查询。假设您可以定义最大连续关闭天数。假设给定一个业务日期,您将生成一个可能的下一个业务日期列表,然后从该列表中选择并返回假期表中未包含的最小日期。我已选择14天作为最长连续关闭天数。虽然查询本身并不过于复杂,也不过于简单,但我会将其隐藏在函数中。看

变成

next_business_day(S01.latest_b_date) Effective_Date, 

注意:刚刚注意到这实际上是一篇旧文章,但我最初看到的只是昨天。所以我想我就不谈了。

今天的提示:始终使用现代的显式连接语法。更容易编写而不出错,更容易阅读和维护,如果需要,更容易转换为外部联接!今天的提示:始终使用现代的显式连接语法。更容易编写而不出错,更容易阅读和维护,如果需要,更容易转换为外部联接!谢谢,但是在更改函数之后,我如何在代码片段中使用该函数来获得所需的生效日期?@BikashKumarBehera我不会,因为您不知道需要添加多少天。我没有返回真实值,而是将函数重命名为number of_days_until_next_working_day,如果是工作日,则返回0,否则从函数返回直到next是工作日的天数。另一种方法是将查询重写为PL/SQL。我认为这是更好的方法-你永远不知道谁/什么在使用is_working_day函数。只需在“开始-结束”中关闭查询;差不多了……我有一个查找表HOLIDAY_CALENDAR,其中存储了2020年的假期日期列表。因此,现在的问题是,在包含此函数以获取生效日期之后,代码应该是什么样子。@MT0,我尝试编译给定代码,直到下一个工作日函数它给出异常[Error]PLS-00306 7:9:PLS-00306:调用“NOT”和[Error]时参数的数量或类型错误PLS-00382 10:10:PLS-00382:表达式类型错误。此外,我想返回日期为天的函数,直到下一个工作日。你能在同样的方面帮助我吗?谢谢,但是在更改函数后,我如何在代码片段中使用该函数来获得所需的生效日期?@BikashKumarBehera我不会,因为你不知道需要添加多少天。我没有返回真实值,而是将函数重命名为number of_days_until_next_working_day,如果是工作日,则返回0,否则从函数返回直到next是工作日的天数。另一种方法是将查询重写为PL/SQL。我认为这是更好的方法-你永远不知道谁/什么在使用is_working_day函数。只需在“开始-结束”中关闭查询;差不多了……我有一个查找表HOLIDAY_CALENDAR,其中存储了2020年的假期日期列表。因此,现在的问题是,在包含此函数以获取生效日期之后,代码应该是什么样子。@MT0,我尝试编译给定代码,直到下一个工作日函数它给出异常[Error]PLS-00306 7:9:PLS-00306:调用“NOT”和[Error]时参数的数量或类型错误PLS-00382 10:10:PLS-00382:表达式类型错误。此外,我想返回日期为天的函数,直到下一个工作日。你能帮我做同样的事吗?