2011-07-05 86 views
3

我想插入一些數據到與下一年的日期相關的表中。我其實只需要插入工作日。Oracle 11g - 只在工作日插入表中的FOR循環?

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; 

我可以解決回去和刪除是週末兩天排我的問題,但似乎相當不雅 - 任何人都可以想辦法來修改我的循環,使其跳過週末?

回答

7

你總是可以檢查星期插入行之前(的星期幾的名稱將取決於您的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; 
+2

我們可以使用D'格式掩碼代替。星期幾仍然取決於NLS_TERRITORY(美國的星期日是1,英國的星期日是7),但與日子的名字相比變化不大。 – APC

+0

@APC - 非常真實。但是一旦你將NLS設置加入混音中,問題會變得更加複雜。我有足夠的時間知道我們美國人在哪一天宣佈本週開始,更不用說搞清楚你們英國人的決定了。 –

+2

'無論NLS會話設置如何,'to_char(SYSDATE,'fmDAY','nls_date_language =''AMERICAN''')'都會返回正確的輸出* –

0

如果讓星期一= 0和星期日= 6,則可以使用(如果mod(i,7)< 4)),則Insert ...應該可以工作。

+0

這對oracle有何用處? –

2

您可以使用以下某種日期格式來檢查它是哪一天。

從dual中選擇to_char(sysdate,'DAY');/* TUESDAY */
從dual中選擇to_char(sysdate,'D');/* 3 */
從dual中選擇to_char(sysdate,'DY');/* TUE */

添加如下所示的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; 
+2

'D'值取決於NLS設置(我認爲是領土)。有些國家星期日開始本週,其他星期一開始。 –

3

我建議使用to_date(your_date,'d')作爲@Jeff Moore的提及。不過,我也建議擺脫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在外部查詢中。