2012-03-28 68 views
-1

將文本轉換爲日期時間我需要將轉換文本(VARCHAR)列到DATETIME如果一個表達式,且僅當它匹配dd/MM/yyyyd/MM/yyyydd/M/yyyyd/M/yyyy。如果它不匹配,那麼我想要一個NULL在特定格式

我有這個...

CASE ISDATE([DateField]) 
    WHEN 1 THEN CONVERT(DATETIME,[DateField],103) 
    ELSE NULL 
END 

但是失敗了'15/04/76'例如 - 有錯誤「的轉換從字符串轉換日期時間時失敗」 - 而我希望它返回NULL

示例輸出

'1/6/1976'  -> 1976-06-01 
'01/06/1976' -> 1976-06-01 
'13/06/2001' -> 2001-06-13 
'06/13/2001' -> NULL 
'13/06/76'  -> NULL 

是否有強迫ISDATE來驗證一個給定的格式的一種方式?

The documentation似乎暗示所以...如果與CONVERT函數中使用

ISDATE只有確定性的 CONVERT樣式參數是指定的,風格不等於0,100, 9,或109.

但是ISDATE只需要一個參數,那麼如果我不這樣做,我該如何「使用它與CONVERT函數」?

+0

請在downvoting時發表評論。這個問題完全有效。 – 2012-03-28 15:14:43

+0

有趣的是,我收到了這個問題的'普遍問題'徽章,它已經收到一個downvote,沒有upvotes ... – 2013-04-04 09:30:10

回答

1

你可以在這裏做一個嵌套的case語句。第一個可以檢查是否有10個字符的字符串2爲一天,2個爲一個月,4個爲一年,2爲分隔符= 10個字符。

SET DATEFORMAT DMY; 

    Case When DateField Like '%/%/[0-9][0-9][0-9][0-9]' 
     Then Case When IsDate(DateField) = 1 
        Then CONVERT(DATETIME,[DateField],103) 
        End 
     End 

修:我改變了代碼中使用,迫使那裏是在字符串的結尾/ YYYY,然後做一個則IsDate檢查,以允許單日和/或每月像搜索。

+0

嗨我還需要'1/6/1976'例如有效,並轉換爲DATETIME – 2012-03-28 14:13:50

+0

看到我修改後的建議。 – 2012-03-28 14:47:45

+0

額外的情況是否真的有必要?我想你可以用一個簡單的AND來做到這一點。處理順序不應改變結果。 – 2012-03-28 15:40:45

0

感謝您的回覆人。

我已經做了這樣的...

CASE ISDATE([DateField]) WHEN 1 THEN 
    CASE WHEN SUBSTRING([DateField],LEN([DateField])-4,1) = '/' THEN 
     CASE WHEN CHARINDEX('/',[DateField],LEN([DateField])-3)=0 THEN 
      CONVERT(datetime, [DateField] , 103) 
     END 
    END 
END 

這是非常討厭的業務,所以仍然會欣賞的東西整潔!

但是這也行不通 - 它仍然在mm/dd/yyyy格式日期上出錯!

廢棄最後一條評論 - 現在確實有效?可能與某事有關SET DATEFORMAT

+0

如果字符串不是有效日期,則代碼將失敗。例如,針對字符串「Yesterday」運行您的代碼,您將收到轉換錯誤。 – 2012-03-28 14:50:15

+0

您正在將日期時間值放入varchar中。你如何期望SQL Server能夠區分'01/03/1976'和'03/01/1976'之間的區別? – 2012-03-28 15:02:48

+0

@AaronBertrand我知道這是多麼愚蠢的把日期放在一個文本字段(不是我的數據庫...)。不過我只想用dd/MM/yyyy日期工作 - 因此我希望可能會有類似於.Net的'TryParseExact'的函數。感謝您的TRY_CONVERT建議 - 我期待2012年! – 2012-03-28 15:23:27

1

那麼,首先,爲什麼地球上的日期時間值存儲在varchar列?由於各種原因,這是一個主要罪魁禍首,其中最重要的是你無法驗證數據是否是(或可以轉換爲)日期時間。即使將列作爲varchar保留,也應該考慮驗證輸入,因此您不需要考慮有效的各種潛在格式。

因此,這裏是一個辦法,借用@G Mastros位:

DECLARE @f TABLE(i INT, d VARCHAR(32)); 

INSERT @f VALUES 
(1,'15/04/76'), 
(2,'15/04/1976'), 
(3,'1/3/1976'), 
(4,'1/3/76'), 
(5,'15/3/1976'), 
(6,'22/22/22'), 
(7,'Yesterday'); 

SET DATEFORMAT DMY; 

SELECT i, d, d2 = CASE WHEN ISDATE(d) = 1 
    AND d LIKE '%/[0-9][0-9][0-9][0-9]' 
    THEN CONVERT(DATETIME, d, 103) END 
    FROM @f; 

結果:

i d   d2 
- ---------- ----------------------- 
1 15/04/76 NULL 
2 15/04/1976 1976-04-15 00:00:00.000 
3 1/3/1976 1976-03-01 00:00:00.000 
4 1/3/76  NULL 
5 15/3/1976 1976-03-15 00:00:00.000 
6 22/22/22 NULL 
7 Yesterday NULL 

PS,這將是在SQL Server 2012中它確實爲TRY_CONVERT很大的情況下,正是你要求的 - 它試圖轉換爲指定的數據類型;如果不能,則返回NULL

+0

不幸的是,OP的年份需要4位數字。如果一年只有2位數字,則OP需要NULL。你的代碼無法處理。 – 2012-03-28 14:49:26

+0

對不起,錯過了這個要求。更新。 – 2012-03-28 14:56:56

+0

感謝您的光芒,但不幸的是我正在使用的模式不是我設計的(並且不會這樣)。我也不負責數據的驗證。答案看起來不錯,謝謝,我會給它一個:) – 2012-03-28 15:17:55