Must declare the scalar variable "# in tsql - sql-server

I have a stored procedure as shown below. When i use the command so as to call the stored procedure, i get the error message
Must declare the scalar variable "#MusNo"."
I would like to ask your help.
exec sp_executesql N' execute [isb].[SP_GetNakitIslemSorguList_Test] NULL,159986569,''2016/01/01 12:23:45'',''2016/03/03 21:10:12'' '
USE [ATMDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE proc [isb].[SP_GetNakitIslemSorguList_Test]
(
#IslemKodu as varchar(30),
#MusNo as bigint,
#StartDate as Date,
#EndDate as Date
)
AS
DECLARE #Sql nvarchar(max)
DECLARE #AddToWhereSql varchar(50)
IF #IslemKodu is null
BEGIN
SET #AddToWhereSql = '1=1'
END
ELSE
BEGIN
SET #AddToWhereSql = 'IslemKodu = #IslemKodu'
END
BEGIN
SET #Sql = N'SELECT [KartNo],[HesapNo],[TCKN],[CepTel],[MusNo],[Alacakli],[Tutar],[Tarih],[AtmNo],[Borclu]
FROM [ATMDB].[isb].[NakitIslemSorgu] WITH (NOLOCK)
WHERE MusNo = #MusNo and cast([Tarih] as Date)>= #StartDate and cast([Tarih] as Date) <= #EndDate and CashResult = 0
and ' + #AddToWhereSql + ' ORDER BY Tarih DESC'
exec sp_executesql #Sql
END
GO

As you pass in a Variable #MusNo of type BIGINT you must concatenate its value into your dynamic SQL. Try it like this:
SET #Sql = N'SELECT [KartNo],[HesapNo],[TCKN],[CepTel],[MusNo],[Alacakli],[Tutar],[Tarih],[AtmNo],[Borclu]
FROM [ATMDB].[isb].[NakitIslemSorgu] WITH (NOLOCK)
WHERE MusNo = ' + CAST(#MusNo AS VARCHAR(100)) + ' and cast([Tarih] as Date)>= #StartDate and cast([Tarih] as Date) <= #EndDate and CashResult = 0
and ' + #AddToWhereSql + ' ORDER BY Tarih DESC'

sp_executesql requires the variables to be declared and initialised. This is done using parameters as follows:
DECLARE #Params NVARCHAR(2000);
SET #Params = N'#MusNo bigint, #StartDate Date, #EndDate Date';
exec sp_executesql #Sql, #Params, #MusNo = #MusNo, #StartDate = #StartDate, #EndDate = #EndDate;
Even better is the following which will completely avoid any sql injection.
DECLARE #Sql nvarchar(max)
DECLARE #Params NVARCHAR(2000);
SET #Params = N'#IslemKodu varchar(30), #MusNo bigint, #StartDate Date, #EndDate Date';
SET #Sql = N'SELECT [KartNo],[HesapNo],[TCKN],[CepTel],[MusNo],[Alacakli],[Tutar],[Tarih],[AtmNo],[Borclu]
FROM [ATMDB].[isb].[NakitIslemSorgu] WITH (NOLOCK)
WHERE MusNo = #MusNo and cast([Tarih] as Date)>= #StartDate and cast([Tarih] as Date) <= #EndDate and CashResult = 0
and IslemKodu = ISNULL(#IslemKodu, IslemKodu) ORDER BY Tarih DESC'
exec sp_executesql #Sql, #Params, #IslemKodu = #IslemKodu, #MusNo = #MusNo, #StartDate = #StartDate, #EndDate = #EndDate;

Related

How to store Exec result to datetime variable where exec result has variable table name?

How can I store my execution result in datetime variable?
My query look like this:
Declare #F VARCHAR(50) = (select replace ('H-10','-',''));
DECLARE #SQLQuery AS NVARCHAR(500)
set #SQLQuery=
N'SELECT
top 1 DATEADD(MINUTE, -330, time_stamp) as time
FROM
DMD_'+#F+'_DC_data
ORDER BY
time_stamp ASC';
DECLARE #SOR_time datetime
set #SOR_time=Exec (#SQLQuery)
If you want to store the ... execution result in datetime variable..., one solution is to execute the generated statement using sp_executesql with an OUTPUT parameter:
DECLARE #F varchar(50) = (select replace ('H-10', '-', ''));
DECLARE #SOR_time datetime
DECLARE #SQLQuery AS nvarchar(500)
SET #SQLQuery =
N'SELECT TOP 1 #SOR_time = DATEADD(MINUTE, -330, time_stamp) ' +
N'FROM QUOTE_NAME(DMD_' + #F + '_DC_data) ' +
N'ORDER BY time_stamp ASC'
;
DECLARE #rc int
EXEC #rc = sp_executesql
#SQLQuery,
N'#SOR_time datetime OUTPUT',
#SOR_time OUTPUT
IF #rc <> 0 PRINT 'Error'
Try following way. Execute query result store into the table instead of assign to a variable.
Declare #F VARCHAR(50) = (select replace ('H-10','-',''));
DECLARE #SQLQuery AS NVARCHAR(500)
set #SQLQuery=
N'SELECT
top 1 DATEADD(MINUTE, -330, time_stamp) as time
FROM
DMD_'+#F+'_DC_data
ORDER BY
time_stamp ASC';
DECLARE #TempTable TABLE (SOR_time datetime)
insert #TempTable
exec (#SQLQuery)
select * from #TempTable
You can just assign to variable inside query if result set is just a single variable
Declare #F VARCHAR(50) = (select replace ('H-10','-',''));
DECLARE #SQLQuery AS NVARCHAR(500)
DECLARE #SOR_time DATETIME
set #SQLQuery=
N'SELECT
top 1 #SOR_time = DATEADD(MINUTE, -330, time_stamp)
FROM
DMD_'+#F+'_DC_data
ORDER BY
time_stamp ASC';
-- PRINT #SQLQuery
Exec (#SQLQuery)
SELECT #SOR_time

Dates and Dynamic SQL error message

Using MS SQL 2012.
I am trying to query a set of tables using dynamic SQL and I am passing through the tablename, a start date in the format of dd/MM/yyyy and an end date in the format of dd/MM/yyyy.
My Code is as follows.
#tableName nvarchar(50),
#startDate date,
#endDate date
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Query varchar(max)
SET #Query = 'Select * from ''' + #tableName + ''' where Convert(date, Docdate, 103) >= ''' + CAST(#startDate AS VARCHAR(50)) + ''' and Convert(date, Docdate, 103) <= ''' + CAST(#endDate AS VARCHAR(50)) + ''
EXEC #Query
END
The Docdate field has a data type of Date and is in the format of yyyy-MM-dd.
I get the following error when I run this stored procedure.
Incorrect syntax near '/'.
What am I missing?
UPDATE
I am testing the query with the following entries for the variables and I still get the same error.
USE [TestDbs]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[getResultSet]
#tableName = Prices,
#startDate = 01/02/2016,
#endDate = 20/02/2016
SELECT 'Return Value' = #return_value
GO
You should use sp_executesql and pass proper date parameters to your query, and avoid the need for casting dates to strings at all:
CREATE PROCEDURE dbo.YourProcedure
#TableName SYSNAME,
#StartDate DATE,
#EndDate DATE
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)
SET #Query = 'SELECT * FROM ' + QUOTENAME(#TableName) +
' WHERE Docdate >= #StartDateParam
AND Docdate <= #EndDateParam';
EXECUTE sp_executesql
#Query,
N'#startDateParam DATE, #endDateParam DATE',
#StartDateParam = #StartDate,
#EndDateParam = #EndDate;
END
I have made a couple of other minor tweaks too:
Change the datatype of #TableName from NVARCHAR(50) to SYSNAME (Synonym for `NVARCHAR(128), the maximum length of an object name)
Change the data type of #Query to NVARCHAR(MAX) since this is the type sp_executesql expects.
Wrapped #TableName with QUOTENAME to ensure any special characters do not cause an error.
If DocDate is already a date, then the explicit convert is not necessary so I have removed this.
ADDENDUM
You may also wish to add some validation to the table name:
-- CHECK TABLE NAME IS A VALID TABLE OF VIEW
IF ISNULL(OBJECT_ID(#TableName, 'U'), OBJECT_ID(#TableName, 'V')) IS NULL
BEGIN
-- HANDLE INVALID NAME
RETURN;
END
EDIT
I have changed the procedure slightly to cater for sending through a schema qualified table name
CREATE PROCEDURE dbo.getResultSet
#TableName SYSNAME,
#StartDate DATE,
#EndDate DATE
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)
SET #Query = 'SELECT * FROM ' +
QUOTENAME(OBJECT_SCHEMA_NAME(OBJECT_ID(#TableName))) + '.' +
QUOTENAME(OBJECT_NAME(OBJECT_ID(#TableName))) +
' WHERE Docdate >= #StartDateParam
AND Docdate <= #EndDateParam';
EXECUTE sp_executesql
#Query,
N'#startDateParam DATE, #endDateParam DATE',
#StartDateParam = #StartDate,
#EndDateParam = #EndDate;
END
Then you would use this to execute it:
SET DATEFORMAT DMY;
DECLARE #return_value int
EXEC #return_value = [dbo].[getResultSet]
#tableName = 'dbo.Prices',
#startDate = '01/02/2016',
#endDate = '20/02/2016'
SELECT 'Return Value' = #return_value;
Or better still use a culture insensitive date format (yyyyMMdd) for your literals:
DECLARE #return_value int
EXEC #return_value = [dbo].[getResultSet]
#tableName = 'dbo.Prices',
#startDate = '20160201',
#endDate = '20160220'
SELECT 'Return Value' = #return_value;

sp_executesql date "Conversion failed when converting date and/or time from character string" in specific case

I have something strange:
Declare #SQLQuery As nvarchar(Max)
Declare #maxdat date
Declare #dateColumn nvarchar(10)
Set #maxdat = GETDATE()
Set #dateColumn = 'ERDAT'
Set #SQLQuery = 'SELECT * FROM myTable WHERE #dateColumn <= #maxdat'
Execute sp_executesql #SQLQuery, N'#maxdat date, #dateColumn nvarchar(10)', #maxdat, #dateColumn
This will fail with Conversion failed when converting date and/or time from character string.
But the following will work just fine:
Set #SQLQuery = 'SELECT * FROM myTable WHERE ERDAT <= #maxdat'
Try the updated code like this. Just put the #dateColumn parameter outside the query string
Declare #SQLQuery As nvarchar(Max)
Declare #maxdat date
Declare #dateColumn nvarchar(10)
Set #maxdat = GETDATE()
Set #dateColumn = 'ERDAT'
Set #SQLQuery = 'SELECT * FROM myTable WHERE ' + #dateColumn + ' <= #maxdat'
Execute sp_executesql #SQLQuery, N'#maxdat date', #maxdat
Problem is with your dynamic SQL. the way you are doing it the variables will go as strings. You have to use the "+" symbol and do it like example below so that SQL can parse it and use 'variable value' instead of 'variable name'.
SELECT GETDATE() AS A
INTO
#Temp
Declare #SQLQuery As nvarchar(Max)
Declare #maxdat date
Declare #dateColumn nvarchar(10)
Set #maxdat = DATEADD(Day,1,GETDATE())
Set #dateColumn = 'A'
--Set #SQLQuery = 'SELECT * FROM #Temp WHERE #dateColumn >= #maxdat'
Set #SQLQuery = 'SELECT * FROM #Temp WHERE ' + #dateColumn + ' >= '+ CAST(#maxdat AS nvarchar(10))
--Print #SQLQuery
Execute sp_executesql #SQLQuery, N'#maxdat date, #dateColumn nvarchar(10)', #maxdat, #dateColumn

EXEC sp_executesql with multiple parameters

How to pass the parameters to the EXEC sp_executesql statement correctly?
This is what I have now, but i'm getting errors:
alter PROCEDURE [dbo].[usp_getReceivedCases]
-- Add the parameters for the stored procedure here
#LabID int,
#RequestTypeID varchar(max),
#BeginDate date,
#EndDate date
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #statement nvarchar(4000)
set #statement = N'select SentToLab,
FROM dbo.vEmailSent
WHERE SentToLab_ID=#LabID and convert(date,DateSent) >= #BeginDate
and CONVERT(date, datesent) <= #EndDate
and RequestType_ID in ( #RequestTypeID )
EXEC sp_executesql #statement,N'#LabID int', #LabID, N'#BeginDate date', #BeginDate,N'#EndDate date', #EndDate, #RequestTypeID=#RequestTypeID
END
RequestTypeID is a comma delimited list of integers, like so: "1,2,3,4,5"
here is my try #2, also unsuccessful
declare #statement nvarchar(4000)
SET #statement =' select SentToLab_ID
FROM dbo.vEmailSent
WHERE
SentToLab_ID='+#LabID+' and convert(date,DateSent) >= '+#BeginDate +'
and CONVERT(date, datesent) <= '+#EndDate+'
and RequestType_ID in ('+ #RequestTypeID+' )
group by FileStream_ID, SentToLab_ID'
EXEC(#statement)
Operand type clash: date is incompatible with int
Here is a simple example:
EXEC sp_executesql #sql, N'#p1 INT, #p2 INT, #p3 INT', #p1, #p2, #p3;
Your call will be something like this
EXEC sp_executesql #statement, N'#LabID int, #BeginDate date, #EndDate date, #RequestTypeID varchar', #LabID, #BeginDate, #EndDate, #RequestTypeID
This also works....sometimes you may want to construct the definition of the parameters outside of the actual EXEC call.
DECLARE #Parmdef nvarchar (500)
DECLARE #SQL nvarchar (max)
DECLARE #xTxt1 nvarchar (100) = 'test1'
DECLARE #xTxt2 nvarchar (500) = 'test2'
SET #parmdef = '#text1 nvarchar (100), #text2 nvarchar (500)'
SET #SQL = 'PRINT #text1 + '' '' + #text2'
EXEC sp_executeSQL #SQL, #Parmdef, #xTxt1, #xTxt2
If one need to use the sp_executesql with OUTPUT variables:
EXEC sp_executesql #sql
,N'#p0 INT'
,N'#p1 INT OUTPUT'
,N'#p2 VARCHAR(12) OUTPUT'
,#p0
,#p1 OUTPUT
,#p2 OUTPUT;
maybe this help :
declare
#statement AS NVARCHAR(MAX)
,#text1 varchar(50)='hello'
,#text2 varchar(50)='world'
set #statement = '
select '''+#text1+''' + '' beautifull '' + ''' + #text2 + '''
'
exec sp_executesql #statement;
this is same as below :
select #text1 + ' beautifull ' + #text2

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