SQL Case Statement trouble - sql

im not the best when it comes to SQL still learning the ropes.
I have a Stored procedure in my SQL server manager 2008.
USE [ShaftData]
GO
/****** Object: StoredProcedure [dbo].[GetSalesBuyers] Script Date: 03/23/2012 08:13:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetSalesBuyers]
#Cdisc varchar(255),
#bcs varchar(255),
#From date,
#Too date
AS
SELECT i.Acct,
i.Name,
i.Document,
i.Part,
i.Qty,
i.Unit,
dbo.NEWPareto.Pareto,
i.pg,
dbo.MyPgTable.PgName,
i.[DateTime],
i.BinSeqNo,
i.cdisc,
i.bcs
FROM
OPENQUERY(SACBAUTO, 'SELECT dbo.iHeads.acct,
dbo.iHeads.name,
dbo.iLines.Document,
dbo.iLines.Part,
dbo.iLines.Pg,
dbo.iLines.Qty,
dbo.iLines.unit,
dbo.iHeads.[DateTime],
dbo.iLines.BinSeqNo,
dbo.Customer.cdisc,
dbo.Customer.Bcs
FROM Autopart.dbo.iheads INNER JOIN Autopart.dbo.iLines ON
Autopart.dbo.Iheads.document = autopart.dbo.iLines.document
INNER JOIN Autopart.dbo.Customer ON Autopart.dbo.iheads.acct
= Autopart.dbo.customer.keycode
GROUP By dbo.iHeads.acct,
dbo.iHeads.name,
dbo.iLines.Document,
dbo.iLines.Part,
dbo.iLines.Pg,
dbo.iLines.Qty,
dbo.iLines.unit,
dbo.iHeads.[DateTime],
dbo.iLines.BinSeqNo,
dbo.Customer.cdisc,
dbo.Customer.bcs
') i
left JOIN
dbo.NEWPareto
ON
i.Part collate SQL_Latin1_General_CP1_CI_AS = dbo.NEWPareto.Part
left JOIN
dbo.MyPgTable
ON
i.pg collate SQL_Latin1_General_CP1_CI_AS = dbo.MyPgTable.[pGroup]
WHERE
(i.[DateTime] BETWEEN #From AND #Too)
AND i.cdisc = #Cdisc
AND i.bcs != #bcs
AND i.pg != '60'
AND i.pg != '61'
AND i.pg != '62'
GROUP BY i.Acct,
i.Name,
i.Document,
i.Part,
i.Qty,
i.Unit,
dbo.NEWPareto.Pareto,
i.pg,
dbo.MyPgTable.PgName,
i.[DateTime],
i.BinSeqNo,
i.cdisc,
i.bcs
What I need is a condition in the Where clause. particular this row "AND i.bcs != #bcs".
What happens is IF i pass an Empty string to my param i want this row to exist and run in the where clause.
Else IF i dont pass anything (null), i need the row to not exist(not run).
I have played around but all im getting is red lines everywhere when i attempt to create.
Does anyone have an idea? am i close in my methodology? can it be done? or is there a easy mode way that im over looking.
Many thanks

Optional parameters are constructed like this:
WHERE (#bcs is null OR i.bcs != #bcs)
If you send null every row is selected; if you send anything else, only non-matching rows are selected. You shouldn't worry about performance because Sql Server is very good with constant expressions, and if it evaluates to one it will be suppressed.
USE [ShaftData]
GO
/****** Object: StoredProcedure [dbo].[GetSalesBuyers] Script Date: 03/23/2012 08:13:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetSalesBuyers]
#Cdisc varchar(255),
#bcs varchar(255),
#From date,
#Too date
AS
SELECT i.Acct,
i.Name,
i.Document,
i.Part,
i.Qty,
i.Unit,
dbo.NEWPareto.Pareto,
i.pg,
dbo.MyPgTable.PgName,
i.[DateTime],
i.BinSeqNo,
i.cdisc,
i.bcs
FROM
OPENQUERY(SACBAUTO, 'SELECT dbo.iHeads.acct,
dbo.iHeads.name,
dbo.iLines.Document,
dbo.iLines.Part,
dbo.iLines.Pg,
dbo.iLines.Qty,
dbo.iLines.unit,
dbo.iHeads.[DateTime],
dbo.iLines.BinSeqNo,
dbo.Customer.cdisc,
dbo.Customer.Bcs
FROM Autopart.dbo.iheads INNER JOIN Autopart.dbo.iLines ON
Autopart.dbo.Iheads.document = autopart.dbo.iLines.document
INNER JOIN Autopart.dbo.Customer ON Autopart.dbo.iheads.acct
= Autopart.dbo.customer.keycode
GROUP By dbo.iHeads.acct,
dbo.iHeads.name,
dbo.iLines.Document,
dbo.iLines.Part,
dbo.iLines.Pg,
dbo.iLines.Qty,
dbo.iLines.unit,
dbo.iHeads.[DateTime],
dbo.iLines.BinSeqNo,
dbo.Customer.cdisc,
dbo.Customer.bcs
') i
left JOIN
dbo.NEWPareto
ON
i.Part collate SQL_Latin1_General_CP1_CI_AS = dbo.NEWPareto.Part
left JOIN
dbo.MyPgTable
ON
i.pg collate SQL_Latin1_General_CP1_CI_AS = dbo.MyPgTable.[pGroup]
WHERE
(i.[DateTime] BETWEEN #From AND #Too)
AND i.cdisc = #Cdisc
AND (#bcs is null OR i.bcs != #bcs)
AND i.pg != '60'
AND i.pg != '61'
AND i.pg != '62'
GROUP BY i.Acct,
i.Name,
i.Document,
i.Part,
i.Qty,
i.Unit,
dbo.NEWPareto.Pareto,
i.pg,
dbo.MyPgTable.PgName,
i.[DateTime],
i.BinSeqNo,
i.cdisc,
i.bcs

The only way i know of that you can do that (exactly what you want is to use dynamic sql), that being said, its not pretty. You chuck your whole proc in a string variable then build it up as needed. then execute it in the end. I'll update this post with a sample in a bit.
look at this link as to how the syntax looks normally.
Don't judge me I don't code like this normally
but this is the part you're looking for
IF (ISNULL(#bcs,0) <> 0)
SET #SQL = #SQL + ' AND i.bcs != '+#bcs + CHAR(13)
Your updated proc.
USE [ShaftData]
GO
/****** Object: StoredProcedure [dbo].[GetSalesBuyers] Script Date: 03/23/2012 08:13:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetSalesBuyers]
#Cdisc varchar(255),
#bcs varchar(255),
#From date,
#Too date
AS
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = ' SELECT i.Acct, i.Name, i.Document, i.Part, i.Qty, i.Unit, dbo.NEWPareto.Pareto, i.pg,' + CHAR(13)
SET #SQL = #SQL + ' dbo.MyPgTable.PgName,i.[DateTime],i.BinSeqNo,i.cdisc,i.bcs' + CHAR(13)
SET #SQL = #SQL + ' FROM ' + CHAR(13)
SET #SQL = #SQL + ' OPENQUERY(SACBAUTO, ''SELECT dbo.iHeads.acct, dbo.iHeads.name,dbo.iLines.Document,dbo.iLines.Part, ' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.Pg,dbo.iLines.Qty,dbo.iLines.unit,dbo.iHeads.[DateTime], dbo.iLines.BinSeqNo, ' + CHAR(13)
SET #SQL = #SQL + ' dbo.Customer.cdisc,dbo.Customer.Bcs ' + CHAR(13)
SET #SQL = #SQL + ' FROM Autopart.dbo.iheads INNER JOIN Autopart.dbo.iLines ON ' + CHAR(13)
SET #SQL = #SQL + ' Autopart.dbo.Iheads.document = autopart.dbo.iLines.document' + CHAR(13)
SET #SQL = #SQL + ' INNER JOIN Autopart.dbo.Customer ON Autopart.dbo.iheads.acct ' + CHAR(13)
SET #SQL = #SQL + ' = Autopart.dbo.customer.keycode' + CHAR(13)
SET #SQL = #SQL + ' GROUP By dbo.iHeads.acct,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iHeads.name,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.Document,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.Part,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.Pg,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.Qty,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.unit,' + CHAR(13)
SET #SQL = #SQL + ' dbo.iHeads.[DateTime],' + CHAR(13)
SET #SQL = #SQL + ' dbo.iLines.BinSeqNo,' + CHAR(13)
SET #SQL = #SQL + ' dbo.Customer.cdisc,' + CHAR(13)
SET #SQL = #SQL + ' dbo.Customer.bcs' + CHAR(13)
SET #SQL = #SQL + ' '') i' + CHAR(13)
SET #SQL = #SQL + 'left JOIN' + CHAR(13)
SET #SQL = #SQL + 'dbo.NEWPareto' + CHAR(13)
SET #SQL = #SQL + 'ON ' + CHAR(13)
SET #SQL = #SQL + 'i.Part collate SQL_Latin1_General_CP1_CI_AS = dbo.NEWPareto.Part ' + CHAR(13)
SET #SQL = #SQL + 'left JOIN' + CHAR(13)
SET #SQL = #SQL + 'dbo.MyPgTable ' + CHAR(13)
SET #SQL = #SQL + 'ON ' + CHAR(13)
SET #SQL = #SQL + ' i.pg collate SQL_Latin1_General_CP1_CI_AS = dbo.MyPgTable.[pGroup]' + CHAR(13)
SET #SQL = #SQL + 'WHERE' + CHAR(13)
SET #SQL = #SQL + ' (i.[DateTime] BETWEEN ''+#From+'' AND ''+#Too+'') ' + CHAR(13)
SET #SQL = #SQL + ' AND i.cdisc = '+ #Cdisc + CHAR(13)
IF (ISNULL(#bcs,0) <> 0)
SET #SQL = #SQL + ' AND i.bcs != '+#bcs + CHAR(13)
SET #SQL = #SQL + ' AND i.pg != ''60''' + CHAR(13)
SET #SQL = #SQL + ' AND i.pg != ''61''' + CHAR(13)
SET #SQL = #SQL + ' AND i.pg != ''62''' + CHAR(13)
SET #SQL = #SQL + ' GROUP BY i.Acct,' + CHAR(13)
SET #SQL = #SQL + ' i.Name, ' + CHAR(13)
SET #SQL = #SQL + ' i.Document, ' + CHAR(13)
SET #SQL = #SQL + ' i.Part, ' + CHAR(13)
SET #SQL = #SQL + ' i.Qty, ' + CHAR(13)
SET #SQL = #SQL + ' i.Unit, ' + CHAR(13)
SET #SQL = #SQL + ' dbo.NEWPareto.Pareto, ' + CHAR(13)
SET #SQL = #SQL + ' i.pg,' + CHAR(13)
SET #SQL = #SQL + ' dbo.MyPgTable.PgName, ' + CHAR(13)
SET #SQL = #SQL + ' i.[DateTime],' + CHAR(13)
SET #SQL = #SQL + ' i.BinSeqNo,' + CHAR(13)
SET #SQL = #SQL + ' i.cdisc,' + CHAR(13)
SET #SQL = #SQL + ' i.bcs' + CHAR(13)
EXEC(#SQL)

Related

how to create a dynamic update query with variables?

I am trying to create the below dynamic update query with some variables and for some reason, it's not working inside the stored procedure. Can someone suggest to me where I am doing wrong and what's the best practice by avoiding the SQL Injection as well?
DECLARE #SQL NVARCHAR(MAX)
DECLARE #COLUMN1 NVARCHAR(10)
DECLARE #COLUMN2 NVARCHAR(10)
DECLARE #TABLENAME NVARCHAR(10)
SET #SQL = 'UPDATE TL
SET '+ #COLUMN1 + '= AB.COLUMN1,'
+ #COLUMN2 + '= AB.COLUMN2
FROM' + #TABLENAME + ' TL
JOIN ABACUS AB
ON TL.REF = AB.REF
AND TL.SUBS = AB.SUBS
WHERE ' + #COLUMN1 + ' IS NULL
AND ' + #COLUMN2 +' IS NULL';
SET #COLUMN1 = (SELECT CONCAT('USER_ID', '8'))
SET #COLUMN2 = (SELECT CONCAT('USER_ID', '6'))
SET #TABLENAME = 'POLICYREF';
EXEC sys.sp_executesql #SQL, #TABLENAME, #COLUMN1, #COLUMN2;
SET #TABLENAME = 'USERREF';
EXEC sys.sp_executesql #SQL, #TABLENAME, #COLUMN1, #COLUMN2;
You need dynamic SQL, not parameters. You can't parameterize column names or table names. So something like:
DECLARE #SQL NVARCHAR(MAX)
DECLARE #COLUMN1 NVARCHAR(10) = 'USER_ID8'
DECLARE #COLUMN2 NVARCHAR(10) = 'USER_ID6'
DECLARE #TABLENAME NVARCHAR(10) = 'POLICYREF'
SET #SQL = 'UPDATE TL
SET '+ quotename(#COLUMN1) + '= AB.COLUMN1,'
+ quotename(#COLUMN2) + '= AB.COLUMN2
FROM ' + quotename(#TABLENAME) + ' TL
JOIN ABACUS AB
ON TL.REF = AB.REF
AND TL.SUBS = AB.SUBS
WHERE ' + quotename(#COLUMN1) + ' IS NULL
AND ' + quotename(#COLUMN2) +' IS NULL';
EXEC (#SQL)
SET #TABLENAME NVARCHAR(10) = 'USERREF'
SET #SQL = 'UPDATE TL
SET '+ quotename(#COLUMN1) + '= AB.COLUMN1,'
+ quotename(#COLUMN2) + '= AB.COLUMN2
FROM ' + quotename(#TABLENAME) + ' TL
JOIN ABACUS AB
ON TL.REF = AB.REF
AND TL.SUBS = AB.SUBS
WHERE ' + quotename(#COLUMN1) + ' IS NULL
AND ' + quotename(#COLUMN2) +' IS NULL';
EXEC (#SQL)
Not a huge fan of this but, given that, create a stored procedure OR re-arrange to execute each after updating the #SQL, here is the stored procedure example:
Note this is missing production level things like a transaction, TRY CATCH etc. and is only for an basic UNTESTED example
CREATE PROCEDURE dbo.MyFunQuery
#SQL NVARCHAR(MAX),
#COLUMN1 NVARCHAR(10),
#COLUMN2 NVARCHAR(10),
#TABLENAME NVARCHAR(10)
AS
BEGIN
SET #SQL = 'UPDATE TL
SET '+ #COLUMN1 + '= AB.COLUMN1,'
+ #COLUMN2 + '= AB.COLUMN2
FROM ' + #TABLENAME + ' AS TL
JOIN ABACUS AS AB
ON TL.REF = AB.REF
AND TL.SUBS = AB.SUBS
WHERE ' + #COLUMN1 + ' IS NULL
AND ' + #COLUMN2 + ' IS NULL;';
EXECUTE ( #SQL );
END
--Now to call it:
DECLARE #COLUMN1 NVARCHAR(10) = 'USER_ID8',
#COLUMN2 NVARCHAR(10) = 'USER_ID6';
EXECUTE dbo.MyFunQuery #COLUMN1, #COLUMN2, #TABLENAME='POLICYREF';
EXECUTE dbo.MyFunQuery #COLUMN1, #COLUMN2, #TABLENAME='USERREF';

nvarchar limits to 8000 characters within stored procedure

I have a problem with my stored procedure :
ALTER PROCEDURE [dbo].[Sp_Calculate_TimeSheet_Global_Info]
#DateDebut date,
#DateFin date,
#UserId int,
#CA varchar(10)
AS
BEGIN
DECLARE #TaskQuery nvarchar(MAX) ;
DECLARE #OPENQUERY nvarchar(MAX),#TSQL nvarchar(MAX), #LinkedServer nvarchar(MAX);
DECLARE #DateDebut1 date;
DECLARE #DateFin1 date;
DECLARE #UserId1 int;
DECLARE #Query nvarchar(MAX);
DECLARE #cond1 nvarchar(MAX);
DECLARE #cond2 nvarchar(MAX);
DECLARE #cond3 nvarchar(MAX);
DECLARE #cond4 nvarchar(MAX);
DECLARE #cond5 nvarchar(MAX);
DECLARE #cond6 nvarchar(MAX);
DECLARE #cond7 nvarchar(MAX);
DECLARE #cond8 nvarchar(MAX);
DECLARE #cond9 nvarchar(MAX);
DECLARE #cond10 nvarchar(MAX);
DECLARE #cond11 nvarchar(MAX);
DECLARE #cond12 nvarchar(MAX);
DECLARE #cond13 nvarchar(MAX);
DECLARE #op nvarchar(MAX);
DECLARE #where nvarchar(MAX);
DECLARE #exec nvarchar(MAX);
SET NOCOUNT ON;
SET #LinkedServer = 'TASK'
SET #OPENQUERY = 'SELECT * FROM OPENQUERY('+ #LinkedServer + ','''
SET #DateDebut1 = #DateDebut;
SET #DateFin1 = #DateFin;
SET #UserId1 = #UserId;
set #op = ' UNION ';
set #where = ' where 1=1 ';
set #cond1 = ' LEFT OUTER JOIN tickets tkt ON tkt.ttick_id = h.ttick_id ';
set #cond2 = ' RIGHT OUTER JOIN tickets tkt ON tkt.ttick_id = h.ttick_id ';
set #cond3 = ' LEFT OUTER JOIN ptasks tsk ON h.ptask_id = tsk.ptask_id ';
set #cond4 = ' RIGHT OUTER JOIN tasks tsk ON h.ptask_id = tsk.ptask_id ';
set #cond5 = ' LEFT OUTER JOIN phases ph ON tsk.phase_id = ph.phase_id ';
set #cond6 = ' RIGHT OUTER JOIN tasks tsk ON h.ptask_id = tsk.ptask_id ';
set #cond7 = ' LEFT OUTER JOIN projects p ON ph.proj_id = p.proj_id ';
set #cond8 = ' RIGHT OUTER JOIN projects p ON ph.proj_id = p.proj_id ';
set #cond9 = ' and h.hours_spent >= str_to_date(''''' + convert(varchar,#DateDebut,103) + ''''', ''''%d/%m/%Y'''')';
set #cond10 = ' and h.hours_spent <= str_to_date(''''' + convert(varchar,#DateFin,103) + ''''', ''''%d/%m/%Y'''')';
set #cond11 = ' and h.user_id=' + cast(#UserId as varchar);
set #cond12 = ' and
( ph.phase_name like ''''' + '%' + #CA +'%' +''''' and (p.proj_name not like ''''' + '%' + #CA +'%' +''''' or p.proj_name is null) ) or
( (ph.phase_name not like ''''' + '%' + #CA +'%' +''''' or ph.phase_name is null) and (p.proj_name not like ''''' + '%' + #CA +'%' +''''' or p.proj_name is null) and tsk.ptask_name like ''''' + '%' + #CA +'%' +''''') or
( (ph.phase_name not like ''''' + '%' + #CA +'%' +''''' or ph.phase_name is null) and (p.proj_name not like ''''' + '%' + #CA +'%' +''''' or p.proj_name is null) and (tsk.ptask_name not like ''''' + '%' + #CA +'%' +''''' or tsk.ptask_name is null) and tkt.ttick_name like ''''' + '%' + #CA +'%' +''''') or
( (p.proj_name not like ''''' + '%' + #CA +'%' +''''' or p.proj_name is null) and tsk.ptask_name like ''''' + '%' + #CA +'%' +''''' and (tsk.phase_id is null or tsk.phase_id =-1) ) or
( (p.proj_name not like ''''' + '%' + #CA +'%' +''''' or p.proj_name is null) and tkt.ttick_name like ''''' + '%' + #CA +'%' +''''')
';
set #cond13 = ''') src';
SET #TaskQuery =N' SELECT h.hours_id , h.hours_spent as TimeSheet_Date, h.hours_hours as Hour_Number,h.hours_note as Hour_Note,(case when h.ttick_id is null or h.ttick_id=-1 then tsk.ptask_name else tkt.ttick_name end) as Task_Ticket_Libelle,(case when h.ttick_id is null or h.ttick_id=-1 then h.ptask_id else h.ttick_id end) as Task_Ticket_Id,h.proj_id as Project_Id,(case when h.ttick_id is null or h.ttick_id=-1 then 1 else 0 end) as Is_Task,h.user_id as User_Id,p.proj_name as Project_Name, u.user_uname as User_Name from users u RIGHT OUTER JOIN user_hours h on u.user_id=h.user_id ' ;
SET #Query = #TaskQuery ;
SET #TaskQuery = #Query+ #cond1 ;
SET #TaskQuery = #TaskQuery + #op + #Query + #cond2 ;
SET #Query = #TaskQuery ;
SET #TaskQuery = #Query + #cond3 ;
SET #TaskQuery =#TaskQuery + #op + #Query + #cond4 ;
SET #Query = #TaskLandQuery ;
SET #TaskQuery = #Query + #cond5 ;
SET #TaskQuery =#TaskQuery + #op + #Query + #cond6 ;
SET #Query = #TaskQuery ;
SET #TaskQuery = #Query + #cond7 ;
SET #TaskQuery =#TaskQuery + #op + #Query + #cond8 ;
SET #TaskQuery = #TaskQuery + #where ;
IF(#DateDebut is not null)
BEGIN
SET #TaskQuery = #TaskQuery + #cond9 ;
END
IF(#DateFin is not null)
BEGIN
SET #TaskQuery =#TaskQuery + #cond10 ;
END
IF(#UserId is not null)
BEGIN
SET #TaskQuery = #TaskQuery + #cond11 ;
END
IF(#CA is not null)
BEGIN
SET #TaskQuery = #TaskQuery + #cond12 ;
END
set #TaskQuery = #TaskQuery + #cond13 ;
set #exec = #OPENQUERY+#TaskQuery;
delete from [dbo].[Timesheet_Global_Info];
insert into [dbo].[Timesheet_Global_Info](
[hours_id]
,[TimeSheet_Date]
,[Hour_Number]
,[Hour_Note]
,[Task_Ticket_Libelle]
,[Task_Ticket_Id]
,[Project_Id]
,[Is_Task]
,[User_Id]
,[Project_Name]
,[User_Name]
)
EXEC (#exec) ;
END
When I execute this procedure, I get this error:
Msg 103, Level 15, State 1, Line 3
The string that starts with SELECT h.hours_id, h.hours_spent have TimeSheet_Date, h.hours_hours have Hour_Number, h.hours_note have Hour_Note, (CASE WHEN h.ttick 'is too long. The maximum length is 8000.
the exception is due to this line EXEC (#exec) ; .
So I need to know
What is the reason of this error?
How can I fix it?
You are using OPENQUERY and as per MSDN, the max size for query is 8KB i.e. 8000 characters which is exceeding in your query.
OPENQUERY ( linked_server ,'query' )
' query ' Is the query string executed in the linked server. The
maximum length of the string is 8 KB.
Why not use sp_executesql?
EXEC sp_executesql #exec
As I can see #exec is nvarchar(max), you can pass it without a problem.
On 64-bit servers, the size of the string is limited to 2 GB, the maximum size of nvarchar(max).
EDIT
Use sp_executesql INSTEAD of OPENQUERY
DECLARE #paramDef nvarchar(max) = '#TaskQuery nvarchar(max)'
SELECT #exec = 'INSERT INTO [dbo].[Timesheet_Global_Info] EXEC '+QUOTENAME(#LinkedServer)+'.database.dbo.sp_executesql #TaskQuery',
EXEC sp_executesql #exec, #paramDef, #TaskQuery=#TaskQuery
You exceed the max length character, in this type of case you have to split your dynamic query in multiple part and execute by combine.
Declare #Query1 VARCHAR(MAX),#Query2 VARCHAR(MAX)
SET #Query1='SELECT * FROM'
SET #Query2=' Employee'
EXEC (#Query1+#Query2)
In your case may be
EXEC (#OPENQUERY+#TaskQuery);
If you still got same error, please split your variables into more...

Dynamic sql with CASE expression

SET #SQL =
'SELECT
CaseStatus =
CASE Level1Status
WHEN 1100 THEN ''Case Submitted to QC''
WHEN 1200 THEN ''Pending QC''
WHEN 1400 THEN ''Passed QC''
END,
I'm currently having problems with the dynamic sql/case expression above , as I can't seem to put strings inside dynamic sql, does anyone happen to have a solution to fixing this
EDIT
AS
BEGIN
DECLARE #SQL nvarchar(4000)
SET #SQL =
'SELECT
CaseStatus =
CASE Level1Status
WHEN 1100 THEN ''Case Submitted to QC''
WHEN 1200 THEN ''Pending QC''
WHEN 1400 THEN ''Passed QC''
END,
CaseStartDateTime,
CaseEndDateTime,
StatusName,
Cell_NameDescription,
QCAnalystName,
AnalystName,
Upload_Datetime,
Requesting_Entity,
Legal_Entity_TypeDescription,
HighPriorityDescription,
DD_Level_RequiredDescription,
CountryDscr,
Maintable.KYCCaseId AS KYCCaseId
FROM
UACTc75760ab10784b51b585f082d4b25223 AS MI,
UACT175e55161660402692a53a4cdeb89bd6 AS MainTable,
UACT5996d6e5151245cab24e4e76e3e53540 AS Statuses,
UACTde5f05df6c5f4872a1e57b3cf8368301 AS AddressDetails
WHERE
(
MI.CaseStartDateTime BETWEEN ' + quotename(convert(varchar(10), #CaseStartDateTime, 120), '''') + ' AND ' + quotename(convert(varchar(10), #CaseEndDateTime, 120), '''') +
' OR
MI.CaseEndDateTime BETWEEN ' + quotename(convert(varchar(10), #CaseStartDateTime, 120), '''') + ' AND ' + quotename(convert(varchar(10), #CaseEndDateTime, 120), '''') +
' )
AND
MI.KYCCase_Id = MainTable.KYCCaseId'
IF #StatusName IS NOT NULL AND ltrim(rtrim(#StatusName)) != N''
SET #SQL = #SQL + '
AND
Statuses.SourceStatus = MainTable.Level1Status
AND
Statuses.StatusName = ' + quotename(#StatusName, '''')
IF #CountryDscr IS NOT NULL AND ltrim(rtrim(#CountryDscr)) != N''
SET #SQL = #SQL + '
AND
AddressDetails.CountryDscr = ' + quotename(#CountryDscr, '''')
IF #CellDscr IS NOT NULL AND ltrim(rtrim(#CellDscr)) != N''
SET #SQL = #SQL + '
AND
MainTable.Cell_NameDescription = ' + quotename(#CellDscr, '''')
IF #QCAnalystName IS NOT NULL AND ltrim(rtrim(#QCAnalystName)) != N''
SET #SQL = #SQL + '
AND
MainTable.QCAnalystName = ' + quotename(#QCAnalystName, '''')
IF #AnalystName IS NOT NULL AND ltrim(rtrim(#AnalystName)) != N''
SET #SQL = #SQL + '
AND
MainTable.AnalystName = ' + quotename(#AnalystName, '''')
IF #RequestingEntity IS NOT NULL AND ltrim(rtrim(#RequestingEntity)) != N''
SET #SQL = #SQL + '
AND
MainTable.Requesting_Entity = ' + quotename(#RequestingEntity, '''')
IF #EntityType IS NOT NULL AND ltrim(rtrim(#EntityType)) != N''
SET #SQL = #SQL + '
AND
MainTable.Legal_Entity_TypeDescription = ' + quotename(#EntityType, '''')
IF #HighPriority IS NOT NULL AND ltrim(rtrim(#HighPriority)) != N''
SET #SQL = #SQL + '
AND
MainTable.HighPriorityDescription = ' + quotename(#HighPriority, '''')
IF #DDLevelRequired IS NOT NULL AND ltrim(rtrim(#DDLevelRequired)) != N''
SET #SQL = #SQL + '
AND
MainTable.DD_Level_RequiredDescription = ' + quotename(#DDLevelRequired, '''')
EXEC sp_executesql #SQL
This is the entire code, The error I'm getting is
Msg 156, Level 15, State 1, Line 32
Incorrect syntax near the keyword 'Case'.
This is working fine .
Create Table #Level1Status(Id int identity ,Level1Status int)
Insert INto #Level1Status(Level1Status) values(1100),(1200),(1400)
Declare #SQL Nvarchar(Max)
SET #SQL =
'SELECT
CaseStatus =
CASE Level1Status
WHEN 1100 THEN ''Case Submitted to QC''
WHEN 1200 THEN ''Pending QC''
WHEN 1400 THEN ''Passed QC''
END from #Level1Status';
Exec SP_ExecuteSQL #SQL
Since you are concatenate your #SQL string with local variable "#xxx", in case any of thease may null, It want give any output so use ISNULL() or COALESCE() at concatenation with all local vaiable you used.

Trim Spaces inside whole Database

How to trim spaces inside all table's column values from particular Database?
It has to LTrim & RTrim spaces inside row column values from all tables in Database. How Can I do that?
Try below one
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL = #SQL + 'UPDATE T SET T.'+IC.COLUMN_NAME +
' = LTRIM(RTRIM(' + IC.COLUMN_NAME+'))
FROM '+ IT.TABLE_SCHEMA + '.[' + IT.TABLE_NAME +
'] AS T ;' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES IT
JOIN INFORMATION_SCHEMA.COLUMNS IC ON IT.TABLE_NAME = IC.TABLE_NAME
AND IT.TABLE_SCHEMA = IC.TABLE_SCHEMA AND IT.TABLE_TYPE = 'BASE TABLE'
and IC.DATA_TYPE in( 'varchar','char','nvarchar','nchar')
Exec (#SQL)
Please try using below script to trim the space by specifying the table name
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableName NVARCHAR(100)
SET #TableName = 'TableName'
SELECT #SQL = COALESCE(#SQL + ',[', '[') +
COLUMN_NAME + ']=RTRIM([' + COLUMN_NAME + '])'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableName
--AND DATA_TYPE = 'varchar' /*If any condition in my case its varchar*/
SET #SQL = 'UPDATE [' + #TableName + '] SET ' + #SQL
PRINT #SQL
You can write as:
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL = #SQL + 'UPDATE ' + IT.TABLE_SCHEMA + '.['
+ IT.TABLE_NAME + ']'
+ 'SET '+IC.COLUMN_NAME
+ ' = LTRIM(RTRIM(' + IC.COLUMN_NAME+')) ' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES IT
JOIN INFORMATION_SCHEMA.COLUMNS IC ON IT.TABLE_NAME = IC.TABLE_NAME
AND IT.TABLE_SCHEMA = IC.TABLE_SCHEMA
EXEC (#SQL)
This Solved my issue :
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL += 'UPDATE ' + IT.TABLE_SCHEMA + '.'
+ QUOTENAME(IT.TABLE_NAME) +
+ 'SET '+IC.COLUMN_NAME
+ ' = LTRIM(RTRIM(' + IC.COLUMN_NAME+')) ' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES IT
JOIN INFORMATION_SCHEMA.COLUMNS IC ON IT.TABLE_NAME = IC.TABLE_NAME
AND IT.TABLE_SCHEMA = IC.TABLE_SCHEMA AND IC.DATA_TYPE in ('nvarchar','char','varchar','nchar')
EXEC (#SQL)
Reference : Deepshikha's answer.. Thanks Deepshikha
Godd.. i almost sweated doing this :D
This will loop through all tables in your DB, and generate & execute query to trim all columns in it
DECLARE #tablename as nvarchar(100)=''
Declare #sql varchar(max) = ''
DECLARE tempcursor CURSOR FOR
SELECT TABLE_NAME
FROM information_schema.tables
where TABLE_TYPE = 'BASE TABLE'
OPEN tempcursor
FETCH NEXT FROM tempcursor
INTO #tablename
WHILE ##FETCH_STATUS = 0
BEGIN
if exists (select c.name from sys.columns c inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename and collation_name is not null)
BEGIN
set #sql = #sql + 'update '+ #tablename + ' SET '
select #sql = #sql + c.name + '= LTRIM(RTRIM(' + c.name + ')) ,'
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename
and collation_name is not null
and is_ansi_padded = 1
and is_computed = 0
SET #sql = LEFT(#sql, LEN(#sql) - 1)
END
FETCH NEXT FROM tempcursor
INTO #tablename
END
CLOSE tempcursor;
DEALLOCATE tempcursor;
print #sql
EXEC (#sql)
Remember the limit of 8000 characters for SQL Query string variable (i.e. #sql)

I am not able to execute the stored procedure. It is throwing an error

I am not able to execute the stored procedure. It is throwing an error
Invalid column name ' UNION ALL '.
Any one can help
USE [M511Symaster]
GO
/****** Object: StoredProcedure [dbo].[CostCenterWiseBudget] Script Date: 09/04/2015 16:59:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CostCenterWiseBudget]
#CoCode char(4),
#DivCode char(3),
#MinYear int,
#Maxyear int,
#Fromdate Date,
#Todate Date
AS
Declare #lnLoop int,
#Sql varchar(max)
set #lnLoop = #MinYear
set #Sql = ''
BEGIN
SET NOCOUNT ON;
while #MinYear <= #Maxyear
BEGIN
if #lnLoop < #MinYear
BEGIN
set #Sql = #Sql + " UNION ALL "
END
set #Sql = "SELECT a.cost_code,b.name, SUM(a.amount) AS Actual_amt,b.Budgeted_Amt as Budgeted_Amt,"
set #Sql = #Sql + " Actual_amt - Budgeted_Amt as var_Amt "
set #Sql = #Sql + " FROM " + #CoCode + #DivCode + ".dbo.FactTrans a,"
set #Sql = #Sql + #CoCode + "Symaster.dbo.CostMst b where a.cost_code = b.code AND "
set #Sql = #Sql + CONVERT(VARCHAR(8),#Fromdate ,1) + " <= CONVERT(VARCHAR(8),a.Vou_dt ,1)"
set #Sql = #Sql + " AND "
set #Sql = #Sql + CONVERT(VARCHAR(8),#Todate ,1) + " <= CONVERT(VARCHAR(8),a.Vou_dt ,1)"
set #Sql = #Sql + " GROUP BY a.cost_code,b.code,b.name "
SET #MinYear = #MinYear + 1
END
EXEC (#Sql)
END
You should use single quote instead of double quote in the procedure.
USE [M511Symaster]
GO
/****** Object: StoredProcedure [dbo].[CostCenterWiseBudget] Script Date: 09/04/2015 16:59:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Alter PROCEDURE [dbo].[CostCenterWiseBudget]
#CoCode char(4),
#DivCode char(3),
#MinYear int,
#Maxyear int,
#Fromdate Date,
#Todate Date
AS
Declare #lnLoop int,
#Sql varchar(max)
set #lnLoop = #MinYear
set #Sql = ''
BEGIN
SET NOCOUNT ON;
while #MinYear <= #Maxyear
BEGIN
if #lnLoop < #MinYear
BEGIN
set #Sql = #Sql + ' UNION ALL '
END
set #Sql = 'SELECT a.cost_code,b.name, SUM(a.amount) AS Actual_amt,b.Budgeted_Amt as Budgeted_Amt,'
set #Sql = #Sql + ' Actual_amt - Budgeted_Amt as var_Amt '
set #Sql = #Sql + ' FROM ' + #CoCode + #DivCode + '.dbo.FactTrans a,'
set #Sql = #Sql + #CoCode + 'Symaster.dbo.CostMst b where a.cost_code = b.code AND '
set #Sql = #Sql + CONVERT(VARCHAR(8),#Fromdate ,1) + ' <= CONVERT(VARCHAR(8),a.Vou_dt ,1)'
set #Sql = #Sql + ' AND '
set #Sql = #Sql + CONVERT(VARCHAR(8),#Todate ,1) + ' <= CONVERT(VARCHAR(8),a.Vou_dt ,1)'
set #Sql = #Sql + ' GROUP BY a.cost_code,b.code,b.name '
SET #MinYear = #MinYear + 1
END
EXEC (#Sql)
END
In the above query " (double quotes) were used instead of ' (single quotes). In addition, the UNION ALL was misplaced in the Dynamic Query.
Try this instead:
USE [M511Symaster]
GO
/****** Object: StoredProcedure [dbo].[CostCenterWiseBudget] Script Date: 09/04/2015 16:59:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CostCenterWiseBudget]
#CoCode char(4),
#DivCode char(3),
#MinYear int,
#Maxyear int,
#Fromdate Date,
#Todate Date
AS
Declare #lnLoop int,
#Sql varchar(max)
set #lnLoop = #MinYear
set #Sql = ''
BEGIN
SET NOCOUNT ON;
if #MinYear <= #Maxyear
begin
set #Sql = 'SELECT a.cost_code,b.name, SUM(a.amount) AS Actual_amt,b.Budgeted_Amt as Budgeted_Amt,'
set #Sql = #Sql + ' Actual_amt - Budgeted_Amt as var_Amt '
set #Sql = #Sql + ' FROM ' + #CoCode + #DivCode + '.dbo.FactTrans a,'
set #Sql = #Sql + #CoCode + 'Symaster.dbo.CostMst b where a.cost_code = b.code AND '
set #Sql = #Sql + CONVERT(VARCHAR(8),#Fromdate ,1) + ' <= CONVERT(VARCHAR(8),a.Vou_dt ,1)'
set #Sql = #Sql + ' AND '
set #Sql = #Sql + CONVERT(VARCHAR(8),#Todate ,1) + ' <= CONVERT(VARCHAR(8),a.Vou_dt ,1)'
set #Sql = #Sql + ' GROUP BY a.cost_code,b.code,b.name '
SET #MinYear = #MinYear + 1
end
while #MinYear <= #Maxyear
BEGIN
set #Sql = #Sql + ' UNION ALL '
set #Sql = 'SELECT a.cost_code,b.name, SUM(a.amount) AS Actual_amt,b.Budgeted_Amt as Budgeted_Amt,'
set #Sql = #Sql + ' Actual_amt - Budgeted_Amt as var_Amt '
set #Sql = #Sql + ' FROM ' + #CoCode + #DivCode + '.dbo.FactTrans a,'
set #Sql = #Sql + #CoCode + 'Symaster.dbo.CostMst b where a.cost_code = b.code AND '
set #Sql = #Sql + CONVERT(VARCHAR(8),#Fromdate ,1) + ' <= CONVERT(VARCHAR(8),a.Vou_dt ,1)'
set #Sql = #Sql + ' AND '
set #Sql = #Sql + CONVERT(VARCHAR(8),#Todate ,1) + ' <= CONVERT(VARCHAR(8),a.Vou_dt ,1)'
set #Sql = #Sql + ' GROUP BY a.cost_code,b.code,b.name '
END
EXEC (#Sql)
END