Report Builder paramter dropdown to choose column name - sql

I have a parameter with the available values as column names and a I am using that parameter in the sql query
WHERE ((#ColumnName) BETWEEN (#StartDate) AND (#EndDate))
AND (schema.table.column_name LIKE (#Number))
When i try to run the report i get a cannot convert date/time from characters
If i remove the #ColumnName parameter the report runs fine but i want the ability to choose a column to search the date against.

If you want pass Column name dynamically you will need to use a stored procedure to do this using dynamic sql something like this....
CREATE PROCEDURE Get_Data
#ColumnName1 SYSNAME,
#ColumnName2 SYSNAME,
#StartDate DATETIME,
#EndDate DATETIME,
#Number VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = N'SELECT * FROM TableName'
+ N'WHERE ' + QUOTENAME(#ColumnName1) + N' BETWEEN #StartDate AND #EndDate '
+ N' AND ' + QUOTENAME(#ColumnName2) + N' LIKE ''#Number'' '
EXECUTE sp_executesql #SQL
,N'#StartDate DATETIME, #EndDate DATETIME, #Number VARCHAR(100)'
,#StartDate
,#EndDate
,#Number
END

Related

Dynamic Sp_Executesql failing on datetime conversion error

I have a very simple dynamic SQL query that specifically needs to be called using sp_executesql with parameters. This query works fine in regular dynamic SQL, but fails when using sp_executesql on a conversion error.
I have tried many combinations of dynamic SQL, but none of them seem to work specifically for datetime conversions related to sp_executesql.
declare
#sql_nvarchar nvarchar(max),
#datetime datetime = GETDATE(),
#sqlparams nvarchar(max),
#tablename nvarchar(max) = 'SomeTableName'
Set #sql_nvarchar =
N'
Select *
from ' + #tablename + '
where Date > ''' + convert(nvarchar(23), #datetime, 101) + ''' '
Set #sqlparams =
N'
#datetime datetime,
#tablename nvarchar(max)
'
EXEC(#sql_nvarchar)
EXEC [sp_executesql] #sql_nvarchar,#sqlparams, #datetime, #tablename
The first exec correctly returns the desired query, the second EXEC throws an error: 'Error converting data type nvarchar(max) to datetime.'
You cannot parameterize an identifier, such as a table name. So, phrase this as:
Set #sql_nvarchar = N'
Select *
from ' + #tablename + '
where Date > #datetime
';
Set #sqlparams = N'#datetime datetime'
exec sp_executesql #sql_nvarchar, #sqlparams,
#datetime=#datetime

Multi values passing through a single parameter

ALTER PROCEDURE Example
(#BranchCode AS INT,
#Department VARCHAR(8000),
#DateFrom AS DATETIME,
#DateTo AS DATETIME,
#TransactionNumber AS NVARCHAR(30)
-- #Delimiter char(1)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX)
SET #Sql = 'Select
Mast.Branch_code, Mast.purerq_id as purerq_id,
Max(Mast.purreq_date) as purreq_date, Max(Mast.Dept_code) as Dept_code,
Max(Mast.purreq_desc) as purreq_desc,
Sum(Det.purreq_qty2) as purreq_qty2,
Det.Item_Code, Max(Mast.purreq_docecNo) as DocNo,
Sum(IsNull(Det.purreq_qty1,0)) as purreq_qty1,
IsNull(Det.purerq_TranNo,'') as purerq_TranNo,
IsNull(Max(Mast.purerq_adduserid),'') as Adduserid,
Max(Det.ItemPacking_Code) as ItemPacking_Code
From
tbl_purreqMaster Mast, tbl_purreq_detail1 Det
Where
Mast.Branch_code = Det.Branch_code And
Mast.purerq_id = Det.purerq_id And
Mast.purreq_date Between ' + #DateFrom + ' And ' + #DateTo + ' And
Mast.Dept_code IN (' + REPLACE( #Department, '''','') + ')
Mast.Branch_code = ' + CAST(#BranchCode AS VARCHAR) + ' AND
Mast.purreq_docecNo =' + #TransactionNumber + '
Group By
Mast.Branch_code, Mast.purerq_id, Det.Item_Code, Det.purerq_TranNo'
PRINT #Sql
--exec sp_executesql #Sql
END
GO
EXEC Example 1,'7,8','2017-10-01 00:00:00','2017-10-30 00:00:00','ALIA/PURQGEN/0000001'
This query shows this error
Msg 241, Level 16, State 1, Procedure Example, Line 18
Conversion failed when converting date and/or time from character string.
However I have tried replace and cast functions to resolve this but I found no solution
I would use the #params that go along with sp_executesql for the parameters that do not need to be concatenated to your executed string. I would also recommend some more processing on #Department to prevent sql injection.
ALTER PROCEDURE Example
(#BranchCode AS INT,
#Department VARCHAR(8000),
#DateFrom AS DATETIME,
#DateTo AS DATETIME,
#TransactionNumber AS NVARCHAR(30)
-- #Delimiter char(1)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX), #Params nvarchar(8000);
set #Params = '#BranchCode INT, #DateFrom DATETIME, #DateTo DATETIME, #TransactionNumber NVARCHAR(30)'
SET #Sql = 'Select
Mast.Branch_code, Mast.purerq_id as purerq_id,
Max(Mast.purreq_date) as purreq_date, Max(Mast.Dept_code) as Dept_code,
Max(Mast.purreq_desc) as purreq_desc,
Sum(Det.purreq_qty2) as purreq_qty2,
Det.Item_Code, Max(Mast.purreq_docecNo) as DocNo,
Sum(IsNull(Det.purreq_qty1,0)) as purreq_qty1,
IsNull(Det.purerq_TranNo,'') as purerq_TranNo,
IsNull(Max(Mast.purerq_adduserid),'') as Adduserid,
Max(Det.ItemPacking_Code) as ItemPacking_Code
From tbl_purreqMaster Mast
inner join tbl_purreq_detail1 Det
on Mast.Branch_code = Det.Branch_code
and Mast.purerq_id = Det.purerq_id
Where Mast.purreq_date Between #DateFrom and #DateTo
and Mast.Dept_code IN (' + REPLACE( #Department, '''','') + ')
and Mast.Branch_code = #BranchCode
and Mast.purreq_docecNo = #TransactionNumber
Group By
Mast.Branch_code, Mast.purerq_id, Det.Item_Code, Det.purerq_TranNo'
PRINT #Sql
--exec sp_executesql #Sql, #Params, #BranchCode, #DateFrom, #DateTo, #TransactionNumber
END
The best approach in SQL Server 2008 would be using table valued parameters for #DepartmentId:
Table-Valued Parameters - msdn
User-Defined Table Types - msdn
SQL Server 2008 Table-Valued Parameters and C# Custom Iterators: A Match Made In Heaven! - Leonard Lobel
Table Value Parameter Use With C# - Jignesh Trivedi
Using Table-Valued Parameters in SQL Server and .NET - Erland Sommarskog
SQLZim's solution should work. But since he doesn't mention it, I will point out that the reason for the error is this line:
Mast.purreq_date Between ' + #DateFrom + ' And ' + #DateTo + ' And
You need to CAST/CONVERT your datetime variables to nvarchar, and surround them with single-quotes.

Dynamic Stored Procedure with View name and Date as parameters

I created a stored procedure which takes a view name and date as parameters and checks if there is record for that date in the view. However, I get the following error
'Operand type clash: date is incompatible with int'.
I am hoping that if the record exists that 1 will be returned else 0 will be returned and I can use that to make a decision in another stored procedure.
The code is listed below
CREATE PROCEDURE [dbo].[usr_RecordExist]
-- Add the parameters for the stored procedure here
#ViewName SYSNAME,
#TransDate Date
--<#Param2, sysname, #p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #DATEVARCHAR nvarchar(4000);
SET #DATEVARCHAR = CONVERT(NVARCHAR, #TransDate, 103);
-- Insert statements for procedure here
DECLARE #SQLCommand NVARCHAR(MAX) =
N'SELECT COUNT(SYMBOL) FROM ' + QUOTENAME(#ViewName) + 'WHERE TRANSDATE = ' + '' + #DATEVARCHAR + '';
EXECUTE [dbo].[sp_executesql]
#sqlCommand;
END
The expression + '' does nothing, use + '''' to add a single quote.
... + '''' + #DATEVARCHAR + '''';
You are using the right tools but in the wrong way, You should not concatenate parameters but pass them as parameters to the system stored procedure sp_executesql as shown below:
CREATE PROCEDURE [dbo].[usr_RecordExist]
#ViewName SYSNAME,
#TransDate Date
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLCommand NVARCHAR(MAX);
SET #SQLCommand = N'SELECT COUNT(SYMBOL) FROM ' + QUOTENAME(#ViewName)
+ N' WHERE TRANSDATE = #TransDate';
EXECUTE [dbo].[sp_executesql] #sqlCommand
,N'#TransDate Date'
,#TransDate
END
Edit
To get the count in an output parameter you would do the following:
CREATE PROCEDURE [dbo].[usr_RecordExist]
#ViewName SYSNAME,
#TransDate Date,
#Count INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLCommand NVARCHAR(MAX);
SET #SQLCommand = N'SELECT #Count = COUNT(SYMBOL) FROM ' + QUOTENAME(#ViewName)
+ N' WHERE TRANSDATE = #TransDate';
EXECUTE [dbo].[sp_executesql] #sqlCommand
,N'#TransDate Date, #Count INT OUTPUT'
,#TransDate
,#Count OUTPUT
END
Since you used QUOTENAME() for ViewName why not QUOTENAME(#DATEVARCHAR, '''') or QUOTENAME(#DATEVARCHAR, CHAR(39))
Cosmin got it. Although I also noticed you set #DATEVARCHAR to NVARCHAR(4000) even though convert(NVARCHAR without a length defaults to 30.

Dynamic SQL Server stored procedure with table name as input param

I have the following stored procedure
CREATE PROCEDURE [dbo].[Insert]
#Service varchar(max),
#TableName varchar(100),
#Query varchar(250),
#Results varchar(max),
#CreatedDate datetime,
#ExpirationDate datetime
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE #SQL NVARCHAR(MAX), #ParmDefinition NVARCHAR(MAX)
DECLARE #q1 VARCHAR(MAX), #rez1 VARCHAR(MAX),
#date1 DATETIME, #date2 DATETIME
DECLARE #tablename VARCHAR(MAX) = #Service + '.' + #TableName
SET #SQL = N'if not EXISTS (select #q from ' + #tablename + ' where Query = #q) insert into ' + #tablename + ' values(#q, #rez, #date1, #date2)'
SET #ParmDefinition = N'#q varchar(max), #rez varchar(max),
#date1 datetime, #date2 datetime'
EXECUTE sp_executeSQL -- Dynamic T-SQL
#SQL,
#ParmDefinition,
#q = #Query,
#rez = #Results,
#date1= #CreatedDate,
#date2 = #ExpirationDate
COMMIT TRANSACTION
END
When I try to execute it, it doesn't insert anything, 0 rows
If I execute the code without the stored procedure, like a single query it inserts
Am I missing something?
There are a lot of things you have done in your question which doesnt make any sense to me, Why do you need to declare all these variables inside your procedure.
Yes true you are using parametrised query to protect yourself against sql injection attack, yet you left a hole by concatenating the object names (Table and database name), yes you will need to concatenate them but you can use QUOTENAME() function around them passed parameters and enforce sql server to put square brackets around these parameters and force sql server to treat them as nothing else but object names.
And Selecting a variable in IF EXISTS not make much sense. Select 1 which returns true if a row is found with matching criteria , and if no row is found it will simply insert a row.
Only declare variables that needs to declared, otherwise this make it look like a mess and difficult to debug. As they say Keep it simple :)
Also use appropriate data types for your parameters, #Service I believe is your database name why does it need to be a VARCHAR(MAX) data type, use the data type specific to store Sql Server Object names SYSNAME.
CREATE PROCEDURE [dbo].[Insert]
#Service SYSNAME,
#TableName SYSNAME,
#Query varchar(250),
#Results varchar(max),
#CreatedDate datetime,
#ExpirationDate datetime
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE #SQL NVARCHAR(MAX), #ParmDefinition NVARCHAR(MAX)
SET #SQL = N'IF NOT EXISTS (select 1 from ' + QUOTENAME(#Service) + '.' + QUOTENAME(#TableName)
+ N' where Query = #q) '
+ N'insert into ' + QUOTENAME(#Service) + '.' + QUOTENAME(#TableName)
+ N' values(#q, #rez, #date1, #date2)'
SET #ParmDefinition = N'#q varchar(250), #rez varchar(max),
#date1 datetime, #date2 datetime'
EXECUTE sp_executeSQL #SQL
,#ParmDefinition
,#q = #Query
,#rez = #Results
,#date1= #CreatedDate
,#date2 = #ExpirationDate
COMMIT TRANSACTION
END

T-SQL Conversion failed when converting datetime from character string

I am using the following stored procedure which takes a datetime variable as input
ALTER PROCEDURE dbo.report #createfrom as datetime=null,#createto as datetime=null
AS
BEGIN
declare #sql varchar(1000)
declare #s datetime;
declare #s1 datetime;
--set #createfrom='7/7/2014 12:00:00 AM'(my input is like in this format)
set #sql = N'select * from table1 where createdon >=''' + cast(#createfrom as datetime) + '''and createdon <=''' + cast(#createto as datetime) + ''' AND createdon is not null'
exec(#sql)
END
I don't know what I am doing wrong. createdon is a datetime variable in the table1. I have given the input parameter format within the code itself. I want to stick to cast instead of convert
I know you said you wanted to stick to cast over convert, but it might be best to format the date as yyyymmdd in your string
e.g.
ALTER PROCEDURE dbo.report #createfrom as datetime=null,#createto as datetime=null
AS
BEGIN
declare #sql varchar(1000)
declare #s datetime;
declare #s1 datetime;
--set #createfrom='7/7/2014 12:00:00 AM'(my input is like in this format)
set #sql = N'select * from table1 where createdon >=''' + CONVERT(VARCHAR(8), #createfrom, 112) + '''and createdon <=''' + CONVERT(VARCHAR(8), #createto, 112) + ''' AND createdon is not null'
exec(#sql)
END