I need to import some data obtained from an Indonesian file, part of which is a date in the form '01OKT2011'. I need to be able to automatically convert these to a T-SQL datetime, eg 10-01-2011 00:00:00.
The simplest way I can think of to do it is to create a lookup table with a column for the foreign short name and one for the month number, but this is made more difficult by the fact that the only source file I have at the moment only covers October and November, and I'm not entirely sure how the other months will be abbreviated.
Is there a simpler way to do this? Does one of the built in languages in SQL Server use the same month short names?
Look into your syslanguages table to learn whether your SQL Server installation supports Indonesian.
Supposing that SQL Server supports Indonesian, set your language to it. Also, SET DATEFORMAT ymd. Then use the datetimes directly.
If Indonesian is not supported/installed, you should try hard to solve localization outside of the database (which I'd actually recommend even if the database server is willing to understand your month names, but I'm saving that advice for a quite different question).
In that case the following approach might help you, if not for actual use, at least for conversion of your data.
DATETIMEFROMPARTS(
SUBSTRING(x, 6, 4),
REPLACE(...(REPLACE(SUBSTRING(x, 3, 3), 'JAN', 'Jan')...,'OKT', 'Oct'),...,'DEC', 'Dec')...),
SUBSTRING(x, 1, 2)
)
Related
I want to create a column of data type having only 'mm-dd' values.
Is it possible and if yes how should I do it?
Note: Instead of "2022-06-07", I want "07-06"
There is no date type that can store that format - in fact none of the date types store a date and/or time in any of the formats you typically recognize.
For your specific requirement, that looks like a char(5) for the data type, but how you constrain it so that it will only accept valid date values, I have no idea. You'd think this would work:
CHECK (TRY_CONVERT(date, string_column + '-2022', 105) IS NOT NULL)
But what about leap years? February 29th is sometimes valid, but you've thrown away the only information that can make you sure. What a bunch of mess to store your favorite string and trust that people aren't putting garbage in there.
Honestly I would store the date as a date, then you can just have a computed column (or a column in a view, or just do this at query time:
d_slash_m_column AS CONVERT(char(5), date_column, 105)
Why not just in your query (or only in a view) say:
[output] = CONVERT(char(5), data_in_the_right_type, 105)
?
I'd personally stay away from FORMAT(), for reasons I've described here:
FORMAT() is nice and all, but…
FORMAT is a convenient but expensive function - Part 1
FORMAT is a convenient but expensive function - Part 2
You can use the SQL Server FORMAT function:
FORMAT(col1, 'dd/MM')
Check the demo here.
In such cases using char or varchar is not the best option as in those cases the underlying DB constraints that validate the integrity of the data do not kick in.
Best option is to use an arbitrary year and then put in a proper date, so for example for storing 01-Jan, the db column should store proper date with year as any arbitrary value, e.g. 2000. So your db should say 2000-01-01.
With such a solution you are still able to rely on the DB to raise an error if you tried month 13. Similarly sorting will work naturally as well.
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)
I realise that you can use SET DATEFORMAT to alter the way that a string is parsed but is the following unambiguous:
SELECT CONVERT(DATE, '02Oct15')
Is there any circumstances that this would be interpreted as 15th October 2002?
The century conversion will be an issue in 35 years (the y2k50, there is an amusing thought), but until then it's unambiguous. Any attempt to pass an invalid date in the first section results in a conversion error rather than it treating the third section as a date instead of a year.
Finally changing the default language (which changes the default date format) uses the same conversion (British), or causes it error out (Italian). Still as others have mentioned, storing dates in this format is a bad idea, however unless I miss my guess this seems like your importing data from a report, so you probably don't have much control over it. Anyway hope that helps and good luck.
I was not able to make 02Oct15 to become October 15, 2002. However, if all three date components are numbers, it's easy to make that cast:
SET DATEFORMAT YMD
SELECT CONVERT(DATE, '02Oct15'), -- October 2, 2015
CONVERT(DATE, '021015') -- October 15, 2002
I suspect that once you introduce natural language to the string, SQL Server use culture-specific rules to convert the date components. But in the end, only Microsoft knows what SQL Server's string-to-date algorithm is.
Now it generates inserts like
INSERT [Bla] ([id], [description], [name], [version])
VALUES (CAST(1 AS Numeric(19, 0)), convert(t...
It's very SQL Server specific. I would like to create a script that everybody can use, database agnostic. I have very simple data types - varchars, numbers, dates, bits(boolean).
I think
insert into bla values (1, 'die', '2001-01-01 11:11:11')
should work in all DBMSs, right?
Some basic rules:
Get rid of the square brackets. In your case they are not needed - not even in SQL Server. (At the same time make sure you never use reserved words or special characters in column or table names).
If you do need to use special characters or reserved words (which is not something I would recommend), then use the standard double quotes (e.g. "GROUP").
But remember that names are case sensitive then: my_table is the same as MY_TABLE but "my_table" is different to "MY_TABLE" according to the standard. Again this might vary between DBMS and their configuration.
The CAST operator is standard and works on most DBMS (although not all support casting in all possible combinations).
convert() is SQL Server specific and should be replaced with an approriate CAST expression.
Try to specify values in the correct data type, never rely on implicit data conversion (so do not use '1' for a number). Although I don't think casting a 1 to a numeric() should be needed.
Usually I also recommend to use ANSI literals (e.g. DATE '2011-03-14') for DATE/TIMESTAMP literals, but SQL Server does not support that. So it won't help you very much.
A quick glance at the Wikipedia article on SQL, will tell you a bit about standardisation of SQL across different implementations, such as MS SQL, PostgreSQL, Oracle etc.
In short, there is a number of ANSI standards but there is varying support for it throught each product.
The general way to support multiple database servers from your software product is to accept there are differences, code for them at the database level, and make your application able to call the same database access code irrespective of database server.
There are a number of problems with number formats which will not port between dbmses however this pales when you look at the problems with dates and date formats. For instance the default DATE format used in an ORACLE DB depends on the whims of whoever installed the software, you can use date conversion functions to get ORACLE to accept the common date formats - but these functions are ORACLE specific.
Besides how do you know the table and column names will be the same on the target DB?
If you are serious about this, really need to port data between hydrogenous DBMSes, and know a bit of perl thn try using SqlFairy which is available from CPAN. The sheer size of this download should be enough to convince you how complex this problem can be.
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.