【问题标题】:Oracle 11g - FOR loop that inserts only weekdays into a table?Oracle 11g - 仅将工作日插入表的 FOR 循环?
【发布时间】:2011-09-29 01:44:23
【问题描述】:

我想将一些数据插入到与下一年的日期相关联的表中。我实际上只需要插入工作日。

 BEGIN
  FOR i IN 1..365 LOOP
  INSERT INTO MY_TABLE (ID, MY_DATE)
  VALUES (i, (to_date(sysdate,'DD-MON-YY')-1)+i);
  END LOOP;
 END;

我可以通过返回并删除周末的行来解决我的问题,但这似乎相当不雅 - 任何人都可以想出一种方法来修改我的循环以使其跳过周末吗?

【问题讨论】:

    标签: sql oracle date for-loop oracle11g


    【解决方案1】:

    您始终可以在插入行之前检查星期几(星期几的名称取决于您的 NLS 设置,因此这不是最可靠的解决方案)

     BEGIN
      FOR i IN 1..365 LOOP
        IF( to_char(sysdate-1+i,'fmDAY') NOT IN ('SATURDAY', 'SUNDAY') )
        THEN
          INSERT INTO MY_TABLE (ID, MY_DATE)
            VALUES (i, (to_date(sysdate,'DD-MON-YY')-1)+i);
        END IF;
      END LOOP;
     END;
    

    【讨论】:

    • 我们可以改用'D' 格式掩码。星期几仍然取决于 NLS_TERRITORY(星期日在美国是 1,在英国是 7),但比日期名称的可变性要小。
    • @APC - 非常正确。但是,一旦您将 NLS 设置加入其中,问题就会变得更加棘手。我很难知道我们美国人宣布一周的开始日期是哪一天,更不用说弄清楚你们英国人的决定了。
    • to_char(SYSDATE, 'fmDAY', 'nls_date_language=''AMERICAN''') 将返回正确的输出无论 NLS 会话设置如何
    【解决方案2】:

    如果你让 Monday = 0 和 Sunday = 6 你可以使用 (if mod(i,7)

    【讨论】:

    • 这如何应用于 oracle?
    【解决方案3】:

    您可以使用以下日期格式之一来检查它是哪一天。

    select to_char(sysdate,'DAY') from dual; /* 星期二 */
    从对偶中选择 to_char(sysdate,'D'); /* 3 */
    从对偶中选择 to_char(sysdate,'DY'); /* 周二 */

    添加如下所示的 if 语句以删除等于 SAT 或 SUN 的日期。

    BEGIN
      FOR i IN 1..365 LOOP
      IF to_char(sysdate-1+i,'DY') NOT in ('SAT','SUN') THEN
    
       INSERT INTO MY_TABLE (ID, MY_DATE) VALUES (i, (to_date(sysdate,'DD-MON-YY')-1)+i);
      END IF;
     END LOOP;
    END;
    

    【讨论】:

    • “D”值取决于 NLS 设置(我认为是地域)。一些国家/地区从周日开始一周,其他国家/地区从周一开始。
    【解决方案4】:

    我建议使用@Jeff Moore 提到的to_date(your_date,'d')。但是,我还建议摆脱for..loop。作为奖励,这将添加任何给定年份的所有天数,这与您的版本不同,它将在闰年产生额外的一天:

    INSERT INTO MY_TABLE (ID, MY_DATE)
    SELECT   lvl, dt
      FROM   (    SELECT   LEVEL lvl,
                           TO_DATE('1/1/2011', 'mm/dd/yyyy') + LEVEL - 1 dt
                    FROM   DUAL
              CONNECT BY   TO_DATE('1/1/2011', 'mm/dd/yyyy') + LEVEL - 1 <
                              ADD_MONTHS(TO_DATE('1/1/2011', 'mm/dd/yyyy'), 12))
     WHERE   TO_CHAR(dt, 'd') NOT IN (1, 7)
    

    如果您希望“ID”列是连续的,您可以在外部查询中使用rownum 而不是lvl

    【讨论】:

      猜你喜欢
      • 2017-07-04
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      • 2014-09-17
      • 2016-01-17
      相关资源
      最近更新 更多