I'm trying to debug a MS SQL Server error 242:
>The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
The error is originated by this statement:
```sql
CREATE TABLE db.schema.test (
Column1 datetime NULL
) GO
INSERT INTO db.schema.test (Column1)
VALUES (convert(varchar,convert(datetime,{D '2019-06-30'}),102));
```
This is my server version:
Microsoft SQL Server 2017 (RTM-CU15) (KB4498951) - 14.0.3162.1 (X64)
May 15 2019 19:14:30
Copyright (C) 2017 Microsoft Corporation
Standard Edition (64-bit) on Linux (Debian GNU/Linux 9 (stretch))
And the language `@@LANGUAGE` is `Italiano`.
The same statements works on
Microsoft SQL Server 2017 (RTM-CU10) (KB4342123) - 14.0.3037.1 (X64)
Jul 27 2018 09:40:27
Copyright (C) 2017 Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)
With language: `us_english`
Without without making explicit convert style it works
```sql
INSERT INTO db.schema.test (Column1)
VALUES (convert(varchar,convert(datetime,{D '2019-06-30'})));
```
Convert style 102 is ANSI `yyyy.mm.dd`, shouldn't be recognized by both English and Italian SQL Server?
```
VALUES (convert(varchar,convert(datetime,{D '2019-06-30'}),102));
```
Starting from the inside, the ODBC escape sequence `{D '2019-06-30'}` returns a `datetime`.
(ignoring the redundant convert to `datetime`)
You're then converting that to a string with 102 style (rather than 105 for Italian).
You're then relying on an implicit conversion back to `datetime` to match the type of the target column.
The implicit conversion has a default style of 0 as you can see in the execution plan:
```none
[Expr1003] = Scalar Operator(CONVERT_IMPLICIT(datetime,CONVERT(varchar(30),[@1],102),0))
```
(note: you should always specify the maximum length when using `varchar`)
When you use style 102 `yyyy.mm.dd` you must also set `DATEFORMAT` to `YMD` so SQL Server can parse the format under style 0.
When you use style 105 `dd-mm-yyyy`, you must set `DATEFORMAT` to `DMY` for the same reason.
The reason it works on one and not the other is the default `DATEFORMAT` for the language in each case.
See [datetime][1], [`SET LANGUAGE`][2], and [Write International Transact-SQL Statements][3] in the documentation.
>Applications that use other APIs, or Transact-SQL scripts, stored procedures, and triggers should use the [CONVERT][4] statement with an explicit style parameter for all conversions between the **time**, **date**, **smalldate**, **datetime**, **datetime2**, and **datetimeoffset** data types and character string data types.
Also [SQL Server DateTime Best Practices][5] by Aaron Bertrand.
[1]: https://docs.microsoft.com/en-us/sql/t-sql/data-types/datetime-transact-sql#supported-string-literal-formats-for-datetime
[2]: https://docs.microsoft.com/en-us/sql/t-sql/statements/set-language-transact-sql
[3]: https://docs.microsoft.com/en-us/sql/relational-databases/collations/write-international-transact-sql-statements
[4]: https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql
[5]: https://www.mssqltips.com/sqlservertip/5206/sql-server-datetime-best-practices/