问题
I am trying to remove the timestamp from my date values so I end up with something like mm/dd/yy or mm/dd/yyyy. I referenced many technet, stackoverflow, and w3schools articles but still can't get the date to appear correctly. All of my columns in the table are defined as a datetime and they come from the same table.
I am using convert statements like this: CONVERT(VARCHAR(10), E.PD_DT, 101) AS 'Paid Date'
In place of 101 I have used 10 and 11, still have the same issue with the data (below). What's happening is when the date value (not including the time) is 8 characters, I am getting an additional character from the time, as seen in the Claim Adjustment Date-10 and Claim Adjustment Date-11 columns. Here is my data:
Claim Paid Date-101 Claim Paid Date Claim Adjustment Date-10 Claim Adjustment Date-11 Claim Adjustment Date
10/23/2012 10/23/12 12:00 AM 9/4/2012 1 9/4/2012 1 9/4/12 12:00 AM
10/23/2012 10/23/12 12:00 AM 9/4/2012 1 9/4/2012 1 9/4/12 12:00 AM
10/23/2012 10/23/12 12:00 AM 9/4/2012 1 9/4/2012 1 9/4/12 12:00 AM
09/06/2011 09/06/11 12:00 AM 9/4/2012 1 9/4/2012 1 9/4/12 12:00 AM
10/23/2012 10/23/12 12:00 AM 8/21/2012 8/21/2012 8/21/12 12:00 AM
09/06/2011 09/06/11 12:00 AM 8/21/2012 8/21/2012 8/21/12 12:00 AM
The strange thing is that all of the dates in the "Claim Paid Date" column have a zero for padding if the month or day is < 10. This makes the convert come out just fine but where the month or day is < 10 and doens't have a zero is where I get my problem.
回答1:
You have a string source, not a DATETIME
source.
What happens with DATETIME
:
SELECT GETDATE() -- DATETIME
,CAST(GETDATE() AS DATE) --DATE
,CONVERT(VARCHAR(10),GETDATE(),101) --101 format
Result:
DateTime Date 101 Format
----------------------- ---------- ----------
2013-09-24 13:58:48.880 2013-09-24 09/24/2013
What happens with strings parading as DATETIME
:
DECLARE @fake_date VARCHAR(25) = '10/23/12 12:00 AM'
SELECT CAST(@fake_date AS DATETIME) --DATETIME
,CAST(@fake_date AS DATE) --DATE
,CONVERT(VARCHAR(10),@fake_date,101) --101 format
Result:
DateTime Date 101 Format
----------------------- ---------- ----------
2012-10-23 00:00:00.000 2012-10-23 10/23/12 1
So perhaps you want:
CONVERT(VARCHAR(10),CAST(@fake_date AS DATE),101)
回答2:
The correct way to do this is to store the data as DATETIME
in the first place. Currently you are storing the data as strings, and you shouldn't be doing this, for a variety of reasons:
- you lose the ability to sort (
9/1/2012
will sort after12/12/2012
) without converting first. Converting is expensive. - you lose the ability to perform meaningful range queries without converting first (again,
9/1/2012
>12/12/2012
) - you lose all means of built-in validation - anyone can enter
13/33/2999
or02/32/2099
or simplyfoo
as a "date" - you lose the ability to perform date-related functions such as
DATEADD
,DATEPART
orDATEDIFF
against these columns without first converting - you need to convert to another type first before you can perform a conversion that will allow you to do things like trim time or present the date in a specific format
If you can't fix the table design and want to continue storing dates using the wrong data type, then the next best thing is to simply format the string in the client. If the client knows it's a date/time, then using .Format()
or .ToString()
should allow you to present the date without the time in whatever format you want.
You should be presenting dates to users in unambiguous formats, since you never know when some of your readers will see 6/12/2012
and not be sure if that's June 12 or December 6 (Canadians and Americans will see those differently, for example). So you can use, as an example:
DateVariable.Format('yyyy-MM-dd')
This will present an unambiguous date like 2012-06-12, which can only be misinterpreted in some very isolated regions and age groups in France (where y-d-m seems to remain in vogue).
However, if you absolutely want to present the ambiguous format, you can just use:
DateVariable.Format('MM/dd/yyyy')
...with no reason to change your SQL query at all. If, for some reason, you absolutely want or need to do this at the query level, then you can use:
SELECT CONVERT(CHAR(10), CONVERT(DATE, col), 101) -- mm/dd/yyyy
If you want to use less ambiguous forms, like yyyymmdd
or yyyy-mm-dd
, you can use:
SELECT CONVERT(CHAR(8), CONVERT(DATE, col), 112) -- yyyymmdd
SELECT CONVERT(CHAR(10), CONVERT(DATE, col), 120) -- yyyy-mm-dd
But again, conversion at the database layer is expensive, whereas string formatting at the client layer (where you're already handling these things as strings at that final step) is relatively cheap. You should be keeping these as date values as long as possible, both on the way in and on the way out of the database. There is just no advantage to treating them as strings anywhere SQL Server is concerned.
So, summary:
- fix the table
- perform the conversion on the client (preferably to an unambiguous format)
- if you can't perform the conversion on the client, use a double-nested
CONVERT
(again, preferably to an unambiguous format)
来源:https://stackoverflow.com/questions/18987990/converting-sql-date-formats-not-ending-up-the-same