Mig*_*uel 8 sql-server sql-server-2012
我有一个问题,因为我一直在使用这个查询没有问题......直到现在:
UPDATE T1
SET ORDINAL = DATEDIFF(DAY, T2.Opening_Date, T1.Date)
FROM FactTransactions T1
INNER JOIN DimStore T2 ON T1.cod_store = T2.cod_storeKey
Run Code Online (Sandbox Code Playgroud)
但现在它给了我一个错误:
从字符串转换日期和/或时间时转换失败
我不知道是怎么回事。以下是列:
Ordinal(numeric,null)
Opening_date(varchar, not null)
Date(varchar, not null)
cod_store(int,not null)
cod_storekey(PK,int, not null)
Run Code Online (Sandbox Code Playgroud)
您将日期存储为字符串 - 为什么?Opening_Date
并且Date
应该是date
or datetime
,不是varchar
。但在解决此问题之前,您需要确定导致转换问题的行:
SELECT cod_store, [Date]
FROM dbo.FactTransactions
WHERE ISDATE([Date]) = 0;
SELECT cod_storekey, Opening_Date
FROM dbo.DimStore
WHERE ISDATE(Opening_Date) = 0;
Run Code Online (Sandbox Code Playgroud)
现在您已经解决了这个问题,并且我知道您使用的是 2012 而不是 2008 R2,使用它可能更干净TRY_CONVERT()
,特别是因为它可以让您识别月和日转置不正确的任何行。例如,假设您希望将日期存储为mm/dd/yyyy
字符串:
SELECT cod_store, [Date]
FROM dbo.FactTransactions
WHERE TRY_CONVERT(datetime, [Date], 101) = 0;
SELECT cod_storekey, Opening_Date
FROM dbo.DimStore
WHERE TRY_CONVERT(datetime, Opening_Date, 101) = 0;
Run Code Online (Sandbox Code Playgroud)
除了识别用户在何处存储废话像垃圾一样行floob
和9992-13-36
作为“日期”,这也将确定用户在何处存储行13/07/1999
代替07/13/1999
(但没有办法知道是否05/06/2000
意味着是5月6日或6月5日)。
现在,您需要先修复这些行,然后才能更正表。
ALTER TABLE dbo.DimStore ALTER COLUMN Opening_Date date; -- or datetime;
ALTER TABLE dbo.FactTransactions ALTER COLUMN [Date] date; -- or datetime;
Run Code Online (Sandbox Code Playgroud)
您还可以考虑将Date
列重命名为 (a) 不那么模糊和 (b) 不是保留字。
如果无法修复表,则需要更改查询:
UPDATE T1
SET ORDINAL = DATEDIFF(DAY,
CASE WHEN ISDATE(T2.Opening_Date) = 1 THEN T2.OpeningDate END,
CASE WHEN ISDATE(T1.[Date]) = 1 THEN T1.Date END)
FROM dbo.FactTransactions AS T1
INNER JOIN dbo.DimStore AS T2
ON T1.cod_store = T2.cod_storeKey
WHERE ISDATE(T2.Opening_Date) = 1
AND ISDATE(T1.[Date]) = 1;
Run Code Online (Sandbox Code Playgroud)
@RLF 也提出了一个很好的观点;如果您无法修复表格,则日期列可能包含表示特定日期(例如 9 月 7 日)但以错误格式输入的数据(例如,在美国英语系统中,以英国格式输入为字符串, 7/9/2015)。所以真的,你需要修复表格并停止将这些东西存储为字符串。
其他一些有用的材料:
您可以使用具有正确样式的Convert以将varchar(x)
本地格式转换为正确的日期:
DATEDIFF(DAY, convert(date, T2.Opening_Date, 104), convert(date, T1.Date, 104))
Run Code Online (Sandbox Code Playgroud)
在此示例中,我假设您使用的是德国风格 (dd.mm.yyyy)。德国风格是104
:
Select convert(date, '01.02.2015', 104)
Run Code Online (Sandbox Code Playgroud)
输出: 2015-02-01
您必须使其适应您的设置和本地格式,并用您使用的任何内容替换 104。主要款式有:
Style Standard Input/Ouput
1 U.S. 1 = mm/dd/yy
101 U.S. 101 = mm/dd/yyyy
2 ANSI 2 = yy.mm.dd
102 ANSI 102 = yyyy.mm.dd
3 British/French 3 = dd/mm/yy
103 British/French 103 = dd/mm/yyyy
4 German 4 = dd.mm.yy
104 German 104 = dd.mm.yyyy
5 Italian 5 = dd-mm-yy
105 Italian 105 = dd-mm-yyyy
Run Code Online (Sandbox Code Playgroud)
看看CAST 和 CONVERT (Transact-SQL)
如果您的日期格式错误或格式混合,您还可以使用以下查询查看TRY_CONVERT:
Select ...
FROM FactTransactions T1
INNER JOIN DimStore T2 ON T1.cod_store = T2.cod_storeKey
Where try_convert(date, T2.Opening_Date, 104) is null
or try_convert(date, T1.Date, 104) is null
Run Code Online (Sandbox Code Playgroud)
它将为您提供样式 104 格式不正确的日期列表。同样,根据您的设置调整它并替换 104。您可以在修复错误格式和日期之前使用它。
但主要的问题和问题是:你为什么使用 varchar(x)。如果您可以更新您的表格,您应该使用 Date 或 Datetime 2。