Passing a date from query to a column header - sql-server

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

Related

Table with date columns - conversion error with variables

I have a table called [Tails] that looks like this.
Duration January February ....
1 0.8782 0.735
2 37.22 0.678
3 0.544 0.47347
What I need to do is lookup values for a given month depending on circumstances. So far I have (for example):
DECLARE #monthX Date = '04-01-2016'
Select [Duration],
iif(.....,datename(month,#monthX),....)
From [Tails]
This should be the equivalent of
SELECT [Duration], [APRIL] FROM [TAILS]
But my code results in a conversion error message. I've tried a few different ways to convert the variable to work like this after searching online for a solution and am getting nowhere.
Please can anyone advise? I am using SQL Server 2014.
Thank you so much
You can create your query dynamically and then use EXECUTE to execute it :
DECLARE #monthX Datetime
DECLARE #monthS varchar(20)
SET #monthX = '04-01-2016'
SET #monthS = datename(month,#monthX)
DECLARE #SQL varchar(100)
SET #SQL = 'select [Duration], [' + #monthS + '] from [Tails];'
EXECUTE (#SQL)
You can not select columns like that, but you could construct a dynamic sql query and execute it with sp_executesql like so:
declare #monthX Date = '20160101';
declare #sql nvarchar(max);
set #sql = 'Select [Duration], '+quotename(datename(month,#monthx))+' From [Tails];';
select #sql as sql;
exec sp_executesql #sql;
The query executed for this example would be:
Select [Duration], [January] From [Tails];
rextester demo: http://rextester.com/KBAS15857
If you want the whole column summed... Use this (minus the temp data for testing)
DECLARE #date DATETIME
SET #date = '2/28/17'
DECLARE #monthname VARCHAR(20)
SET #monthname = DATENAME(month, #date)
DECLARE #strSQL varchar(100)
CREATE TABLE #tempTable(duration int, january NUMERIC(28,12), february NUMERIC(28,12))
INSERT INTO #temptable(duration, january, february)
VALUES(1 , 0.8782 ,0.735)
INSERT INTO #temptable(duration, january, february)
VALUES(2 , 37.22 ,0.678)
INSERT INTO #temptable(duration, january, february)
VALUES(3 , 0.544 ,0.47347)
SET #strSQL = 'select SUM(' + #monthname + ') from #tempTable;'
EXECUTE (#strSQL)
DROP TABLE #tempTable

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.

SQL Server EXEC backup table with date dynamically

I am looking to backup a table and auto add the date to the end of the table name.
Here is what I have
declare #table char(36)= 'template_fields'
EXEC('select * into '+#table+'_'+'convert(date, getdate()) from '+#table)
And I want the end result to look something like
template_fields_09-09-2015
What am I missing here?
Just print what you do:
DECLARE #table NVARCHAR(MAX) = 'tab';
DECLARE #sql NVARCHAR(MAX) = 'select * into '+#table+'_'
+'convert(date, getdate()) from '+#table;
SELECT #sql;
you will get: select * into tab_convert(date, getdate()) from tab
You need to pass date with table name like:
SqlFiddleDemo
DECLARE #table NVARCHAR(MAX) = 'tab';
DECLARE #new_table NVARCHAR(MAX) = #table + '_' +
CONVERT(NVARCHAR(100), GETDATE(),105);
DECLARE #sql NVARCHAR(MAX) = 'select * into ' + #new_table + ' from '+ #table;
SELECT #sql;
/* Result select * into tab_09-09-2015 from tab */
-- EXEC(#sql);
First of all, do not use EXEC to run dynamic queries, use sp_executesql instead.
Second: When you want to build a SQL query with variable object names, use QUOTENAME().
DECLARE #table sys.sysname = 'mytable'
DECLARE #backup sys.sysname = #table + '_' + CONVERT(date, GETDATE());
DECLARE #sql NVARCHAR(MAX) = 'SELECT * INTO '
+ QUOTENAME(#backup) + ' '
+ FROM + ' '
+ QUOTENAME(#table);
EXEC sp_executesql
#stmt = #sql
Please note that, the sys.sysname is a built in data type (essentially an alias for NVARCHAR(128) NOT NULL) and SQL Server uses it internally for object names.
Note: I have no SQL Server instance accessible right now, so the above query can contain typos.
I ended up resolving this myself. While some nice responses were added I wrote my initial query more simply to achieve this. Thank you all for the help.
--Declare and initiate the table
declare #table varchar(36)= 'template_fields'
--Declare and initiate the date (YYYYMMDD) without dashes
declare #date varchar(10) = convert(int, convert(varchar(10), getdate(), 112))
--Execute the query with the variables resulting in a new table titled 'template_fields_20150909'
EXEC('select * into '+#table+'_'+#date+' from '+#table)

convert varchar parameter to datetime in sql procedure

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)'

SELECT dynamic columns GROUP BY dynamic columns

I need to accomplish the following in the stored procedure:
Pass parameterized column names.
Select the parameterized column names and provide total group by selected columns.
Code:
CREATE PROCEDURE sproc (
#column1 NVARCHAR(MAX),
#column2 NVARCHAR(MAX),
#startdate DATE,
#enddate DATE ) AS
BEGIN
DECLARE #sqlquery NVARCHAR(MAX) = 'SELECT #column1, #column2, SUM(amountcolumn)
FROM tablename
WHERE column3 = ''#value3'',
datecolumn BETWEEN ''#startdate'' AND ''#enddate''
GROUP BY #column1, #column2';
DECLARE #params NVARCHAR(MAX) = '#column1 VARCHAR(MAX),
#column2 VARCHAR(MAX),
#startdate DATE,
#enddate DATE';
EXEC sp_sqlexec #sqlquery, #params,
#column1 = #column1,
#column2 = #column2,
#startdate = #startdate,
#enddate = #enddate;
END
GO
Assuming #value3 is a string and is another parameter to the stored procedure, that datecolumn is in fact date, and ignoring the fact that I have no idea how you can have a schema where the grouping fields can be random like this (which you ignored in other recent questions here):
DECLARE #sql nvarchar(max) = N'SELECT '
+ QUOTENAME(#column1) + ', '
+ QUOTENAME(#column2) + ', SUM(amountcolumn)
FROM dbo.tablename
WHERE column3 = #value3
AND datecolumn BETWEEN #startdate AND #enddate
GROUP BY ' + QUOTENAME(#column1)
+ ', ' + QUOTENAME(#column2) + ';';
EXEC sys.sp_executesql #sql,
N'#value3 varchar(255), #startdate date, #enddate date',
#value3, #startdate, #enddate;
-- strongly recommend against sp_sqlexec
-- it is undocumented and unsupported
This also assumes you don't care about order (you probably do and will want to add ORDER BY as well as GROUP BY).
For more info on dynamic SQL and even further ways to protect yourself from user input:
sqlblog.org/dynamic-sql

Resources