Converting SQL date formats not ending up the same

╄→гoц情女王★ 提交于 2020-01-17 08:11:25

问题


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 after 12/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 or 02/32/2099 or simply foo as a "date"
  • you lose the ability to perform date-related functions such as DATEADD, DATEPART or DATEDIFF 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:

  1. fix the table
  2. perform the conversion on the client (preferably to an unambiguous format)
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!