convert varchar parameter to datetime in sql procedure - sql-server

Below is my procedure
create proc abc -- 'all','18','18','12/12/2015','','','inactive'
#JoinedDate varchar(100),
#LastLogin varchar(100),
#Location varchar(100),
#Status varchar(50)
as
declare #WhereCondition varchar(1000)
set #WhereCondition=' '
if #LastLogin !=''
set #WhereCondition= ' and u.UpdatedDate>=' + CAST(#LastLogin as datetime)
exec('select * from tableName where' + #WhereCondition)
When I am passing the parameter LastLogin it is giving me error as below:
Conversion failed when converting date and/or time from character string.

First of all capture the data in correct data type, If you are expecting a datetime value use the datetime data type for your variable.
Dont get values in varchar and then try to convert them to datetime(poor practice) , Also use parameterised dynamic sql do not concatenate variables into your dynamic sql (open doors for sql injection).
see below:
create proc abc -- 'all','18','18','12/12/2015','','','inactive'
#JoinedDate datetime,
#LastLogin datetime,
#Location varchar(100),
#Status varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'select * from tableName where 1 = 1 '
+ CASE WHEN #LastLogin <> ''
THEN N' AND UpdatedDate >= #LastLogin' ELSE N'' END
Exec sp_executesql #Sql
,N'#LastLogin datetime'
,#LastLogin
END

You can't concatenate a Datetime datatype with a string.
EDITED:
Try this:
set #WhereCondition= ' and u.UpdatedDate>=CAST(''' + #LastLogin + ''' AS datetime)'

I got the solution, it is possible to pass datetime as varchar paramter to dynamic sql and convert it to datetime dynamically-
Below is the way -
set #WhereCondition= ' and u.UpdatedDate>=convert(datetime,''' + #LastLogin + ''', 110)'

Related

Passing a date from query to a column header

I am working on a COVID database and I want to use part of the date from the Last_Update column of an import file, and use that as an alias for a column in that same file.
Here is an example of the import file:
FIPS County Province_State Country_Region Last_Update Lat Long Confirmed Deaths Recovered Active
45001 Abbeville South Carolina US 2020-05-30 02:32:48.00 34.22333378-82.46170658 39 0 0 39
22001 Acadia Louisiana US 2020-05-30 02:32:48.00 30.2950649 -92.41419698 401 23 0 378
51001 Accomack Virginia US 2020-05-30 02:32:48.00 37.76707161-75.63234615 7 12 0 815
Here is the expected result:
Province_State Country_Region 05-30
--------------------------------------
Abruzzo Italy 3237
Acre Brazil 5841
Aguascalientes Mexico 797
Aichi Japan 506
The Last_Update date column imports as 2020-05-30 02:32:48.0000000 and I have used the following code to extract the shortened date format for the new column header to read 05-30
DECLARE #ColumnName VARCHAR (50)
DECLARE #Date VARCHAR (50)
DECLARE #Query AS NVARCHAR (MAX)
SET #ColumnName = (SELECT TOP 1[Last_Update] FROM [DailyImport5.30.20])
SET #Date = SUBSTRING (#ColumnName,6,6)
PRINT #Date
Next I have tried to pass the variable of #Date to the new column header with no luck so far:
DECLARE #ColumnA nvarchar(max),
#ColumnB nvarchar(max),
#ColumnC nvarchar(max),
#ColumnName VARCHAR (50),
#Date VARCHAR (50),
#table nvarchar(max),
#sql nvarchar(max)
SET #table = 'DailyImport5.30.20'
SET #ColumnName ='(SELECT TOP 1[Last_Update] FROM [COVIDResearch].[dbo].[DailyImport5.30.20])'
SET #Date = 'SUBSTRING (#ColumnName,6,6)'
SELECT
#ColumnA = N'Province_State',
#ColumnB = N'Salary',
#ColumnC = N'#Date',
#table = N'[COVIDResearch].[dbo].[DailyImport5.30.20]'
SELECT #sql = N'SELECT ' +(#ColumnA)+','+(#ColumnB)+','+(#ColumnC)+ ' FROM '+(#table) +';'
EXEC sp_executesql #sql
I get this error:
Must declare the scalar variable "#Date".
I have also tried PIVOT but not been able to find how to read the date, trim it down, and then perform a pivot for all the results in the table. Not just a specified set of results.
Any advice is greatly appreciated!
Alex gave me the final push to solve this issue. Here is my final code to extract the date from the import file, shorten it to just the month and day, then insert it as the column header for use in a new table.
DECLARE #ColumnA nvarchar(max),
#ColumnB nvarchar(max),
#ColumnC nvarchar(max),
#ColumnName VARCHAR (50),
#Date VARCHAR (50),
#table nvarchar(max),
#sql nvarchar(max)
SET #table = 'DailyImport5.30.20'
SET #ColumnName =(SELECT TOP 1[Last_Update] FROM [COVIDResearch].[dbo].[DailyImport5.30.20])
SET #Date = SUBSTRING (#ColumnName,6,6)
SELECT #ColumnA = N'Province_State',
#ColumnB = N'Country_Region',
#ColumnC = 'Confirmed AS [' + #Date + ']',
#table = N'[COVIDResearch].[dbo].[DailyImport5.30.20]'
SELECT #sql = N'SELECT ' +(#ColumnA)+','+(#ColumnB)+','+(#ColumnC)+ ' FROM '+(#table) +';'
EXEC sp_executesql #sql
Thanks for your help!
If you "print" your query (via PRINT #sql) and copy the text to a new query window you will find that it has a syntax error near #Date column name. Variable names are not allowed as column names.
You need to give an alias to an existing data column. What you want to do is something along these lines:
.... Omitted for brevity
SELECT
#ColumnA = N'Province_State',
#ColumnB = N'Salary',
-- You need to give an alias to an existing column in [DailyImport5.30.20] table
-- Note: square brackets to avoid invalid identifiers, i.e. you assign value of #Date to #ColumnC.
#ColumnC = 'Confirmed AS [' + #Date + ']',
#table = N'[COVIDResearch].[dbo].[DailyImport5.30.20]'
SELECT #sql = N'SELECT ' +(#ColumnA)+','+(#ColumnB)+','+(#ColumnC)+ ' FROM '+(#table) +';'
EXEC sp_executesql #sql

Call a Stored Procedure or Function from Dynamic SQL - with Nullable Parameter

I am trying to call an sql function accepting a nullable parameter - from a dynamic SQL statement.
Creating the dynamic statement is difficult because when the parameter value is 'NULL' the concatentation causes the whole statement to be empty. I have the following:
SET dynamicQuery =
'select * from [qlik].udf_getStatistic( ''' + #myParameter + ''' )'
The sample above is inside a stored procedure to which #myParameter is passed. It may be null, or a string value. Clearly, when it is a string it needs to be enclosed in quotes, but when it is null it must not be enclosed in quotes. As follows:
select * from [qlik].udf_getStatistic( 'Heights' )
select * from [qlik].udf_getStatistic( NULL )
The question is equally applicable to calling a stored procedure accepting a nullable parameter from dynamic SQL.
The examples are from SQL Server.
Just escape the NULL value with an explicit literal NULL, making sure that the quotes are only included when the value is not NULL.
DECLARE #myParameter VARCHAR(10) = 'ABC'
DECLARE #dynamicQuery VARCHAR(MAX)
SET #dynamicQuery =
'select * from [qlik].udf_getStatistic(' + ISNULL('''' + #myParameter + '''', 'NULL') + ')'
SELECT #dynamicQuery -- select * from [qlik].udf_getStatistic('ABC')
SET #myParameter = NULL
SET #dynamicQuery =
'select * from [qlik].udf_getStatistic(' + ISNULL('''' + #myParameter + '''', 'NULL') + ')'
SELECT #dynamicQuery -- select * from [qlik].udf_getStatistic(NULL)
You might want to escape additional single quotes that might be on your variable, replacing them with double single quotes, so it doesn't break your dynamic build.
The answer is actually different between stored procedures and functions.
From Books On Line or whatever they call it this month (Scroll down a ways):
When a parameter of the function has a default value, the keyword DEFAULT must be specified when the function is called to retrieve the default value. This behavior is different from using parameters with default values in stored procedures in which omitting the parameter also implies the default value. However, the DEFAULT keyword is not required when invoking a scalar function by using the EXECUTE statement.
So for a proc, when you want to pass a NULL parameter, you can just not pass it. For a function, though, you have to tell it to use the DEFAULT value explicitly. Either way, you do not pass it an explicit NULL. Luckily for your dynamic SQL, though, the explicit DEFAULT also works with a stored procedure. In both cases, in order to make sure that the parameters you are passing get assigned correctly, you want to use explicit parameter names in your call.
Let's use this function definition:
CREATE FUNCTION (or procedure) [qlik].udf_getStatistic (
#param1 integer = 0,
#param2 varchar(100) = 'foo'
) AS ...
Both parameters are optional. Since this is a function, this call will throw an insufficient number of parameters error:
select * from [qlik].udf_getStatistic( 'Heights' );
If it were a procedure call, it would throw a cannot convert value 'Heights' to data type integer because it will apply the only parameter value passed to the first parameter it encounters, which is expecting an integer. In both cases, you get what you want this way:
select * from [qlik].udf_getStatistic( #param1 = DEFAULT, #param2 = 'Heights' );
Which brings us to your dynamic SQL. Add your parameter name(s) to the static text, then use COALESCE (or CASE if you like) to decide whether to pass an explicit value, or the DEFAULT call.
DECLARE #myParameter1 VARCHAR(100) = 'foo',
#myParameter2 INTEGER,
#SQL NVARCHAR(MAX);
SET #SQL =
'select
*
from [qlik].udf_getStatistic(
#param1 = ''' + COALESCE(#myParameter1, 'DEFAULT') + ''',
#param2 = ' + COALESCE(CAST(#myParameter2 AS VARCHAR(30)),'DEFAULT') + ' );';
SELECT #SQL;
Result:
select * from [qlik].udf_getStatistic( #param1 = 'foo', #param2 = DEFAULT );
From my understanding, I try this on SQL Server 2012,
CREATE PROCEDURE ToNullProc
(#i VARCHAR(20))
AS
BEGIN
PRINT 'you entered ' + #i
END
CREATE FUNCTION ToNullFun
(#i VARCHAR(20))
RETURNS #table TABLE (i VARCHAR(20))
AS
BEGIN
INSERT INTO #table
SELECT ('You entered ' + #i) a
RETURN
END
DECLARE #j VARCHAR(20) = 'Hi',
#QueryFun NVARCHAR(50) = N'',
#QueryProd NVARCHAR(50) = N''
IF #j IS NOT NULL
BEGIN
SET #QueryFun = N'select * from ToNullFun ('''+#j+''')'
SET #QueryProd = N'exec ToNullProc '''+#j+''''
END
ELSE BEGIN
SET #QueryFun = N'select * from ToNullFun ('+#j+')'
SET #QueryProd = N'exec ToNullProc '+#j+''
END
PRINT #queryfun
PRINT #queryprod
EXEC sp_executesql #queryfun
EXEC sp_executesql #queryprod
update for dynamic procedure and dynamic function :
create table #temp (Num int identity (1,1), NullVal int)
insert into #temp (NullVal) values (1),(null),(3)
alter proc ToNullProc (
#Operator varchar (max), #NullVal varchar (max)
) as
begin
declare #Query nvarchar (max) = N'select * from #temp where NullVal ' +
#Operator + #NullVal
-- print #query + ' ToNullProc print '
exec sp_executesql #query -- Here we run the select query from Proc
end
create function ToNullFun (
#Operator varchar (max), #NullVal varchar (max)
)
returns nvarchar (max)
as
begin
declare #Query nvarchar (max)
set #Query = N'select * from #temp where NullVal ' + #Operator + #NullVal
/*
I try to into to Table variable by using ITVF,
'insert into #table exec sp_executesql #query'.
But this type of insert is not allowed in ITVF.
*/
return #query
end
declare #NullVal varchar (max) = '1'
, #QueryFun nvarchar (max) = N''
, #QueryProd nvarchar (max) = N''
declare #FunResultTalbe table (
Query nvarchar (100)
) /* To store the result Funtion */
if #NullVal is not null
begin
set #QueryFun = N'select dbo.ToNullFun ('' = '','''+#NullVal+''')'
set #QueryProd = N'exec ToNullProc '' = '','''+#NullVal+''''
end
else begin
set #QueryFun = N'select dbo.ToNullFun ('' is null '','''')'
set #QueryProd = N'exec ToNullProc '' is null '','''''
end
print #queryfun + ' At start'
print #queryprod + ' At start'
exec sp_executesql #queryprod -- It calls Proc
insert into #FunResultTalbe
exec sp_executesql #queryfun -- It calls the Function and insert the query into the table.
set #QueryFun = (select top 1 * from #FunResultTalbe) -- Here we get the query from the table.
print #queryfun
exec sp_executesql #queryfun -- Here we run the select query. Which is dynamic
Result sets
-- Result of Procedure
Num NullVal
1 1
-- Result of Function
Num NullVal
1 1
Let me know, what did you got.

SQL Parameterised column names

I am trying to create a parameterised query for retrieving data back from a table
Essentially I have a table structure of
ID
nvarchar1
ntext
datetime1
datetime2
and I am trying to do a query like so that it selects all the data where the current date is greater than datetime1 and less than datetime2
SELECT
ID, nvarchar1,
ntext,
datetime1,
datetime2
FROM
TABLEName
WHERE
datetime1 >= #CurrentDate
AND datetime2 <= #CurrentDate
I want to make the columns parameters such as
#TableName, #CurrentDate, #StartDate, #EndDate
DECLARE #TableName NVARCHAR(100);
SET #TableName = '[Surveys].[dbo].[Table]'
DECLARE #CurrentDate DateTime;
SET #CurrentDate = GETDATE();
DECLARE #StartDate NVARCHAR(100);
SET #StartDate = 'datetime1'
DECLARE #EndDate NVARCHAR(100);
SET #EndDate = 'datetime2'
DECLARE #sql nvarchar(1000)
SET #sql = 'SELECT * FROM ' + #TableName + 'WHERE' + #EndDate + '>=' + #CurrentDate + 'AND' + #StartDatedatetime1 + '<=' + #CurrentDate
EXEC(#sql)
The data is going to be coming from a SP data source so I have no control of the column names etc. and when I create the SP Lists they automatically assign to a table column of that type so this is why I need to columns to be parameters.
Using the above code which I thought should work returns
Msg 241, Level 16, State 1, Line 14
Conversion failed when converting date and/or time from character string.
What am I doing wrong?
Try the below. As #GordonLinoff stated, you where missing the single quotes (') from around the #CurrentDate variable. Also, you where passing a DATETIME parameter in to the #sql variable which is an NVARCHAR data type. These are not implicitly converted, so the #CurrentDate variable needs to be converted to a NVARCHAR first:
DECLARE #sql nvarchar(1000)
SET #sql = 'SELECT * FROM ' + #TableName
+ ' WHERE ' + #EndDate + ' >= ''' + CONVERT(NVARCHAR(50), #CurrentDate,120)
+ ''' AND ' + #StartDate + ' <= ''' + CONVERT(NVARCHAR(50), #CurrentDate,120) + ''''
EXEC(#sql)
You are pretty close. I would construct the SQL for the table and then use parameters for the current date: This would be something like this:
SET #sql = '
SELECT *
FROM #TableName
WHERE datetime2 >= #CurrentDate AND datetime1 <= #CurrentDate';
SET #sql = REPLACE(#sql, '#TableName', #TableName);
exec sp_executesql #sql, N'#CurrentDate date', #CurrentDate = #CurrentDate;
Incidentally, the problem with your query is the lack of single quotes around the date constants.
EDIT:
You cannot substitute column or table names using parameters. I would write the code as:
SET #sql = '
SELECT *
FROM #TableName
WHERE #datetime2 >= #CurrentDate AND #datetime1 <= #CurrentDate';
SET #sql = REPLACE(#sql, '#TableName', #TableName);
SET #sql = REPLACE(#sql, '#datetime1', #DateTime1);
SET #sql = REPLACE(#sql, '#datetime2', '#DateTime2);
. . .
I use REPLACE() for this type of operation because the code is easier to understand and to maintain.

Passing multiple values into a one parameter in SQL Server 2008 using a stored procedure

alter PROCEDURE [dbo].[DisplayFinancialColumn]
(
#sectorid smallint
)
AS
BEGIN
SET NOCOUNT ON;
declare #sectorid_vc varchar(5)
set #sectorid_vc = REPLACE(#sectorid,',',''',''')
DECLARE #listStr varchar(MAX) = (select [SectorFinancialType_Desc] + ',' from SectorFinancialTypes where CONVERT(varchar(300), SectorFinancialType_ID) in (#sectorid_vc) for xml path(''))
DECLARE #query varchar(MAX) = 'SELECT ' + LEFT(#listStr, LEN(#listStr)-1) + ' FROM [dbo].[Financials] where project_id = ''1096'' '
execute(#query)
END
GO
But I encounter
Error converting data type varchar to smallint.
But I have converted the smallint to varchar format, so why there is still such an error?
The Problem is the first line of code in your procedure:
SET #sectorid = REPLACE(#sectorid,',',''',''')
will not convert #sectorid to varchar! You define #sectorid as SMALLINT parameter so #sectorid will never become a varchar variable. Change the type of your parameter or do something like that in your procedure instead:
declare #sectorid_vc nvarchar(5)
set #sectorid_vc = REPLACE(#sectorid,',',''',''')
this will do the trick i think.
set your query like below: Here you have change #sectorid to VARCHAR(MAX)
ALTER PROCEDURE [dbo].[DisplayFinancialColumn]
(
#sectorid VARCHAR(MAX)
)
AS
BEGIN
//write your procedure code here
END
GO
let me know, is this works for you ?
Try this to convert:
REPLACE(CONVERT(VARCHAR(MAX),#sectorID),',',''',''')

SQL, Assign Select Column to Variable

I am using SQL Server 2012, I am going to Create Store Procedure which copies a column from a table in a variable, Could any one please tell me what is Wrong with this code?
alter Procedure Id_Fetch
#Col varchar(50)=null,
#Table VARCHAR(50)=Null,
#OrdrBy Varchar(40)=null
as
Begin
declare #TempCol nvarchar (100)
Exec(' SELECT '+#TempCol+' = '+#Col+' from ' + #Table +' order by '+#OrdrBy )
its showing error "Incorrect Syntax near '='
A little modification ...... Use TOP 1 in your select as if more than one value is returned by your select it will throw an error.
Use SYSNAME datatype for your Column names and table names.
Use QUOTENAME() function around your object name parameters, which puts square brackets [] around the passed parameter value and forces it to be treated as an object name (Protection against Sql Injection attack).
Use sp_executesql instead of EXEC and concatenating parameter values into string and executing again protects you against Sql Injection attack.
ALTER PROCEDURE Id_Fetch
#Col SYSNAME,
#Table SYSNAME,
#OrdrBy SYSNAME,
#Col_Value NVARCHAR(100) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N' SELECT TOP 1 #Col_Value = ' + QUOTENAME(#Col)
+ N' FROM ' + QUOTENAME(#Table)
+ N' ORDER BY ' + QUOTENAME(#OrdrBy)
EXECUTE sp_executesql #Sql
,N'#Col_Value NVARCHAR(100) OUTPUT'
,#Col_Value OUTPUT
END

Resources