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

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

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';

Generate script with INSERT SELECT statements from T-SQL

I have two databases in SQL Server 2014 Express, since a few days ago I am unifying both databases in such a way that there is only one left.
When I have this new database I must pass it to Azure (I don't have any experience using this technology), however, I am doing tests on my local server, so far I have created the whole scheme but I must fill out all the tables to perform tests with my application.
There are 313 tables of which many have more than 200,000 records, my question is, what is the best way to populate the database?
Because at this moment I want to test my local machine, I could fill in the tables through Tasks> Generate Script> Advanced Options (Include only data) but this information will change the day when the migration to Azure is done, therefore I must Do the same process.
So, is it possible to create an INSERT SELECT script so that it does not include records one by one and is as dynamic as possible? For example, you would have to generate an INSERT INTO similar to this:
SET IDENTITY_INSERT [SchemaX].[TableA] ON ;
INSERT INTO [SchemaX].[TableA]
(
[id]
,[fieldA]
,[fieldB]
,[fieldC])
SELECT
[id]
,[fieldA]
,[fieldB]
,[fieldC]
FROM [server].[dbname].[SchemaX].[TableA]
SET IDENTITY_INSERT [SchemaX].[TableA] OFF ;
Some tables have IDENTITY enabled so you would have to recognize which tables are like this and use SET IDENTITY_INSERT when inserting. This way you would have to link the production server and insert the information into the local server.
If there are suggestions or recommendations about another way you are welcome
Has been answered before ...
/****** Object: StoredProcedure [dbo].[procUtils_GenerateInsertProc] Script Date: 03/20/2010 13:06:13 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[procUtils_GenerateInsertProc]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[procUtils_GenerateInsertProc]
GO
/****** Object: StoredProcedure [dbo].[procUtils_GenerateInsertProc] Script Date: 03/20/2010 13:06:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--exec procUtils_GenerateInsertProc 'Whatever'
--exec sp_HelpText procUtils_GenerateInsertProc
CREATE PROCEDURE [dbo].[procUtils_GenerateInsertProc]
#TableName [varchar](50)
WITH EXECUTE AS CALLER
AS
BEGIN -- proc start
SET NOCOUNT ON;
BEGIN TRY --begin try
--FIRST SEARCH THE TABLE WHICH HAD A "Feature" in its name
--SELECT NAME FROM SYS.TABLES WHERE NAME LIKE '%Feature%'
--SELECT column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Feature' --SELECT * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Task'
--Decalre a variable to remember the position of the current delimiter
DECLARE #ProcName varchar(1000)
set #ProcName = '[dbo].[procGen_' + #TableName + '_Insert]'
DECLARE #CurrentDelimiterPositionVar INT
DECLARE #PkColumnName varchar(200)
--Decalre a variable to remember the number of rows in the table
DECLARE #Count INT
DECLARE #ColumnName varchar(300);
DECLARE #DataType varchar(50)
DECLARE #IsNullable bit
DECLARE #MaxLength INT
DECLARE #IsComputed BIT
set #IsComputed = 0
DECLARE #IsPrimaryKey BIT
set #IsPrimaryKey = 0
DECLARE #CODESTR VARCHAR(max)
--PRINT DROP PROCEDURE
set #CODESTR = ' '
--Declare the Table variable
DECLARE #ColumnNames TABLE
(
Number INT IDENTITY(1,1), --Auto incrementing Identity column
TableName varchar(300) , --the name of the table
ColumnName VARCHAR(300) , --The string value ,
DataType varchar(50) , --the datatype
IsNullable bit , --should we add =null in front
MaxLength INT , --VARCHAR(LENGHTi)
IsComputed bit , --whether or not this table is computed
IsPrimaryKey bit --whether or not this table is computed
)
--Populate the TABLE variable using some logic
-- SELECT * from INFORMATION_SCHEMA.COLUMNS
INSERT INTO #ColumnNames
(
TableName ,
ColumnName ,
DataType ,
IsNullable ,
MaxLength ,
IsComputed ,
IsPrimaryKey )
SELECT
TableName ,
ColumnName ,
DataType ,
IsNullable ,
MaxLength ,
IsComputed ,
IsPrimaryKey
from viewMeta_TableColumns
--debug where TableName = 'Whatever'
where TableName = #TableName
--SELECT column_name , Data_type , IsNullable , MaxLength
--from INFORMATION_SCHEMA.COLUMNS
--where TABLE_NAME=#TableName
--Initialize the looper variable
SET #CurrentDelimiterPositionVar = 1
--Determine the number of rows in the Table
SELECT #Count=max(Number) from #ColumnNames
--A variable to hold the currently selected value from the table
set #CODESTR = #CODESTR + 'IF OBJECT_ID(''' + #ProcName + ''') IS NOT NULL
BEGIN
DROP PROC ' + #ProcName + '
END
GO'
set #CODESTR = #CODESTR + '
/****** Object: StoredProcedure ' + #ProcName + '*/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE ' + #ProcName + '
#CurUserSessionId [int] ,
#CurPageTypeId [int] ,
#MsgOut [varchar](200) OUTPUT ,
#DebugMsgOut [varchar](200) OUTPUT,
#Ret [int] OUTPUT ,' + CHAR(13)
--#COLUMN_NAME [DATA_TYPE] (MAX_LENGTH) =NULL ,
WHILE #CurrentDelimiterPositionVar <= #Count --1st loop
BEGIN
--Load current value from the Table
SELECT #ColumnName = ColumnName FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #DataType = DataType FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #MaxLength = MaxLength FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
set #IsNullable = ( select IsNullable FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
set #IsPrimaryKey = ( select IsPrimaryKey FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
if ( #DataType = 'timestamp' or #IsComputed = 1)
begin
set #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
continue
end
set #CODESTR = #CODESTR + '#' + #ColumnName + ' ['+ #DataType + '] '
--ADD THE (200)
IF #MaxLength IS NOT NULL
BEGIN --IF #MaxLength IS NOT NULL
--xml
if #DataType <> 'xml' and #DataType <> 'sql_variant' and
#DataType <> 'text' and #DataType <> 'ntext' and #DataType <> 'image' and
#DataType <> 'hierarchyid' and #DataType <> 'bit' and #DataType <> 'varbinary' and
#DataType <> 'int' and #DataType <> 'uniqueidentifier' and #DataType <> 'tinyint' and
#DataType <> 'timestamp' and #DataType <> 'uniqueidentifier' and #DataType <> 'smallint' and
#DataType <> 'bigint' and #DataType <> 'smallmoney' and #DataType <> 'money' and
#DataType <> 'real' and #DataType <> 'smalldatetime' and #DataType <> 'datetime'
begin --those with()
if #MaxLength <> -1
SET #CODESTR = #CODESTR + '(' + CONVERT(VARCHAR , #MaxLength ) + ')'
else
SET #CODESTR = #CODESTR + '(max)'
end --those with(200)
else
begin
SET #CODESTR = #CODESTR --DO NOTHING
end
END --IF #MaxLength IS NOT NULL
IF #IsNullable = 1
SET #CODESTR = + #CODESTR + ' = NULL '
if #IsPrimaryKey = 1
SET #CODESTR = #CODESTR + ' OUTPUT '
if #CurrentDelimiterPositionVar <> #Count
SET #CODESTR = #CODESTR + ','
--DEBUGGING
--set #CODESTR = #CODESTR + '#ColumnName - ' + #ColumnName
--set #CODESTR = #CODESTR + '#DataType - ' + #DataType
--set #CODESTR = #CODESTR + '#IsNullable - ' + #IsNullable
--set #CODESTR = #CODESTR + '#MaxLength - ' + CONVERT ( VARCHAR , #MaxLength )
set #CODESTR = #CODESTR + CHAR(13)
SET #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
END
SET #CODESTR = #CODESTR + '
WITH EXECUTE AS CALLER
AS
BEGIN -- proc start
SET NOCOUNT ON;
BEGIN TRY --begin try
--
set #Ret = 1 --assume false from the beginning
declare #MsgKey [nvarchar](max)
declare #MsgTxt [nvarchar](max)
exec procUtils_GetMsgTxtByKeyAndUserSessionId
#UserSessionId =2 ,
#MsgKey = ''MsgOkTheAddingOfItemIsOk'' ,
#MsgTxt = ''''
set #MsgOut = replace (#MsgTxt , ''{0}'' , ''' + #TableName + ''' )
declare #thisProcName varchar(300)
set #thisProcName= ( SELECT OBJECT_NAME(##PROCID))
'
SET #CurrentDelimiterPositionVar = 1 --START LOOP AGAIN
set #CODESTR = #CODESTR + '
--Action !!!
INSERT INTO [dbo].[' + #TableName + ']( ' + CHAR(13)
--Loop through until all row processing is done
WHILE #CurrentDelimiterPositionVar <= #Count --2nd loop
BEGIN
--Load current value from the Table
SELECT #ColumnName = ColumnName FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #DataType = DataType FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #MaxLength = MaxLength FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
set #IsNullable = ( select IsNullable FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
set #IsPrimaryKey = ( select IsPrimaryKey FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
if #IsPrimaryKey = 1
begin -- the primary key
set #PkColumnName = #ColumnName
end --the primary key
if ( #DataType = 'timestamp' or #IsComputed = 1 or #IsPrimaryKey = 1 )
begin
set #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
continue
end
--select
if #CurrentDelimiterPositionVar <= #Count
BEGIN
set #CODESTR = #CODESTR + '[' + #ColumnName + ']' --null the codestring var
if #CurrentDelimiterPositionVar <> #Count
set #CODESTR = #CODESTR + ', --type of ' + #DataType + CHAR(13) --WITH COMMA
ELSE
set #CODESTR = #CODESTR + ' --type of ' + #DataType + CHAR(13) --NO COMMA
END -- IF SHOULD PRINT COLUMN
SET #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1;
END --eof while 2
set #CODESTR = #CODESTR + ') VALUES ( '
--AND START ALL OVER AGAIN
SET #CurrentDelimiterPositionVar = 1
--Loop through until all row processing is done
WHILE #CurrentDelimiterPositionVar <= #Count --WHILE 3
BEGIN
--Load current value from the Table
SELECT #ColumnName = ColumnName FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #DataType = DataType FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #MaxLength = MaxLength FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
set #IsNullable = ( select IsNullable FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
set #IsPrimaryKey = ( select IsPrimaryKey FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
if ( #DataType = 'timestamp' or #IsComputed = 1 or #IsPrimaryKey = 1)
begin
set #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
continue
end
set #CODESTR = #CODESTR + '#' + #ColumnName
if #CurrentDelimiterPositionVar <= #Count
BEGIN
IF #CurrentDelimiterPositionVar <> #Count
set #CODESTR = #CODESTR + ' , --type of ' + #DataType --all others with comma
else
set #CODESTR = #CODESTR + ' --type of ' + #DataType --the last one without comma
END -- IF SHOULD NOT PRINT COLUMN
--increase the counter
set #CODESTR = #CODESTR + CHAR(13)
SET #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1;
END
set nocount off
SET #CODESTR = #CODESTR + ')
SET #' + #pkColumnName + ' = ##IDENTITY
set #Ret = ##ERROR
set #DebugMsgOut = ''TODO:REMOVE INSERT OK ''
END TRY
BEGIN CATCH
EXEC #ret = [dbo].[procUtils_GetMsgTxtByKeyAndUserSessionId]
#UserSessionId = 2,
#MsgKey = N''ErrorMsgMenuRetrievalFailed'',
#MsgTxt = #MsgOut OUTPUT
set #ret = 1
set #msgOut = #MsgTxt
set #debugMsgOut = '' Error number: '' + CAST(ERROR_NUMBER() AS varchar(100)) +
''Error message: '' + ERROR_MESSAGE() + ''Error severity: '' +
CAST(ERROR_SEVERITY() AS varchar(10)) +
''Error state: '' + CAST(ERROR_STATE() AS varchar(100)) +
''XACT_STATE: '' + CAST(XACT_STATE() AS varchar(100))
-- record the error in the database
set #debugMsgOut = #debugMsgOut + #msgOut
INSERT INTO [dbo].[LogStore] ( [Date],[Thread],[Level],[Logger],[Message])
values ( getdate() , N''8'', N''DEBUG'', #thisProcName , #debugMsgOut )
END CATCH
END --procedure end
GO
'
print #codestr
END TRY --end try
BEGIN CATCH
print ' Error number: ' + CAST(ERROR_NUMBER() AS varchar(100)) +
'Error message: ' + ERROR_MESSAGE() + 'Error severity: ' +
CAST(ERROR_SEVERITY() AS varchar(1000)) +
'Error state: ' + CAST(ERROR_STATE() AS varchar(100)) +
'XACT_STATE: ' + CAST(XACT_STATE() AS varchar(100))
END CATCH
END --procedure end
--USE [Gaf]
--GO
--SELECT NAME FROM SYS.tables where name like '%Msg%'
--EXEC [dbo].[procUtils_GenerateInsertProc] #TableName = N'Whatever'
GO

How to pass datetime in dynamic query in sql?

I have written a stored procedure like this
ALTER PROCEDURE [dbo].[spLoadPendingPaymentSheetByFilter] --'2015-04-01','2015-04-02','Select-One','Select-One','Select-One',''
#FromDate as datetime,
#ToDate as datetime,
#Status as nvarchar(50),
#Remarks as nvarchar(50),
#Paymenttype as nvarchar(50),
#BillID as nvarchar(50)
AS
Declare #Where as nvarchar(max)
set #Where = '( MenifestDate BETWEEN ''' + CONVERT(VARCHAR(10),#FromDate, 101) + ''' and ''' + CONVERT(VARCHAR(10),#ToDate, 101) + ''' )'
if(#Status <> 'Select-One')
set #Where = 'Status = '+ #Status
if(#Remarks <> 'Select-One')
set #Where = #Where + 'and Remarks = '+ #Remarks
if(#Paymenttype <> 'Select-One')
set #Where = #Where + 'and PaymentType = ' + #Paymenttype
if(#BillID <> '')
set #Where = #Where + 'and BillID = '+ #BillID
Declare #SelectString as nvarchar(1000)
set #SelectString = 'SELECT MasterID,BillID, MenifestDate, FarwardingNo,ReceverCountryName,Status,Remarks,PaymentType
FROM tblMenifest
WHERE ' + #Where
exec #SelectString
When I execute it I got this error
The name 'SELECT MasterID,BillID, MenifestDate, FarwardingNo,ReceverCountryName,Status,Remarks,PaymentType FROM tblMenifest WHERE ( MenifestDate BETWEEN '04/01/2015' and '04/02/2015' )' is not a valid identifier
The MenifestDate column datatype is datetime.
I believe that you want to put EXEC(#SelectString) rather than exec #SelectString.

Best practise custom paging SQL server 2005

I'm got trouble with paging on SQL server 2005 which run query 2 times (get data and total rows). My demo proc below which base on Northwind database. Please help me to how to get total rows without query again.
CREATE PROCEDURE [dbo].[SearchEmployees]
#search nvarchar(4000)
,#orderBy varchar(200)
,#PageSize int
,#PageIndex int
,#TotalRowsNumber int output
AS
DECLARE #PageLowerBound int
DECLARE #PageUpperBound int
SET #PageLowerBound = #PageSize * #PageIndex
SET #PageUpperBound = #PageSize + #PageLowerBound
--Default order by to first column
IF (#OrderBy is null or LEN(#OrderBy) < 1)
BEGIN
SET #OrderBy = 'EmployeeID DESC'
END
-- SQL Server 2005 Paging
declare #SQL as nvarchar(4000)
declare #SQLCOUNT as nvarchar(4000)
declare #Param as nvarchar(500)
SET #SQL = 'WITH PageIndex AS ('
SET #SQL = #SQL + ' SELECT '
IF #PageSize > 0
BEGIN
SET #SQL = #SQL + ' TOP ' + convert(nvarchar, #PageUpperBound)
END
SET #SQL = #SQL + ' ROW_NUMBER() OVER (ORDER BY ' + #OrderBy + ') as RowIndex '
SET #SQL = #SQL + ' ,EmployeeID'
SET #SQL = #SQL + ', LastName'
SET #SQL = #SQL + ', FirstName'
SET #SQL = #SQL + ', Title'
SET #SQL = #SQL + ' FROM employees'
IF Len(#Search) > 0
BEGIN
SET #SQL = #SQL + ' ' + #Search
END
SET #SQL = #SQL + ') SELECT '
SET #SQL = #SQL + ' EmployeeID'
SET #SQL = #SQL + ', LastName'
SET #SQL = #SQL + ', FirstName'
SET #SQL = #SQL + ', Title'
SET #SQL = #SQL + ' FROM PageIndex '
SET #SQL = #SQL + ' WHERE RowIndex > ' + convert(nvarchar, #PageLowerBound)
IF #PageSize > 0
BEGIN
SET #SQL = #SQL + ' AND RowIndex <= ' + convert(nvarchar, #PageUpperBound)
END
--Get Row Count
SET #SQLCOUNT = 'SELECT #TotalRowsNumber = count(EmployeeID)
FROM employees'
SET #Param = N'#Search nvarchar(2000),#TotalRowsNumber INT OUTPUT'
IF LEN(#Search) > 0
BEGIN
SET #SQLCOUNT = #SQLCOUNT + #Search
END
exec sp_executesql #SQL
exec sp_executesql #SQLCOUNT, #Param,#Search=#Search,#TotalRowsNumber = #TotalRowsNumber OUT
Thanks in advance!
Try Like this, See it as an example
CREATE Procedure usp_GetBookings
#pageIndex int,
#pageSize tinyint
as
;with CTE as
(
Select Distinct ROW_NUMBER() over( order by ssi.SSItineraryID desc) as seq ,Count(*) over() as TotalRow,ssi.SSItineraryID
from SightSeeingItinerary as ssi
)
select * from CTE
where cte.seq between (#pageIndex-1) * #pageSize+1 and ((#pageIndex-1) * #pageSize +(#pageSize))

SQL Case Statement trouble

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)