TSQL Passing a varchar variable of column name to SUM function - sql-server

I need to write a procedure where I have to sum an unknown column name.
The only information I have access to is the column position.
I am able to get the column name using the following:
SELECT #colName = (SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='TABLENAME' AND ORDINAL_POSITION=#colNum)
I then have the following:
SELECT #sum = (SELECT SUM(#colName) FROM TABLENAME)
I then receive the following error:
Operand data type varchar is invalid for sum operator
I am confused about how to make this work. I have seen many posts on convert and cast, but I cannot cast to an float, numeric, etc because this is a name.
I would appreciate any help.
Thank you

This is not possible. You will have to assemble the SQL query and then execute it. Something like this:
SET #sqlquery = 'SELECT SUM(' + #colName + ') FROM TABLENAME'
EXECUTE ( #sqlquery )
Adjust accordingly.

Related

Passing Int to dynamic stored procedure fails

I have a dynamic stored procedure in SQL Server that works well to pivot a table:
CREATE PROCEDURE dbo.DynamicPivotTableInSql
#ColumnToPivot NVARCHAR(255),
#ListToPivot NVARCHAR(255),
#SurveyID INT=10
AS
BEGIN
DECLARE #SqlStatement NVARCHAR(MAX)
SET #SqlStatement = N'SELECT *
FROM
(SELECT
[resp_id], [benefit], [weight]
FROM Segment_Responses) myResults
PIVOT
(SUM([weight])
FOR [' + #ColumnToPivot + ']
IN (' + #ListToPivot + ')) AS PivotTable';
EXEC (#SqlStatement)
END
and I call it like this
EXEC DynamicPivotTableInSql
#ColumnToPivot = 'benefit',
#ListToPivot = '[OBSERVABILITY], [COST], [EASE OF USE], [SERVICE]'
Here is where I run into problems. You'll notice I have hardcoded #SurveyID = 10 and if I try to add that as a where statement in the stored procedure like this:
FROM Segment_Responses
WHERE survey_id = ' + #SurveyID + '
and run the stored procedure again I get this error:
Conversion failed when converting the nvarchar value '
SELECT * FROM (
SELECT
[resp_id],
[benefit],
[weight]
FROM Segment_Responses where survey_id=' to data type int.
I've tried to solve this many ways (e.g., passed the Int variable instead of hard coding it) but always get the same result. Any ideas what is going on?
Just to try to add some clarity, when you add together two different types, SQL Server will (where it can) implicitly convert one to the other - the result must be a single type after all.
It decides which one to convert "to the other" based on an order of precedence.
So where you are trying to concatenate a varchar with an int, the int has the higher order of precedence. This is also a common cause of errors and bugs when using a case expression when mixing types in different execution paths of the expression.
You need to be explicit and cast the int to a varchar.
Ideally you would use a parameterised query which would also reuse the cached execution plan - this may be beneficial if the cardinality of the data is similar but sometimes making the value part of the query dynamically can be advantagous, it depends on the use-case.
This is why the syntax EXEC (#SQL) is strongly suggested against. Use sys.sp_executesql and parametrise your statement:
SET #SQL = N'SELECT ...
FROM ...
WHERE survey_id = #SurveyID ...;';
EXEC sys.sp_executesql #SQL, N'#SurveyID int',SurveyID;
The + only works with strings. If you use a number TSQL assumes you are trying to use the addition operator, and tries to convert the string argument to int.
eg this
select 1 + '2'
works and returns 3.
Use CONCAT instead of +, or use an explicit conversion on the int.
eg
WHERE survey_id = ' + cast(#SurveyID as varchar(20)) + '

Cannot pass string to IN clause in stored procedure

I have the following stored procedure that takes one parameter and I need to use that in my IN clause, but that does not work. I get this error when trying.
Conversion failed when converting the varchar value '1,2' to data type int
Here is my stored procedure..
CREATE PROCEDURE [dbo].[p_GetSegment]
#SegmentIds nVarChar(20)
AS
BEGIN
SET NOCOUNT ON;
SELECT dbo.Segment.Name
FROM dbo.tbl_Category
INNER JOIN dbo.Segment ON dbo.tbl_Category.SegmentId
WHERE (dbo.Segment.Id IN (#SegmentIds))
I pass in "1,2". How can I make this work?
In SQL Server 2016+, you can use string_split():
WHERE dbo.Segment.Id IN (SELECT value FROM STRING_SPLIT(#SegmentIds, ','))
You can use any string split function for this purpose. You can also just use `like:
where ',' + #SegmentIds + ',' like '%,' + convert(varchar(255), dbo.Segment.Id) + ',%'

SQL Server binary value in dynamic sql

I need binary value in dynamic SQL but I am getting an error
The data types nvarchar and binary are incompatible in the add operator
I need help.
DECLARE #MaxSeqValue binary(10)=NULL
DECLARE #script varchar(max)
-- I have incremental binary values in my table,which I can sort it.
SELECT
#MaxSeqValue = MAX(seqvalue)
FROM [dbr].[DBA_CDClog]-- this my log table
WHERE TableName = #TableName2
set #script = 'Select seq value, tablename
from table X
where SeqValue >'+#MaxSeqValue+'
'
You have to cast #MaxSeqValue to nvarchar.
set #script ='
Select seq value,
tablename
from table X
where SeqValue >' + cast(#MaxSeqValue as nvarchar(max))
This answer is worked for me. CAST option didnt workout.
WHERE SeqValue >0x'+CONVERT(nvarchar(max),#MaxSeqValue,2)+'

Converting nvarchar to numeric

I have variable called #prmclientcode which is nvarchar. The input to this variable can be a single client code or multiple client codes separated by comma. For e.g.
#prmclientcode='1'
or
#prmclientcode='1,2,3'.
I am comparing this variable to a client code column in of the tables. The data type of this column is numeric(6,0). I tried converting the variable data type like below
SNCA_CLIENT_CODE IN ('''+convert(numeric(6,0),#prmclientcode+''')) (The query is inside a dynamic sql).
But when I try executing this I get the error
Arithmetic overflow error converting nvarchar to data type numeric.
Can anyone please help me here!
Thanks!
You need to convert the numeric(6,0) column to nvarchar data type. You can use below scrip to convert it to nvarchar, before processing:
SNCA_CLIENT_CODE IN ('''+convert(cast( numeric(6,0) as nvarchar(max) ),#prmclientcode+'''))
Please try with the below code snippet.
DECLARE #ProductTotals TABLE
(
ProductID int
)
INSERT INTO #ProductTotals VALUES(1)
INSERT INTO #ProductTotals VALUES(11)
INSERT INTO #ProductTotals VALUES(3)
DECLARE #prmclientcode VARCHAR(MAX)='1'
SELECT * FROM #ProductTotals
SELECT * FROM #ProductTotals WHERE CHARINDEX(',' + CAST(ProductID AS VARCHAR(MAX)) + ',' , ',' + ISNULL(#prmclientcode,ProductID) + ',') > 0
Let me know if any concern.
use following code in order to separate your variable:
DECLARE
#T VARCHAR(100) = '1,2,3,23,342',
#I int = 1
;WITH x(I, num) AS (
SELECT 1, CHARINDEX(',',#T,#I)
UNION ALL
SELECT num+1,CHARINDEX(',',#T,num+1)
FROM x
WHERE num+1<LEN(#T)
AND num<>0
)
SELECT SUBSTRING(#T,I,CASE WHEN num=0 THEN LEN(#T)+1 ELSE num END -I)
FROM x
Use can use either table function or dynamic sql query, both options will work.
Let me know if you need more help

SQL Server expression substitution in SELECT statements as column names

How do I evaluate a character expression to resolve to a valid column name in a SELECT statement that would return column row values? Eg valid column name = Customer_1 == 'Customer_'+'1'
You need to use dynamic SQL. An example
DECLARE #DynSQL nvarchar(max)
DECLARE #Suffix int = 1
SET #DynSQL = N'SELECT Customer_' + CAST(#Suffix as nvarchar(10)) +
N' FROM YourTable WHERE foo = #foo'
EXEC sp_executesql #DynSQL, N'#foo int', #foo=1
As always with dynamic SQL you need to consider SQL injection if any of the inputs to the process will be user supplied.
How do I evaluate a character expression to resolve to a valid column name in a SELECT statement that would return column row values? Eg valid column name = Customer_1 == 'Customer_'+'1'
You're probably doing something wrong if you need to do this, but if you have to: build the column names as rows and then pivot.

Resources