Why Is it giving me "Must declare the Scalar variable "#jobnumber" " - sql

DECLARE #sql VARCHAR(8000)
,#jobNumber VARCHAR(25)
,#DBName VARCHAR(30)
SET #jobNumber = '417133'
DROP TABLE #Actual
CREATE TABLE #Actual (
jobnumber INT
,firstNameCounts VARCHAR(25)
,lastNameCounts VARCHAR(25)
,address1Counts VARCHAR(25)
,address2Counts VARCHAR(25)
,cityCounts VARCHAR(25)
,stateCounts VARCHAR(25)
,zipCounts VARCHAR(25)
,inHomeDateCounts VARCHAR(25)
)
SET #sql = 'INSERT INTO #actual (jobnumber,firstNameCounts,lastNameCounts ,
address1Counts, address2Counts, cityCounts, stateCounts, zipCounts,
inHomeDateCounts) '
SET #sql = #sql + ' Select s.jobnumber, count(s.firstName) AS
[firstNameCounts], Count (s.lastName) AS [lastNameCounts], Count (s.Address1)
As [address1Counts], Count (s.address2)-Count (address2) AS '
SET #sql = #sql + ' [address2Counts], Count (s.City) AS [cityCounts], Count
(s.State) AS [stateCounts], Count (s.Zip) AS [zipCounts], Count
(jb.inHomeDate) AS [inHomeDateCounts] '
SET #sql = #sql + ' From [s-portaldb1].[tdis_417133) + ].[dbo].
[tblStandardFinal] s '
SET #sql = #sql + ' INNER JOIN [s-printstream].[tdSchedule2].[dbo].
[tblJobTicketActions] jb '
SET #sql = #sql + ' ON jb.psFlagJobNumber = s.jobNumber '
*SET #sql = #sql + ' where jobNumber = #jobNumber '* Getting error here
SET #sql = #sql + ' group by jobNumber '
PRINT #SQL
EXEC (#sql)
SELECT *
FROM #Actual
I am getting this
Error: Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "#jobNumber". I have declared the value and not sure what the reason could be.
any help would be appreciated.

Because you are executing SQL with exec() and have not provided a declaration for that variable inside the executed sql. #sql will be executed in its own context, and will not be able to access the variable of the same name that you have declared outside of the executed sql.
You could instead use sp_executesql which allows for parameter declaration and passing of parameters.
declare #sql nvarchar(max); /* nvarchar() instead of varchar() */
...
exec sp_executesql #sql, N'#JobNumber Varchar(25)', #JobNumber;
dynamic sql reference:
The curse and blessings of dynamic SQL - Erland Sommarskog
sp_executesql

You are running dynamic SQL - it runs in its own context and doesn't have access to the declared variables you have.
Either construct the dynamic SQL with the value being passed in (in the SQL string you later execute), or figure out how to do this without dynamic SQL (I don't see a reason for building the string and the EXECuting it).
All that string concatenation seems completely superfluous.
So instead of this:
SET #sql = 'INSERT INTO #actual (jobnumber,firstNameCounts,lastNameCounts ,
address1Counts, address2Counts, cityCounts, stateCounts, zipCounts,
inHomeDateCounts) '
SET #sql = #sql + ' Select s.jobnumber, count(s.firstName) AS
[firstNameCounts], Count (s.lastName) AS [lastNameCounts], Count (s.Address1)
As [address1Counts], Count (s.address2)-Count (address2) AS '
SET #sql = #sql + ' [address2Counts], Count (s.City) AS [cityCounts], Count
(s.State) AS [stateCounts], Count (s.Zip) AS [zipCounts], Count
(jb.inHomeDate) AS [inHomeDateCounts] '
SET #sql = #sql + ' From [s-portaldb1].[tdis_417133) + ].[dbo].
[tblStandardFinal] s '
SET #sql = #sql + ' INNER JOIN [s-printstream].[tdSchedule2].[dbo].
[tblJobTicketActions] jb '
SET #sql = #sql + ' ON jb.psFlagJobNumber = s.jobNumber '
SET #sql = #sql + ' where jobNumber = #jobNumber '
SET #sql = #sql + ' group by jobNumber '
PRINT #SQL
EXEC (#sql)
You should just have:
INSERT INTO #actual (jobnumber,firstNameCounts,lastNameCounts ,
address1Counts, address2Counts, cityCounts, stateCounts, zipCounts,
inHomeDateCounts)
Select s.jobnumber, count(s.firstName) AS
[firstNameCounts], Count (s.lastName) AS [lastNameCounts], Count (s.Address1)
As [address1Counts], Count (s.address2)-Count (address2) AS
[address2Counts], Count (s.City) AS [cityCounts], Count
(s.State) AS [stateCounts], Count (s.Zip) AS [zipCounts], Count
(jb.inHomeDate) AS [inHomeDateCounts]
From [s-portaldb1].[tdis_417133) + ].[dbo].
[tblStandardFinal] s
INNER JOIN [s-printstream].[tdSchedule2].[dbo].[tblJobTicketActions] jb
ON jb.psFlagJobNumber = s.jobNumber
where jobNumber = #jobNumber
group by jobNumber

Related

Variable in SQL query syntax

I want to make a simple SQL query like:
SELECT * FROM table WHERE $variable_2 = $variable_1
instead of a default one:
SELECT * FROM table WHERE column_name = $variable_1
It seems like first example doesn't work at all. Is it even possible to modify SQL query syntax in such way?
as this reference answer for:
in link:
Use Variable as SQL column Name in query
answer1:
declare #ColumnName varchar(50)
declare #sql nvarchar(max)
set #ColumnName = 'SalesData_' + convert(varchar(2),datepart(dd,getdate()))
set #sql = 'select ' + #ColumnName + ' from SalesTable'
print #sql
EXEC sp_sqlexec #sql
answer 2:
declare #ColumnName varchar(50)
declare #sql nvarchar(max)
set #ColumnName = 'SalesData_' + convert(varchar(2),datepart(dd,getdate()))
set #sql = 'select ' + #ColumnName + ' from yourschema.SalesTable'
print #sql

Assign result from dynamic SQL in a parameter to another parameter

I'm having to build my query dynamically, firstly, it gets the maxlogid from the log, and appends this to the temporary table name. Then it does a COALESCE to return the distinct values into a string.
However, the output of the string, I want to have in a parameter, so I can use it again later on within a dynamic sql query.
Here is my code;
DECLARE #maxLogId VARCHAR(10)
SELECT #maxLogId = (SELECT Max(id) FROM dbo.tLog)
DECLARE #PolicyTempTable VARCHAR(100)
SET #PolicyTempTable = '##tPols' + #maxLogId
DECLARE #emailParm NVARCHAR(1000)
SET #emailParm = N'DECLARE #email VARCHAR(MAX)
SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm
The results are returned as follows;
"abc#a.co.uk",""abc#b.co.uk"
I want to be able to write the sp_executesql into a seperate parameter, so I can use for a dynamic query like below;
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + '' EXEC sp_executesql #emailParm + '' + ')'')'
However, I can't use the sp_executesql within my dynamic query.
You can use parameters with sp_executesql
DECLARE #emailParm NVARCHAR(1000)
DECLARE #emailOut NVARCHAR(MAX)
SET #emailParm = N'SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm, N'#email VARCHAR(1000) OUTPUT', #email = #emailOut OUTPUT
Then you can build your second dynamic sql
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + #emailOut + ')'')'

Conversion failed when converting the varchar value 'dynamic sql query' to data type int

I have a stored procedure for checking if row exist. I use this with ADO.NET for a dynamic query instead of having similar queries for all my tables.
CREATE PROCEDURE [dbo].[Row_Exist]
#TableName VARCHAR(50),
#ColumnName VARCHAR(50),
#RowId INT
AS
BEGIN
DECLARE #sqlQuery NVARCHAR(MAX) = ''
SET #sqlQuery = 'SELECT COUNT(1) as count FROM ' + #TableName + ' WHERE ' + #ColumnName + ' = ' + #RowId
EXEC(#sqlQuery)
END
If I execute this with a valid rowid, tablename, and columnname, I get the following error
Conversion failed when converting the varchar value SELECT COUNT(1) as count FROM Users WHERE UserID = to data type int.
This is because you try to concate int to varchar. Please try the below sql
CREATE PROCEDURE [dbo].[Row_Exist]
#TableName varchar(50),
#ColumnName varchar(50),
#RowId int
AS
BEGIN
DECLARE #sqlQuery NVARCHAR(MAX) = ''
SET #sqlQuery = 'SELECT COUNT(1) as count FROM ' + #TableName + ' WHERE ' + #ColumnName + ' = ' + CAST(#RowId AS VARCHAR(20))
EXEC(#sqlQuery)
END
Use parameters where you can. I tend to use REPLACE() to fill in the other values:
DECLARE #sqlQuery NVARCHAR(MAX) = '
SELECT COUNT(1) as count
FROM #TableName
WHERE #ColumnName = #RowId
';
SET #sqlQuery = REPLACE(REPLACE(#sqlQuery, '#TableName', quotename(#TableName)), '#ColumnName', quotename(#ColumnName));
EXEC sp_executesql #sqlQuery, N'#RowId int', #RowId=#RowId;

Must declare the scalar variable with Table-Valued Parameters and Stored Procedure

Could someone explain why the following gives me "Must declare the scalar variable #facilities." but works fine if I were to use VARCHAR instead of my created type? How can I fix this?
TIA
--CREATE TYPE integer_list AS TABLE (n int NOT NULL PRIMARY KEY)
--DROP PROCEDURE spTestTVP
CREATE PROCEDURE spTestTVP (
#facilities integer_list READONLY
--#facilities varchar(100)
)
AS
DECLARE #sql nvarchar(4000)
SET #sql = 'SELECT * FROM TestTable'
SET #sql = #sql + ' WHERE 1=1 '
IF #facilities IS NOT NULL
SET #sql = #sql + ' AND (FacilityNo IN (' + #facilities + ') OR FacilityNo IS NULL)'
EXEC sp_executesql #sql
DECLARE #items VARCHAR(MAX)
SELECT#items = COALESCE(#items+',' ,'') + n
FROM #facilities
DECLARE #sql nvarchar(4000)
SET #sql = 'SELECT * FROM TestTable'
SET #sql = #sql + ' WHERE 1=1 '
IF #facilities IS NOT NULL
SET #sql = #sql + ' AND (FacilityNo IN (' + #items + ') OR FacilityNo IS NULL)'
EXEC sp_executesql #sql
or not dynamic as follows:
SELECT t.* FROM TestTable as t
left outer join
#facilities as f
on
f.n = t.FacilityNo
where
t.FacilityNo is null
or
f.n is not null
When you are concatenating things in a dynamicSQl statment all pieces that build the statement must be either varchar or nvarchar. That is a limit of SQL.
On the other hand you don't need dynamic sql since you have created a table.
SELECT * FROM TestTable t
LEFT join #facilities f on f.n = t.facilityNO

Dynamic SQL using Sp_executesql

I have a stored procedure which I have to rewrite using sp_executesql. I want to use sp_executesql instead of exec because of performance issue on my SQL Server instance.
Here is my code:
ALTER PROCEDURE [dbo].[sp_TestSp1]
#Type1 VARCHAR(256)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sqlCommand varchar(2000) = ''
DECLARE #columnList varchar(1000) = ''
DECLARE #dynamicSql varchar(1000) = ''
IF (#Type1 IS NOT NULL )
BEGIN
SET #dynamicSql = #dynamicSql + 'AND tbl1.DTypeID IN ( '+ #Type1+ ' )'
END
SET #columnList = 'SELECT DISTINCT tbl2.ID, Name AS PName '
SET #sqlCommand = #columnList
+ ' FROM tbl1 '
+ ' INNER JOIN tbl3 ON tbl1.NID= tbl3.NID '
+ ' INNER JOIN tbl4 ON tbl3.DID = tbl4.DID '
+ ' WHERE TT=1 AND IsActive=1 AND tbl1.DTypeID IN (1,3,5)'
+ #dynamicSql
EXEC (#sqlCommand)
Replace your EXEC (#sqlCommand) statement with the following.
EXECUTE sp_executesql #sqlCommand
TechNet Link