2014-07-16 111 views
1

轉換日期和/或時間的字符串我有我的表中的下列列:轉換失敗時SQL

year decimal(4,0) 
month decimal(2,0) 
day decimal(2,0) 

,我試圖將它們如下轉換:

SELECT (CAST (CAST(year AS varchar(4)) 
      +CAST(month AS varchar(2)) 
      +CAST(day AS varchar(2) 
      ) AS date)) AS xDate 
FROM table 
ORDER BY xDate DESC 

但我收到此錯誤:

Conversion failed when converting date and/or time from character string.

+0

您是否試圖rt到日期時間? –

+0

我用硬編碼的數字做了一個快速測試,它適用於我,所以你確定「年」,「月」和「日期」是數字,並在可接受的範圍內? – jimo3

+0

@Kris - 我試圖將其轉換爲日期,但如果它很容易轉換爲日期時間那麼這也很好,但我得到錯誤。 – Geeme

回答

0

此問題是因爲您的表中有冗餘數據(您的查詢沒有錯誤)。請在您的表格中查看。

1)。 天的列值不得大於關聯月份(例如,第2個月中不得有30天或31天)的最大天數。 2)。值爲月份列不得大於或等於。

2

您的方法沒有考慮到monthday可以是一位數值。如果你有一排這樣的:

year month day 
---- ----- --- 
2014 7  18 

你的方法將拼接的部分爲2014718和隨後試圖將其轉換成date將導致問題的錯誤。

您可能想要合併如下零件:20140718,這將轉換爲date沒有問題。對我來說,去從數字部分該格式的最簡單的方法是這樣的:

  • 計算year * 10000 + month * 100 + day;

  • 將以前的結果轉換爲char(8);

  • 將字符串轉換爲date

所以,在Transact-SQL它會是這樣:

CAST(CAST(year * 10000 + month * 100 + day AS char(8)) AS date) 

在不同的音符,我不可能知道你是否真的需要存儲您的日期分裂一樣,當然,但如果你堅持這樣做,至少考慮使用整數類型的零件。我意識到,decimal(2,0)可能會作爲某種約束條件,確保您無法使用兩位數以上的月份或日期值,但仍無法保護您無效的月份或日期。而另一個重點是decimal(2,0)需要更多的存儲空間,甚至比int更不用說,更不用說smallinttinyint

所以,這似乎沒什麼問題

year int, 
month int, 
day int 

但如果你是到節省存儲空間儘可能的,你也可以試試這個:

year smallint, 
month tinyint, 
day tinyint 

最後,爲了確保你不能在這些列中有無效的值,你可以添加一個檢查約束,如下所示:

ALTER TABLE tablename 
ADD CONSTRAINT CK_tablename_yearmonthday CHECK 
    ISDATE(CAST(year * 10000 + month * 100 + day AS char(8))) = 1 
;