When I ran the below query in MS SQL Server 2019, it returned the correct date value:
SELECT CONVERT(DATETIME,'13/12/2019',103)
Output:
2019-12-13 00:00:00.000
But when I ran the below code block with the same query, I am not getting correct date value in the output. I am getting a 19th century date value.
DECLARE @BEFOREDATE varchar(30)
DECLARE @SqlStatment VARCHAR(1000)
BEGIN
SET @BEFOREDATE = '13/12/2019'
SET @SqlStatment = 'select CONVERT(DATETIME,' + @BEFOREDATE + ',103)'
EXECUTE( @SqlStatment )
END
Output:
1900-01-01 00:00:00.000
Please help to resolve this issue.
The problem is injection, and bad injection at that. The best way to debug "dynamic" SQL is to PRINT
/SELECT
the dynamic statement. If we do that, we get the following:
select CONVERT(DATETIME,01/03/2023,103)
So, this means you want to convert the integer
expression 01/03/2023
to a datetime
, so that's 1/3/2023
->0/2023
->0
, and 0
as a datetime
is 1900-01-01
.
Coincidentally, if you used date
, which it appears you should be using, you would have got a "better" error that would have likely pointed you to the real problem:
Explicit conversion from data type int to date is not allowed.
As I stated though, the problem is injection, you should be parametrising the value. You can't do that with EXEC(<Variable>)
syntax, and I actually stronly recommend against its use because of that; it promotes injection because it can't be parametrised. Instead use sys.sp_executesql
and pass the variable to it as a parameter:
DECLARE @BeforeDate varchar(30);
DECLARE @SqlStatement nvarchar(MAX); --varchar is not a valid datatype for `sys.sp_exutesql`.
SET @BEFOREDATE = '01/03/2023';
SET @SqlStatement = 'SELECT CONVERT(datetime,@BeforeDate,103);';
EXEC sys.sp_executesql @SqlStatement, N'@BEFOREDATE varchar(30)', @BEFOREDATE;
Of course, this makes the whole "dynamic" statement pointless, as it's no longer dynamic.