Dynamic SQL won't allow me to pass null variables to SSRS - sql-server

I'm trying to write a Dynamic SQL query that will allow the end-user to opt-out of entering certain search criteria. In this example, I would like the end-user to be able to enter a value for #GLAccountStart without entering a value for #GLAccountEnd and have the "IF ..." statement where #GLAccountStart IS NOT NULL and #GLAccountEnd IS NULL execute correctly.
When I try to run this in SSRS, however, entering just the first value returns 0 rows (it should return 2), and entering values for both variables actually returns the correct number of rows. Additionally, if I remove the #GLAccountEnd variable from my script entirely and just run it with the option to include #GLAccountStart, SSRS returns the correct number of rows with the proper input.
Is there a trick or something to implementing this?
USE [DataWarehouse]
GO
/****** Object: StoredProcedure [dbo].[BrowseCODA] Script Date: 6/27/2016 8:37:37 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[BrowseCODA]
#GLAccountStart int,
#GLAccountEnd int
AS
SET NOCOUNT ON;
DECLARE #SQLQuery AS nvarchar(4000)
DECLARE #ParameterDef AS nvarchar(2000)
SET #SQLQuery = 'SELECT *
FROM [DataWarehouse].[dbo].[VDocDetails]
WHERE Company+''-''+FullDocNumber IN
(SELECT Company+''-''+FullDocNumber
FROM [DataWarehouse].[dbo].[VDocDetails]
WHERE (1=1)'
IF (#GLAccountStart IS NOT NULL) AND (#GLAccountEnd IS NOT NULL)
SET #SQLQuery = #SQLQuery + ' AND (GLAccount >= #GLAccountStart) AND (GLAccount <= #GLAccountEnd)'
IF (#GLAccountStart IS NOT NULL) AND (#GLAccountEnd IS NULL)
SET #SQLQuery = #SQLQuery + ' AND (GLAccount = #GLAccountStart)'
SET #SQLQuery = #SQLQuery + ')'
SET #ParameterDef =
'#GLAccountStart int,
#GLAccountEnd int'
EXECUTE sp_Executesql #SQLQuery,
#ParameterDef,
#GLAccountStart,
#GLAccountEnd
IF ##ERROR <> 0 GOTO ErrorHandler
SET NOCOUNT OFF
RETURN(0)
ErrorHandler:
Return(##ERROR)
GO

I guess #GLAccountEnd is not getting a null value from SSRS.
But, Why don't you try simple SQL?
SELECT *
FROM [DataWarehouse].[dbo].[VDocDetails]
where GLAccount between #GLAccountStart
AND case #GLAccountEnd
when '' then #GLAccountStart
else #GLAccountEnd end
or dynamic:
USE [DataWarehouse]
GO
/****** Object: StoredProcedure [dbo].[BrowseCODA] Script Date: 6/27/2016 8:37:37 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[BrowseCODA]
#GLAccountStart varchar,
#GLAccountEnd varchar
AS
SET NOCOUNT ON;
DECLARE #SQLQuery AS nvarchar(4000)
DECLARE #ParameterDef AS nvarchar(2000)
SET #SQLQuery = 'SELECT *
FROM [DataWarehouse].[dbo].[VDocDetails]
WHERE (1=1)'
IF (#GLAccountStart <> '') AND (#GLAccountEnd <> '')
SET #SQLQuery = #SQLQuery + ' AND (GLAccount >= #GLAccountStart) AND (GLAccount <= #GLAccountEnd)'
IF (#GLAccountStart <> '') AND (#GLAccountEnd = '')
SET #SQLQuery = #SQLQuery + ' AND (GLAccount = #GLAccountStart)'
SET #ParameterDef =
'#GLAccountStart int,
#GLAccountEnd int'
EXECUTE sp_Executesql #SQLQuery,
#ParameterDef,
#GLAccountStart,
#GLAccountEnd
IF ##ERROR <> 0 GOTO ErrorHandler
SET NOCOUNT OFF
RETURN(0)
ErrorHandler:
Return(##ERROR)
GO

SSRS apparently takes the lack of input in the parameters to mean '' instead of NULL. When I changed the dynamic query to check against whether or not the values were equal to '', the code worked as-intended.

Related

T-SQL Merge statement in stored procedure throws error

Recently I have had to change a query from the following (fully working):
/****** WORKING ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [operations].[ROIWarehouseDatas]
(#Operation VARCHAR(50) = NULL,
#TableName NVARCHAR(255) = NULL,
#Results [dbo].[ForeSightData] READONLY)
AS
BEGIN
DECLARE #err INT
SET #err = 0
IF (#Operation = 'Insert')
BEGIN
DECLARE #SQLString NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(4000)
SET #SQLString = N'TRUNCATE TABLE ['+ #TableName + N'];
INSERT INTO ['+ #TableName + N']
SELECT [ID], [BrandName], [AdvertName], [VersionName], [WCPM]
FROM #Results;';
SET #ParamDefinition = N'#Operation VARCHAR(50), #Results [dbo].[ForeSightData] READONLY';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName, #Results
END
--ENDIF Insert
SET #err = ##ERROR
RETURN #err
END
To the following (not working):
/****** NOT WORKING ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [operations].[ROIWarehouseDatas]
(#Operation VARCHAR(50) = NULL,
#TableName NVARCHAR(255) = NULL,
#Results [dbo].[ForeSightData] READONLY)
AS
BEGIN
DECLARE #err INT
DECLARE #SQLString NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(4000)
SET #err = 0
IF (#Operation = 'Insert')
BEGIN
SET #SQLString = N'MERGE INTO ['+ #TableName +'] AS T
USING #Results AS S ON T.ID = S.ID
WHEN MATCHED
THEN UPDATE
SET T.[BrandName] = S.[BrandName],
T.[AdvertName] = S.[AdvertName],
T.[VersionName] = S.[VersionName],
T.[VersionDuration] = S.[VersionDuration],
T.[WCPM] = S.[WCPM]
WHEN NOT MATCHED BY TARGET
THEN INSERT ([ID], [BrandName], [AdvertName], [VersionName], [WCPM])
VALUES (S.[ID], S.[BrandName], S.[AdvertName], S.[VersionName], S.[WCPM]);';
SET #ParamDefinition = N'#Operation VARCHAR(50), #Results [dbo].[ForeSightData] READONLY';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName, #Results
END
--ENDIF Insert
SET #err = ##ERROR
RETURN #err
END
However, when I run the program I get the following error:
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. Unclosed quotation mark after the character string ''.
Incorrect syntax near ''.
I tried checking the syntax - and that came up as fine.
Seems not correct syntax for SQL MERGE.
WHEN NOT MATCHED BY T THEN should be Target not T:
WHEN NOT MATCHED BY Target
THEN .....

SQL procedure executes first line then stops

I am running an SQL procedure that has to update a certain table. When I run the procedure it says successfully completed, yet the records are not updated when I try to debug it, it run only the line SET ANSI ON, then it gives the successful message. I am using SQL server 2012
Am I missing something, is there anything I need to add? See my code here:
USE [CADDe_ProdCopy]
GO
/****** Object: StoredProcedure [dbo].[sp_sms_X203] Script Date: 2015/09/03 08:28:15 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[sp_sms_X203]
as
declare #lCount int
set #lCount = (select count(*) from tbl_X203_SMS where SMSSent = 0 )
if #lCount > 0
begin
DECLARE #cSMSeMail varchar(100)
declare #cSMSType varchar(10)
declare #cSMSSent int
declare #cRA varchar(10)
declare #cWizard varchar(7)
declare #cCName varchar(26)
declare #cContact varchar(30)
declare #cUsed_KM int
declare #cAmount_Due decimal(18, 2)
declare #cSMSMessage varchar(160)
declare #cvblf varchar(1)
declare #cCheckInDt datetime
declare #cCheckOutDt datetime
declare #err int
set #cvblf = '|'
declare lcursor CURSOR FOR
Select SMSType, RA, CName, Contact, Used_KM, Amount_Due, eMail, [CheckInDateTime] ,[CheckOutDateTime]
From tbl_X203_SMS WHERE SMSSent = 0
open lcursor
fetch next from lcursor into #cSMSType, #cRA, #cCName, #cContact, #cUsed_KM, #cAmount_Due, #cSMSeMail, #cCheckInDt, #cCheckOutDt
while ##FETCH_STATUS = 0
begin
--SET #cContact = '+27834115771'
--SET #cSMSeMail = 'amangelsdorf#avis.co.za'
-- Check that the date of the checkin is within same day
if rtrim(ltrim(#cSMSType)) = 'CheckIn'
begin
if datediff(day,#cCheckInDt,getdate()) = 0
begin
SET #cSMSMessage = left('Thank you '+ #cCName +' for renting with AVIS.',160)
SET #cSMSMessage = left( #cSMSMessage + ' RA#' + #cRA + 'Retrieve your invoice at http://www.avis.co.za/inv' ,160)
--if #cAmount_Due > 0
-- SET #cSMSMessage = left( #cSMSMessage + #cvbLf + 'AMT:R ' + cast(#cAmount_Due as varchar),160)
exec sp_sms_xml_post #cContact, #cSMSMessage, #cSMSeMail
end
end
-- Check that the date of the checkout is within same day
if rtrim(ltrim(#cSMSType)) = 'CheckOut'
begin
if datediff(day,#cCheckOutDt,getdate()) = 0
begin
--SET #cSMSMessage = left( 'Thank you for choosing AVIS.' + #cvbLf + 'For any assistance contact the AVIS Careline on Tel: 0800001669' ,160)
SET #cSMSMessage = left( 'Thank you for choosing AVIS. ' + #cvbLf + 'Kindly contact 0800001669 for any roadside or emergency assistance.' ,160)
exec sp_sms_xml_post #cContact, #cSMSMessage, #cSMSeMail
end
end
set #err = ##error
if #err = 0
begin
--print 'no error'
update tbl_X203_SMS set SMSSent = 1 where SMSType = #cSMSType and RA = #cRA
end
fetch next from lcursor into #cSMSType, #cRA, #cCName, #cContact, #cUsed_KM, #cAmount_Due, #cSMSeMail, #cCheckInDt, #cCheckOutDt
end
close lcursor
deallocate lcursor
end
`
You check your count value in
set #lCount = (select count(*) from tbl_X203_SMS where SMSSent = 0 )
if #lCount > 0
because may be you are getting value as 0 so it is not going inside the if condition, you can use print(#lCount ) before if and execute stored procedure from sql server.
The code that you have shown is the code to create / alter a stored procedure and won't execute it, hence the Successfully Compiled response.
In order to execute this procedure you will need to use the exec statement:
exec [dbo].[sp_sms_X203]

SQL Server stored procedure to empty specific tables

I have a stored procedure which is supposed to truncate specific tables based on their names.
Tables which do not have "A" as the first character in their names must be truncated.
The problem is that this code doesn't work! Please help
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[return_data]
#DBName varchar(100)
AS
declare #i int, #tc int
set #i = 1
DECLARE #sql NVARCHAR(100)
SET #sql = 'USE ' + QUOTENAME(#DBName) + '
DECLARE cur CURSOR FOR SELECT TABLE_NAME FROM information_schema.tables
'
EXECUTE(#sql)
OPEN cur
declare #tbl_name nvarchar(100)
declare #first_char char(1)
FETCH NEXT FROM cur INTO #tbl_name
WHILE ##FETCH_STATUS = 0 BEGIN
set #first_char = SUBSTRING(#tbl_name, 0, 1)
set #sql = 'DELETE FROM ' + QUOTENAME(#tbl_name)
if (#first_char != 'A')
begin
EXECUTE(#sql)
end
FETCH NEXT FROM cur INTO #tbl_name
END
CLOSE cur
DEALLOCATE cur
return
The problem is with the SUBSTRING function. The starting position is a 1-based ordinal, not 0-based. Try
SUBSTRING(#tbl_name, 1, 1)
or
LEFT(#tbl_name, 1)
Also, I suggest you make it a habit of schema-qualifying table names to avoid ambiguity.

Case Statement for TableName

I want to create a stored procedure which updates table column based on sent condition. The queries which i wrote dont work.
First is if I try to set Table name as variable.
Create Procedure Proc_Test
#Tblname varchar(20)
AS BEGIN
Update #Tblname
Set IsValid = 1;
End
this fails.
Second I have tried is case statement
Create Procedure Proc_Test
#Tblname varchar(20)
AS BEGIN
Case #Tblname
WHEN 1 THEN Update tbl1 set ISValid = 1;
WHEN 2 THEN Update tbl2 set ISValid = 1;
End
END
This also throws exception.
Any other way to achieve this ?
You need to use dynamic sql if you want the table name to be variable, otherwise you need to use conditional statements to filter based on table names, which would be ok if there weren't too many table names to work through.
Conditional Approach
declare #Tblname varchar(20) = 'Table1'
if #Tblname = 'Table1'
begin
update Table1
set IsValid = 1
-- where some condition is met?
end
if #Tblname = 'Table2'
begin
update Table2
set IsValid = 1
-- where some condition is met?
end
Dynamic Sql Approach
declare #SQLString nvarchar(100);
declare #Tblname varchar(20) = 'Table1'
set #SQLString = N'update ' + #Tblname + ' set IsValid = 1';
execute sp_executesql #SQLString
Try this -
CREATE PROCEDURE Proc_Test
#Tblname VARCHAR(20)
AS
BEGIN
DECLARE #SQL varchar(1000);
SET #SQL = 'Update '+#Tblname+' Set IsValid = 1;'
EXECUTE (#SQL);
END

sql server stored procedure sp_executesql

I have this stored procedure
USE [all_things]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_getThingsByType]
#thingid int,
#typeid int
AS
DECLARE #Sql NVARCHAR(MAX) = 'SELECT * from items'
IF #thingid IS NOT NULL
BEGIN
SET #Sql += ' where thingid = #thingid'
END
IF #typeid IS NOT NULL
BEGIN
SET #Sql += ' and TypeID = #typeid'
END
EXEC sp_executesql #sql, N'#thingid int,#typeid int',#thingid=#thingid,#typeid=#typeid;
Test cases:
When I run it with the thingid is null and typeid is null, I get all results which is perfect.
When the thingid is supplied and the typeid is null, the results are ok
Here is where, the results are not good: thingid is null and typeid is supplied. Everything is being returned.
What am I missing?
Thanks
Thanks to #tschmit007, I fixed it.
USE [all_things]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_getThingsByType]
#thingid int,
#typeid int
AS
DECLARE #Sql NVARCHAR(MAX) = 'SELECT * from items'
IF #thingid IS NOT NULL
BEGIN
SET #Sql += ' where thingid = #thingid'
END
IF #typeid IS NOT NULL AND #thingid IS NOT NULL
BEGIN
SET #Sql += ' and TypeID = #typeid'
END
IF #typeid IS NOT NULL AND #thingid IS NULL
BEGIN
SET #Sql += ' where TypeID = #typeid'
END
EXEC sp_executesql #sql, N'#thingid int,#typeid int',#thingid=#thingid,#typeid=#typeid;

Resources