I'm writing a script to cleanup some data, converting dates stored in an varchar field from dd/mm/yy to dd/mm/yyyy format. (yes, I know, but not my design :)
I've got a script written to do this, but I've currently got a hardcoded constant of 2049 as the cutoff date. I know SQL has a 'Two Digit Year Cutoff' advanced option, which I'd like to use in place of this constant.
Is there a safe/convenient way to retrieve and use this in a script?
(Needs to support SQL-Server 2005/2008/2008R2)
SELECT value
FROM sys.configurations
WHERE name = 'two digit year cutoff'
But can't you just convert (assuming that your system is setup to use dd/mm/yyy as a standard) to a datetime, and then back again?
Related
I'm trying to INSERT date variable into my SQL server.
The input format I'm trying to insert is: dd-mm-yyyy
And my SQL server column (which defined as type DATE) expect mm-dd-yyyy.
My PC date format is dd-mm-yyyy.
The error msg:
Conversion failed when converting date and/or time from character string.
Questions:
Why is the expected format mm-dd-yyyy and not dd-mm-yyyy?
How can I make the INSERT command work with this or another date format?
Thanks.
The format that your PC uses for dates doesn't matter when passing literal string for dates, the language setting for the LOGIN you are using to connect to SQL Server does. As the value is being interpreted as MM-dd-yyyy this very likely means that your language setting is (American) ENGLISH.
If, therefore, you are the only person that uses that LOGIN you may well want to change the language of your LOGIN to be appropriate for yourself. Most of the European languages, including BRITISH English (because the British don't speak English Microsoft? 😒) use the format dd-MM-yyyy.
Really, however, what you should be doing is using an unambiguous date format, of which there are only 2 in SQL Server, regardless of the language setting and data type. Those 2 formats are yyyyMMdd and yyyy-MM-ddThh:mm:ss.nnnnnnn. If you are always using the newer date and time data types (so not datetime or smalldatetime), then yyyy-MM-dd( hh:mm:ss.nnnnnnn) is also unambiguous, however, as it's language specific for the older data type then I don't normally recommend it's use.
Storage wise, date and time data types don't have a format, so your column isn't "expected" a value in the format MM-dd-yyyy, as it doesn't retain the "format data" that the value was passed in. Again, the only reason why a value like 13-12-2020 is working is because your language setting, which uses mdy for date interpretation.
Two things really,
Firstly, you can control the expected date format for each connection. Before issuing the insert statement, do set dateformat dmy; or set dateformat mdy; as appropriate.
Secondly, it's always advisable to work with dates in the ISO format of YYYYMMDD, so if you insert the data '20210314' it will always be treated correctly.
I know that ACCESS's time format depends on your Windows time settings. I use ISO-8601 format (YYYYMMDD) so that I can get away with SQL WHERE statements like this one:
WHERE dates > #2020/02/15#
AND dates < #2021/01/30#
If I run the code from above in another computer, whose Windows time settings are for example DDMMYYYY, will the SQL statement no longer work? I could simply do something like this to solve that problem (will it though?):
WHERE dates BETWEEN Format(date1, "\#YYYY\/MM\/DD\#") AND Format(date2, "#YYYY\/MM\/DD\#")
EDIT: Time format has beign changed as pointed out by #Gustav. The question remains; will the first WHERE Statement no longer work on different Windows time settings? Will the second correct the problem?
In Access SQL, use octothorpes:
WHERE dates > #2020/02/15#
AND dates < #2021/01/30#
WHERE dates BETWEEN Format(date1, "\#YYYY\/MM\/DD\#") AND Format(date2, "#YYYY\/MM\/DD\#")
Nope, Windows time settings will mess with a lot of things, but not with ordering or comparisons with dates.
As long as the field is defined as a date (so with octothorpes, like Gustav said), the 2nd of February 2021 will be less the 11th of February 2021, even though that wouldn't be the case if you cast them to a string first.
Always try to keep columns as they are when filtering, so if dates is actually a date column (and not a formatted string), just use WHERE dates BETWEEN #2020/02/15# AND #2021/01/30#, no formats, no funky stuff. And note that especially when trying to keep your application working in all locales, it's important to avoid casting dates to strings, which can happen if you compare a date with a formatted string.
Can anyone help me in writing a query for creating a table which will store date in the format of month/date/year (mm/dd/_ _ _ _)?
I do not want to use varchar, because I will be needing to compare my dates also. I also do not want to use any other date formats because my inputs are being entered in the format of month/date/year (mm/dd/_ _ _ _)?
You can use varchar and it can be converted using the option 101 to the format you want (mm/dd/yyyy).
SELECT CONVERT(varchar(10), CONVERT(datetime, '2017/10/02', 111), 101)
The answer is going to depend on what type of database you are using (SQL Server, MySQL, PostgreSql, etc.) and whether you are doing this with 100% SQL, or if you have an application that uses another language that could manipulate the data as well.
Assuming this is an all SQL application, if you need to compare the dates, you will likely need to use the native Date data type for whatever database you are using.
By contrast, you could store it as a varchar, but then would need to cast it as a date for comparison.
To get the date into the format the you are needing, again depending on the database, you may have some sort of date_format function available to input/output the date in the format that you need. If there is not a native function for your database, someone has likely come up with a solution for that database. Searching for your database type (MySQL, Postgresql, etc.) and "date format" will be a good starting point.
If your application is also using another language, it may also have some native functions to convert the date into the format that you need.
I know this didn't directly answer your question, but hopefully gets you thinking about different ways to solve the problem and gets you pointed in the right direction.
You can use varchar and then convert it to your desired format. Here is a sample query.
DECLARE #s DATETIME
SELECT #s = CONVERT(DATETIME, '03/13/2013', 101)
Does SQLs built-in DateTime type has any merits over nvarchar type?
If it were you , which one would you use?
I need to store dates in my SQLServer database and I'm curious to know which one is better and why it is better.
I also want to know what happens if I for example store dates as string literals (I mean nvarchar )? Does it take longer to be searched? Or they are the same in terms of performance ?
And for the last question. How can I send a date from my c# application to the sql field of tye DateTime? Is it any different from the c#s DateTime ?
You're given a date datetype for a reason, why would you not use it?
What happens when you store "3/2/2012" in a text field? Is it March 2nd? Is it February 3rd?
Store the date in a date or datetime field, and do any formatting of the date after the fact.
EDIT
If you have to store dates like 1391/7/1, your choices are:
Assuming you're using SQL Server 2008 or greater, use the datetime2 data type; it allows dates earlier than 1753/01/01 (which is what datetime stops at).
Assuming you're using SQL Server 2005 or earlier, store the dates as Roman calendar dates, and then in your application, use date/time functions to convert the date and time to the Farsi calendar.
Use the correct datatype (date/datetime/datetime2 dependant on version and requirement for time component).
Advantages are more compact storage than storing as a string (especially nvarchar as this is double byte). Built in validation against invalid dates such as 30 February. Sorts correctly. Avoids the need to cast it back to the correct datatype anyway when using date functions on it.
If I'm storing a DateTime value, and I expect to perform date-based calculcations based on it, I'll use a DateTime.
Storing Dates as strings (varchars) introduces a variety of logistical issues, not the least of which is rendering the date in a proper format. Again, that bows in favor of DateTime.
I would go with the DateTime since you can use various functions on it directly.
string wouldn't be too much of a hassle but you will have to cast the data each time you want to do something with it.
There is no real performance variance while searching on both type of fields so going with DateTime is better than strings when working with date values.
you must realise the datetime datatype like other datatypes is provided for a reason and you should use the datatype that represents your data clearly.. Besides this you gain all the functionalities/operations that are special to the datetime datatype..
One of the biggest gains is correct sorting of data which will not be possible directly if you use nvarchar as your datatype.. Even if you think you dont need sorting right now there will be a time in the future where this will be useful.
Also date validation is something that you will benefit from. There is no confusion of the dateformat stored i.e dd/mm or mm/dd etc..
There is lot discussed about the subject. There is good post on the SQLCentral forum about this particular subject DateTime or nvarchar.
In short, nvarchar is twice as longer as datetime, so it takes more space and on the long range, any action affecting it will be slower. You will have some validation issues and many more.
I require a SQL script to validate a VARCHAR field in a table in a SQL Server 2005 database that contains DateTime values, in the format DD/MM/YYYY, or NULL values. I would like to identify all invalid dates. Can anyone suggest a method?
UPDATE
The answer has to make use of T-SQL; for performance reasons, I can't make use of SQLCLR.
Thanks, MagicAndi
Use "ISDATE()" OR "IS NULL": but set the language first to recognise the day-month-year order
SET LANGUAGE british
SELECT ISDATE('12/31/2009'), ISDATE('31/12/2009')
SET LANGUAGE us_english
SELECT ISDATE('12/31/2009'), ISDATE('31/12/2009')
Edit: As mentioned by #edosoft, you can use SET DATEFORMAT too. SET LANGUAGE implicitly sets DATEFORMAT, SET DATEFORMAT overrides SET LANGUAGE
You should specify the dateformat when using ISDATE(). From Books Online:
SET LANGUAGE us_english;
SET DATEFORMAT dmy;
SELECT ISDATE('15/04/2008'); --Returns 1.
You could use the ISDATE() function
you can use the inbuilt T-SQL IsDate() function.
and change the column to be datetime not varchar.
you can't sort or do any date calcualtions on a varchar column.
SQL's date handling isn't great, we wrote a DotNet function to do our DateTime conversions for difficult case.
I have a solution, although it applies only in a certain set of circumstances. Your case may or may not be right for this.
Create a table called ALMANAC with one row for every valid date. You can populate it with ten years of valid dates with only 3,653 rows, more or less. Even if you go for a hundred years, that's still only 36,525 rows, not too terribly big by today's standards.
You can add strange company specific attributes to this table if it's useful. These are attributes like whether the date is a company specific holiday or not, and what fiscal week, fiscal month, fiscal quarter, and fiscal year the date belongs to.
You'll have to write a program to populate this table, and this program will have to have your company specific calendar rules embedded, if you choose the extra attributes.
Then, you can use this table just like you would use any code validation table. You may also be able to use it to make quirky calendar driven reporting criteria absolutely trivial to implement.
This is only a good idea if your dates are limited to a limited time span, like ten years or maybe even a hundred years. But sometimes, it can really be a time saver! I have sometimes used this technique to make my database independent of one vendor's calendar functions.