Inserting DateTime into datetime field TSQL - tsql

I'm trying to call a stored procedure in SQL Server 2012 Express from a C# program, to insert a DateTime data type into a column (which is also datetime).
For some reason, I keep getting errors about "Conversation failed when converting date and/or time from character string."
I've checked the culture settings in my SQL server, which is set to us_english, but the datetime format is the ISO standard.
Here's the code from the stored procedure. The values are exactly how they're passed by the C# app.
USE testdb;
DECLARE #Name NVARCHAR(50) = 'Somename',
#Location NVARCHAR(50) = 'somelocation',
#Date DateTime = '2013-10-11 11:00:05.000'
BEGIN
SET NOCOUNT ON;
SELECT #Name, #Location, #Date
if exists (select name from ComputerHistory where name = #Name)
begin
DECLARE #Query1 NVARCHAR(MAX)
if #Location <> 'disconnected'
begin
set #Query1 = '
update ComputerHistory
set ' + #Location + ' = 1 + ISNULL((select MAX(' + #Location + ') from ComputerHistory where name = ''' + #Name + '''),0),
lastdateonline = ''' + #Date + '''
where name = ''' + #Name + '''
'
--EXEC sp_executesql #Query1
end
else
begin
set #Query1 = '
update ComputerHistory
set ' + #Location + ' = 1 + ISNULL((select MAX(' + #Location + ') from ComputerHistory where name = ''' + #Name + '''),0)
where name = ''' + #Name + '''
'
EXEC sp_executesql #Query1
end
end
else
begin
DECLARE #Query2 NVARCHAR(150)
set #Query2 = 'insert into ComputerHistory(name, ' + #Location + ') VALUES(''' + #Name + ''', ''1'')'
EXEC sp_executesql #Query2
end
END

Try cast(#Date as nvarchar(50))
set #Query1 = '
update ComputerHistory
set ' + #Location + ' = 1 + ISNULL((select MAX(' + #Location + ') from ComputerHistory where name = ''' + #Name + '''),0),
lastdateonline = ''' + cast(#Date as nvarchar(50)) + '''
where name = ''' + #Name + '''
'

Related

Getting Error With GROUP BY when Converting Query to Dynamic SQL

I'm trying to convert the following query to dynamic SQL to allow for variations:
UPDATE T
SET SumCount = J.SUM
FROM #temp T
JOIN (SELECT Count_99221 + COUNT_99222 + Count_99223 [SUM], t2.userID
FROM #temp t2
GROUP BY t2.userID, Count_99221 + COUNT_99222 + Count_99223
) J ON T.userID = J.UserID
This is what I have for the Dynamic SQL:
DECLARE #sql3 nvarchar(2000) =
'UPDATE T ' +
'SET SumCount = J.SumOfColumns ' +
'FROM #temp T ' +
'JOIN (SELECT ' + #columnSumString + ' [SumOfColumns], t2.userID ' +
'FROM #temp t2 ' +
'GROUP BY t2.userID, ' + #columnSumString +
' ) J ON T.userID = J.UserID'
EXEC sp_executesql #sql3
I am receiving the following error only when I run the query as Dynamic SQL:
Each GROUP BY expression must contain at least one column that is not
an outer reference.
Can somebody help explain why this is happening? I am new to Dynamic SQL so I'm not privy to any limitations for running queries this way.
Thank you in advance.
EDIT:
The variable #columnString is a string made by concatenating several other column names, created in the following way:
DECLARE #Cursor Cursor
DECLARE #code varchar(20)
DECLARE #ID INT
SET #cptCursor = CURSOR FOR
SELECT * FROM dbo.Split(#UserInput,CHAR(44))
OPEN #cptCursor
FETCH NEXT FROM #cptCursor INTO #ID, #code
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #colName varchar(50) = 'Count_' + cast(#code as varchar(10))
DECLARE #sql nvarchar(50) = 'ALTER TABLE #temp ADD ' + #colName + ' int'
EXEC sp_executesql #sql
--Code that adds values to each column that is created.....
SET #columnSumString = #colName + ' + ' + #columnSumString
--SET #columnSumString = #code + ' + ' + #columnSumString
FETCH NEXT FROM #cptCursor INTO #ID, #code
END
CLOSE #Cursor
DEALLOCATE #Cursor
SET #columnSumString = SUBSTRING(#columnSumString,1,LEN(#columnSumString)-2)
SELECT #columnSumString
The user input is a comma separated string. "Count_99221 + COUNT_99222 + Count_99223" is just one example of columns created from the user input "99221, 99222, 99223".
I also realized I was concatenating the #code variable into #columnSumString instead of #colName. Now when I run the query I don't get the error (even though I don't understand how the above error message relates to that mistake) but every value of SumCount is NULL.
IMHO you must re-write your query as follow:
UPDATE #temp
SET SumCount =
(SELECT Count_99221 + COUNT_99222 + Count_99223
FROM #temp t2
WHERE t2.userID = #temp.userID)
So the dynamic SQL will become:
DECLARE #columnString varchar(200)
SET #columnString = Count_99221 + COUNT_99222 + Count_99223
DECLARE #sql3 nvarchar(2000) =
N'UPDATE #temp ' +
'SET SumCount = (SELECT ' + #columnString +
' FROM #temp t2 WHERE t2.userID = #temp.userID)'
EXEC sp_executesql #sql3

T-SQL AVG rounding a float result

I have a big stored procedure, with some nested cursors fetching some parameters dynamically. In this part I get the problem:
DECLARE #Avg_Dev float;
SET #sqlstatement = 'SELECT #Avg_Dev = AVG([' + #QLabel + '])
FROM Imported_Data
WHERE BrandID = ''' + CAST(#BrandID AS nvarchar(max)) + ''' AND CountryID = ''' + CAST(#CountryID AS nvarchar(max))
+ ''' AND [Year] = ''' + CAST(#Year AS nvarchar(max))
+ ''' AND ' + CAST(#QLabel AS nvarchar(max)) + ' <> ''' + CAST(#NoAnswer AS nvarchar(max)) + ''' ' + #Query;
EXEC sp_executesql #sqlstatement, N'#Avg_Dev float output', #Avg_Dev output;
PRINT 'AVG Check'; PRINT #Avg_Dev;
#BrandID and #CountryID are GUID, #Year is int, #QLabel is int and #Query is nvarchar(max). #NoAnswer contains a special value that has not to be considered.
#QLabel contains the column that I'm processing.
#Query contains a condition to apply to the where statement, and it's different for every #QLabel.
The problem is that #Avg_Dev always contains values rounded to the nearest integer, and I can't see why. #QLabel can be a value between 1 and 10.
I know this is not easy to read, but I didn't find any other way to process the table dynamically with every parameter changing often.
The problem here is that the column (QLabel) is defined as an integer. So an AVG() would return an integer (ignoring the decimals) and pushing that into your float variable. Try this:
SET #sqlstatement = 'SELECT #Avg_Dev = AVG(convert(float,[' + #QLabel + ']))
FROM Imported_Data
WHERE BrandID = ''' + CAST(#BrandID AS nvarchar(max)) + ''' AND CountryID = ''' + CAST(#CountryID AS nvarchar(max))
+ ''' AND [Year] = ''' + CAST(#Year AS nvarchar(max))
+ ''' AND ' + CAST(#QLabel AS nvarchar(max)) + ' <> ''' + CAST(#NoAnswer AS nvarchar(max)) + ''' ' + #Query;

Dynamic T-SQL error when converting data type varchar to bigint

I am getting the following error when I execute the below dynamic stored proc with
EXEC #return_value = [dbo].[proc_InsertEventDetails]
#EventID = 10254,
#EventDetType = 65,
#EventDetValue = 2,
#EventDetPriority = 0,
#CreatedBy = '4A47FE71-FC09-4E05-89E9-F68942BB9634'
Msg 8114, Level 16, State 1, Procedure proc_InsertEventDetails, Line 0
Error converting data type varchar to bigint.
I haved looked all over stackoverflow help is much appreatiated. thanks
CREATE PROCEDURE [dbo].[proc_InsertEventDetails]
(
#EventID bigint
,#EventDetType int
,#EventDetValue int
,#EventDetPriority int
,#CreatedBy uniqueidentifier
)
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = 'IF NOT EXISTS(SELECT EventID FROM Events.[dbo].[EventDetail]
WHERE EventID = ' + CONVERT(VARCHAR(50), #EventID) + '
AND EventDetType = ' + CONVERT(VARCHAR(50), ISNULL(#EventDetType, 0)) + '
AND EventDetValue = ' + CONVERT(VARCHAR(50), ISNULL(#EventDetValue, 0)) + '
AND EventDetActive = 1)
BEGIN
INSERT INTO xxx.[dbo]..[EventDetail]
(
[EventID]
,[EventDetType]
,[EventDetValue]
,[EventDetPriority]
,[EventDetActive]
,[EventDetSort]
,[CreatedBy]
,[CreatedDateTime]
,[UpdatedBy]
,[UpdatedDateTime]
)
VALUES
(
' + CONVERT(VARCHAR(50), #EventID) + '
,' + CONVERT(VARCHAR(50), ISNULL(#EventDetType, 0)) + '
,' + CONVERT(VARCHAR(50), ISNULL(#EventDetValue, 0)) + '
,' + CONVERT(VARCHAR(50), ISNULL(#EventDetPriority, 0)) + '
,1
,0
,''' + CONVERT(NVARCHAR(500), ISNULL(#CreatedBy, NULL)) + '''
,''' + CONVERT(NVARCHAR(50), GETDATE()) + '''
,''' + NULL + '''
,''' + NULL + '''
)
END'
EXECUTE( #SQL )
END

Stored proc to get list of tables and stored procs using those tables from all databases

A single stored proc which do the following work: when I pass a column name, I should get a list of all the tables containing that column, and a list of all stored procedures that are using those tables from all databases
DECLARE #rolename AS VARCHAR(200) = 'testx_table'
DECLARE #string1 VARCHAR(2000) = '',
#string2 VARCHAR(2000) = '',
#string3 VARCHAR(2000) = '',
#string4 VARCHAR(2000) = ''
IF #rolename = 'testx_table'
GOTO table_op
IF #rolename = 'testx_proc'
GOTO proc_op
TABLE_OP:
BEGIN
DECLARE #catalog VARCHAR(500),
#schema VARCHAR(50),
#tablename VARCHAR(500),
#tabletype VARCHAR(50)
DECLARE crs_tables CURSOR FOR
SELECT table_catalog,
table_schema,
table_name,
table_type
FROM [INFORMATION_SCHEMA].tables
WHERE table_schema = 'DBO'
OPEN crs_tables
FETCH next FROM crs_tables INTO #catalog, #schema, #tablename,
#tabletype
SELECT #catalog = table_catalog,
#schema = table_schema,
#tablename = table_name,
#tabletype = table_type
FROM [INFORMATION_SCHEMA].tables
WHERE table_schema = 'DBO'
AND #catalog = table_catalog
AND #schema = table_schema
AND #tablename = table_name
AND #tabletype = table_type
SET #string1 = 'GRANT INSERT ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
SET #string2 = 'GRANT DELETE ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
SET #string3 = 'GRANT UPDATE ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
SET #string4 = 'GRANT SELECT ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
EXEC(#string1)
EXEC(#string2)
EXEC(#string3)
EXEC(#string4)
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #catalog = table_catalog,
#schema = table_schema,
#tablename = table_name,
#tabletype = table_type
FROM [INFORMATION_SCHEMA].tables
WHERE table_schema = 'DBO'
AND #catalog = table_catalog
AND #schema = table_schema
AND #tablename = table_name
AND #tabletype = table_type
FETCH next FROM crs_tables INTO #catalog, #schema, #tablename,
#tabletype
SET #string1 = 'GRANT INSERT ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
SET #string2 = 'GRANT DELETE ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
SET #string3 = 'GRANT UPDATE ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
SET #string4 = 'GRANT SELECT ON ' + '[dbo]' + '.' + #tablename
+ ' TO ' + #rolename
EXEC(#string1)
EXEC(#string2)
EXEC(#string3)
EXEC(#string4)
END
CLOSE crs_tables
DEALLOCATE crs_tables
GOTO EXIT
END
/* */
PROC_OP:
BEGIN
DECLARE #p_catalog VARCHAR(500),
#p_schema VARCHAR(50),
#p_name VARCHAR(500),
#p_type VARCHAR(50),
#xtype VARCHAR(50)
DECLARE crs_routines CURSOR FOR
SELECT r.specific_catalog,
r.specific_schema,
r.specific_name,
r.routine_type,
s.xtype
FROM [INFORMATION_SCHEMA].routines r
INNER JOIN sysobjects s
ON s.NAME = r.specific_name
--and s.xtype = 'FN'
WHERE r.specific_schema = 'DBO'
OPEN crs_routines
FETCH next FROM crs_routines INTO #p_catalog, #p_schema, #p_name,
#p_type,
#xtype
SELECT #p_catalog = r.specific_catalog,
#p_schema = r.specific_schema,
#p_name = r.specific_name,
#p_type = r.routine_type,
#xtype = s.xtype
FROM [INFORMATION_SCHEMA].routines r
INNER JOIN sysobjects s
ON s.NAME = r.specific_name
--and s.xtype = 'FN'
WHERE r.specific_schema = 'DBO'
AND #p_catalog = r.specific_catalog
AND #p_schema = r.specific_schema
AND #p_name = r.routine_name
AND #p_type = r.routine_type
SET #string1 = 'GRANT ' + CASE WHEN #p_type = 'PROCEDURE' OR #xtype =
'FN'
THEN ' EXECUTE '
ELSE ' SELECT' END + ' ON ' + '[dbo]' + '.' + '[' +
#p_name +
']'
+ ' TO ' + #rolename
SET #string2 = 'GRANT ' + ' VIEW DEFINITION ' + ' ON ' + '[dbo]'
+ '.' + '[' + #p_name + ']' + ' TO ' + #rolename
PRINT #string1 + ' / ' + #p_type
EXEC(#string1)
EXEC(#string2)
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #p_catalog = r.specific_catalog,
#p_schema = r.specific_schema,
#p_name = r.specific_name,
#p_type = r.routine_type,
#xtype = s.xtype
FROM [INFORMATION_SCHEMA].routines r
INNER JOIN sysobjects s
ON s.NAME = r.specific_name
--and s.xtype = 'FN'
WHERE r.specific_schema = 'DBO'
AND #p_catalog = r.specific_catalog
AND #p_schema = r.specific_schema
AND #p_name = r.routine_name
AND #p_type = r.routine_type
FETCH next FROM crs_routines INTO #p_catalog, #p_schema, #p_name
,
#p_type,
#xtype
SET #string1 = 'GRANT ' + CASE WHEN #p_type = 'PROCEDURE' OR
#xtype =
'FN'
THEN ' EXECUTE '
ELSE ' SELECT' END + ' ON ' + '[dbo]' + '.' + '['
+
#p_name
+
']'
+ ' TO ' + #rolename
SET #string2 = 'GRANT ' + ' VIEW DEFINITION ' + ' ON ' + '[dbo]'
+ '.' + '[' + #p_name + ']' + ' TO ' + #rolename
PRINT #string1 + ' / ' + #p_type
PRINT #string2 + ' / ' + #p_type
EXEC(#string1)
EXEC(#string2)
END
CLOSE crs_routines
DEALLOCATE crs_routines
GOTO EXIT
END

How to add variables in Dynamic Sql, not concatenate them?

I have the following dynamic sql statement where I want to add #StartRowIndex + #MaximumRows and subtract 1 from it. I am unclear on where to put the single quotes in the statement. Here it is:
SET #sql = #sql + ' SELECT *
FROM
LicenseInfo
WHERE RowNum
BETWEEN ' + #StartRowIndex + ' AND ' +
'(' + #StartRowIndex + #MaximumRows + ')' - 1
+ ' ORDER BY cnt desc'
Create new variable #EndRowIndex and calculate it before you construct the dynamic sql statement.
Something like:
DECLARE #EndRowIndex int
SET #EndRowIndex = #StartRowIndex + #MaximumRows - 1
SET #sql = #sql + ' SELECT *
FROM
LicenseInfo
WHERE RowNum
BETWEEN ' + #StartRowIndex + ' AND ' + #EndRowIndex
+ ' ORDER BY cnt desc'
You need to cast the int parameters into varchar
SET #sql = #sql + ' SELECT *
FROM
LicenseInfo
WHERE RowNum
BETWEEN ' + #StartRowIndex + ' AND ' +
'(' + CAST(#StartRowIndex as varchar(10)) + CAST(#MaximumRows as varchar(10)) + ') - 1
ORDER BY cnt desc'
Declare a variable, do the calculation and CAST it to varchar when generating the SQL statement
DECLARE #LastRowIndex int
SET #LastRowIndex = #StartRowIndex + #MaximumRows - 1
SET #sql = #sql + '
SELECT *
FROM LicenseInfo
WHERE 1=1
AND RowNum BETWEEN ' + CAST (#StartRowIndex as VarChar) +
' AND ' + CAST (#LastRowIndex as VarChar)
+ ' ORDER BY cnt DESC'
You have to cast in order to let SQL Server concatenate string values, otherwise it will try to convert the nVarChar to number and try to add them as numerics.