execute stored procedure with a loop and combine results - sql

I have a stored procedure in SQL server 2008.
This stored procedure (lets call it sp1), accepts ID (string),FromDate,ToDate and returns col1,col2,col3
I tried to alter sp1 to accept IDList (ID1,ID2,...,IDn), but it is way over my head.
I need help with creating a new SP (lets call it SP2) that accepts IDList,FromDate,ToDate , and then loops with the id list and calls SP1 and union the results.
I hope I am clear...
This is the original SP, If you can make it accept UnitIMEIList it will also be great:
CREATE PROCEDURE [dbo].[GetGeneratorsReport]
#UnitIMEI varchar(15),
#DateFrom [datetime],
#DateTo [datetime]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #mycur CURSOR
DECLARE #GeneratorId int
DECLARE #FieldId int
DECLARE #SensorName nvarchar(50)
DECLARE #StateNO bit
DECLARE #ReadingDate [datetime]
DECLARE #Value bit
DECLARE #FirstRun bit
DECLARE #SDate [datetime]
DECLARE #UnitName nvarchar(50)
--SET #UnitIMEI='358484004085845'
SET #UnitName = (SELECT TOP 1 NickName FROM Vehicles WHERE UnitIEMI = #UnitIMEI)
IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#GeneratorsTempTable')) BEGIN DROP TABLE #GeneratorsTempTable END
CREATE TABLE #GeneratorsTempTable (
SensorId int,
UnitIMEI varchar(15),
UnitName nvarchar(50),
SensorName nvarchar(50),
FromDate [datetime],
ToDate [datetime]
)
SET #mycur = CURSOR
FOR
SELECT 104+[GPIO], [Name], [StateNO]
FROM [VehicleTrack].[dbo].[UnitSensors]
WHERE [UnitIMEI]=#UnitIMEI AND Type=3
OPEN #mycur
FETCH NEXT FROM #mycur INTO #FieldId, #SensorName, #StateNO
WHILE ##FETCH_STATUS = 0
BEGIN
SET #FirstRun = 1
SET #SDate = NULL
DECLARE messageCur CURSOR
FOR
SELECT ProtocolMessages.Date, convert(bit, AdditionalReadings.Value) AS Value
FROM ProtocolMessages INNER JOIN
AdditionalReadings ON ProtocolMessages.Id = AdditionalReadings.MessageId
WHERE (ProtocolMessages.UnitIEMI = #UnitIMEI) AND AdditionalReadings.FieldId = #FieldId AND ProtocolMessages.Date >= #DateFrom AND ProtocolMessages.Date <= #DateTo
ORDER BY ProtocolMessages.Date
OPEN messageCur
FETCH NEXT FROM messageCur INTO #ReadingDate, #Value
WHILE ##FETCH_STATUS = 0
BEGIN
IF (#Value > 1)
SET #Value = #Value - 2
IF (#FirstRun = 1 AND #SDate IS NULL)
BEGIN -- the first run
SET #FirstRun = 0 -- flip the bit for all future runs
IF (#Value = #StateNO)
SET #SDate = #ReadingDate
END
ELSE -- all subsequent runs after the first
BEGIN
IF (#SDate IS NULL)
BEGIN
IF (#Value = #StateNO)
SET #SDate = #ReadingDate
END
ELSE
BEGIN
IF (#Value <> #StateNO)
BEGIN
-- Store
INSERT INTO #GeneratorsTempTable ([SensorId], [UnitIMEI], [UnitName], [SensorName] , [FromDate], [ToDate]) VALUES (#FieldId - 104, #UnitIMEI, #UnitName, #SensorName, #SDate, #ReadingDate)
SET #SDate = NULL
END
END
END
FETCH NEXT FROM messageCur INTO #ReadingDate, #Value
END
CLOSE messageCur
DEALLOCATE messageCur
IF (#Value = #StateNO)
BEGIN
INSERT INTO #GeneratorsTempTable ([SensorId], [UnitIMEI], [UnitName], [SensorName] , [FromDate], [ToDate]) VALUES (#FieldId - 104, #UnitIMEI, #UnitName, #SensorName, #SDate, GETUTCDATE())
END
FETCH NEXT FROM #mycur INTO #FieldId, #SensorName, #StateNO
END
DEALLOCATE #mycur
SELECT * FROM #GeneratorsTempTable
END
GO
Thanks

For the benefit of other google users :)
I did it all by myself !
I created a database named 'SandBox' for that.
Create a sample table :
USE [SandBox]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tblStudentGrades](
[StudentGradeID] [bigint] IDENTITY(1,1) NOT NULL,
[StudentID] [bigint] NOT NULL,
[TestID] [bigint] NOT NULL,
[TestDate] [date] NOT NULL,
[TestGrade] [int] NULL
) ON [PRIMARY]
GO
Put some data (If you are lazy:) ) :
USE [SandBox]
GO
SET IDENTITY_INSERT [dbo].[tblStudentGrades] ON
INSERT [dbo].[tblStudentGrades] ([StudentGradeID], [StudentID], [TestID], [TestDate], [TestGrade]) VALUES (1, 1, 1, CAST(0x6E390B00 AS Date), 60)
INSERT [dbo].[tblStudentGrades] ([StudentGradeID], [StudentID], [TestID], [TestDate], [TestGrade]) VALUES (2, 1, 2, CAST(0x70390B00 AS Date), 80)
INSERT [dbo].[tblStudentGrades] ([StudentGradeID], [StudentID], [TestID], [TestDate], [TestGrade]) VALUES (3, 2, 1, CAST(0x6E390B00 AS Date), 90)
INSERT [dbo].[tblStudentGrades] ([StudentGradeID], [StudentID], [TestID], [TestDate], [TestGrade]) VALUES (4, 2, 2, CAST(0x70390B00 AS Date), 100)
INSERT [dbo].[tblStudentGrades] ([StudentGradeID], [StudentID], [TestID], [TestDate], [TestGrade]) VALUES (5, 3, 1, CAST(0x6E390B00 AS Date), 95)
INSERT [dbo].[tblStudentGrades] ([StudentGradeID], [StudentID], [TestID], [TestDate], [TestGrade]) VALUES (6, 3, 2, CAST(0x0F230100 AS Date), 98)
SET IDENTITY_INSERT [dbo].[tblStudentGrades] OFF
Create the SP that accepts a single id:
* This is just a sample ... don't forget it - I know I can send multiple IDs as a parameter...
USE [SandBox]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spGetStudentGrades]
#StudentID bigint
AS
BEGIN
SELECT * FROM [SandBox].[dbo].[tblStudentGrades]
WHERE StudentID = #StudentID;
END
GO
Now for the new SP that will allow multiple execution of the above SP (exactly what I was looking for):
USE [SandBox]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spGetMultiple]
#StudentIDList varchar(100)
AS
BEGIN
DECLARE #StudentID VARCHAR(10)
--------------------------------------------------
-- Create a temporary table to hold the results:
--------------------------------------------------
IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#tblTemporaryGrades')) BEGIN DROP TABLE #tblTemporaryGrades END
CREATE TABLE #tblTemporaryGrades (
StudentGradeID bigint,
StudentID bigint,
TestID bigint,
TestDate date,
TestGrade int
)
--------------------------------------------------
-- Add a comma to the end of the ID list,
-- so the last ID will be also included.
SET #StudentIDList = #StudentIDList + ',' ;
---------------------------------------------------
WHILE CHARINDEX(',', #StudentIDList) > 0
BEGIN
-- STEP 1 :
-- Extract the current StudentID we want to get from the original SP
SET #StudentID = SUBSTRING(#StudentIDList, 1, ( CHARINDEX(',', #StudentIDList) - 1 ))
PRINT '#StudentID = ' + #StudentID;
-- STEP 2 :
-- Gather the data using the original SP
INSERT INTO #tblTemporaryGrades EXEC spGetStudentGrades #StudentID
-- STEP 3 :
-- Update the student ID to exclude the last StudentID we worked with
SET #StudentIDList = SUBSTRING(#StudentIDList, CHARINDEX(',', #StudentIDList) + 1, LEN(#StudentIDList))
PRINT 'NEW #StudentIDList = ' + #StudentIDList;
END
SELECT * FROM #tblTemporaryGrades
END
GO
Feel like testing it ?
Go ahead:
USE [SandBox]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[spGetMultiple]
#StudentIDList = N'3,2,1'
SELECT 'Return Value' = #return_value
GO
Good luck all !

Related

How to use DECLARE in a stored procedure

I am creating a stored procedure that will create a new row in a table once the record is new and update the existing record if the record is present in the table.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [procedurename]
(#UserName [varchar](50),
#UserEmail [varchar](50),
#Role [varchar](30),
#Status [varchar](30),
#CreationDate [Date])
AS
DECLARE #countRec INT
SELECT #countRec = COUNT(*)
FROM [Synapse].[tablename]
WHERE [UserName] = #Username
BEGIN
IF (#countRec = 0)
BEGIN
INSERT INTO [Synapse].[tablename] ([UserName], [UserEmail], [Role], [Status], [CreationDate])
VALUES (#Username, #UserEmail, #Role, #Status, #CreationDate)
END
ELSE (#countRec > 0)
BEGIN
UPDATE [Synapse].[tablename]
SET [Role] = #Role,
[Status] = #Status,
[CreationDate] = #CreationDate
WHERE [UserName] = #Username
INSERT INTO [Synapse].[tablename]
END
And I am getting the following error:
Msg 103010, Level 16, State 1, Line 8
Parse error at line: 39, column: 7: Incorrect syntax near '#countRec'.
I am not sure why it is pointing at the countRec variable. I was able to use a similar set-up without any issues. Does anyone know what I am doing wrong here?
Kind regards,
Rutger
You have a number of syntax errors - mostly: you need to start your proedure with a BEGIN before doing any declarations or selects - and you're missing an END at the end.
Try this:
CREATE PROCEDURE [procedurename]
(#UserName [varchar](50),
#UserEmail [varchar](50),
#Role [varchar](30),
#Status [varchar](30),
#CreationDate [Date])
AS
BEGIN -- put the "BEGIN" before you start declaring and selecting stuff
DECLARE #countRec INT
SELECT #countRec = COUNT(*)
FROM [Synapse].[tablename]
WHERE [UserName] = #Username
IF (#countRec = 0)
BEGIN
INSERT INTO [Synapse].[tablename] ([UserName], [UserEmail], [Role], [Status], [CreationDate])
VALUES (#Username, #UserEmail, #Role, #Status, #CreationDate)
END
-- either you have just an "ELSE" here - or if you want to
-- check another conditions, you need to use "ELSE IF ....."
ELSE IF (#countRec > 0)
BEGIN
UPDATE [Synapse].[tablename]
SET [Role] = #Role,
[Status] = #Status,
[CreationDate] = #CreationDate
WHERE [UserName] = #Username
END
END -- this was missing

Setting the order for executing the stored procedures within a master stored procedure

I have a master stored procedure in which have many sub stored procedures, say 10 stored procedures.
What I want is if I specify that stored procedure 1, stored procedure 2, then only these 2 stored procedures should be executed, the other 8 should not be executed.
And if I don't specify any value for the ordering, then it should execute all the stored procedures.
Someone please tell me how to do it? Is there any way to implement it?
I need 1 parameter which could be comma separated. That is if we specify 1,2 in a parameter then it will execute stored procedures 1 and 2.
SET QUOTED_IDENTIFIER ON;
GO
SET ANSI_NULLS ON;
GO
SET NOCOUNT ON;
GO
CREATE PROCEDURE dbo.CI_ILR_Indicator_Master
(
#StartYear INT,
#EndYear INT
)
AS
BEGIN
--Temptable '#TempILR' is created, which contains the common data needed for all the indicator calculation of 'ILR'
--Executing the SP [dbo.CI_ILR_Indicator_VRQ_WBL Indicators] for the ILR Indicator group
--'ILR VRQ WBL' for Indicators (8,9,10)
EXEC SP1 #StartYear,#EndYear
EXEC SP2 #StartYear,#EndYear
EXEC SP3 #StartYear,#EndYear
EXEC SP4 #StartYear,#EndYear
EXEC SP5 #StartYear,#EndYear
EXEC SP6 #StartYear,#EndYear
EXEC SP7 #StartYear,#EndYear
EXEC SP8 #StartYear,#EndYear
EXEC SP9 #StartYear,#EndYear
EXEC SP10 #StartYear,#EndYear
END
This is how my SP looks..
CREATE PROCEDURE [dbo].[Master Sp]
(
#INT_sp1 int= null,
#INT_sp2 int= null,
#INT_sp3 int= null,
#INT_sp4 int= null,
#INT_sp5 int= null,
#INT_sp6 int= null,
#INT_sp7 int= null,
#INT_sp8 int= null,
#INT_sp9 int= null,
#INT_sp10 int= null
)
AS
BEGIN
SET NOCOUNT ON;
if #INT_sp1 is not null
exec dbo.sp1
if #INT_sp2 is not null
exec dbo.sp2
......
END
GO
Follow this stored Proc,it will helps you
CREATE PROCEDURE [dbo].[Usp_RunSp] --give sp list like 'Sp1,Sp2,Sp3' else by default
(
#vr_SpList VARCHAR(1000)=NULL,
#i_StartYear INT ,
#i_EndYear INT
)
AS
BEGIN
BEGIN try
IF Object_id('tempdb..#FinalResult')IS NOT NULL
DROP TABLE #finalresult
IF Object_id('tempdb..#RunSp')IS NOT NULL
DROP TABLE #runsp
IF Object_id('tempdb..#TotalSPToRun')IS NOT NULL
DROP TABLE #totalsptorun
CREATE TABLE #finalresult
(
Rno INT,
Spnamelist VARCHAR(100)
)
CREATE TABLE #totalsptorun
(
Id INT IDENTITY,
Spnamelist VARCHAR(100)
)
DECLARE #RunSql NVARCHAR(max)
DECLARE #Sp_List TABLE
(
Spnamelist VARCHAR(100)
)
INSERT INTO #Sp_List
SELECT #vr_SpList
SELECT split.a.value('.', 'nvarchar(1000)') AS SpnameList
INTO #runsp
FROM (SELECT Cast('<S>' + Replace(Spnamelist, ',', '</S><S>')
+ '</S>' AS XML) AS Data
FROM #Sp_List) AS A
CROSS apply data.nodes('S') AS Split(a)
INSERT INTO #totalsptorun --add your 10 sp names instead of sp1,sp2
(Spnamelist)
SELECT 'Sp1' UNION ALL
SELECT 'Sp2' UNION ALL
SELECT 'Sp3' UNION ALL
SELECT 'Sp4' UNION ALL
SELECT 'Sp5' UNION ALL
SELECT 'Sp6' UNION ALL
SELECT 'Sp7' UNION ALL
SELECT 'Sp8' UNION ALL
SELECT 'Sp9' UNION ALL
SELECT 'S10'
IF #vr_SpList IS NOT NULL
BEGIN
SET #RunSql =' INSERT INTO #FinalResult
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS RNo,
R.SpnameList
FROM #TotalSPToRun R
INNER JOIN #RunSp L
ON L.SpnameList=R.SpnameList'
EXEC(#RunSql)
END
IF #vr_SpList IS NULL
BEGIN
SET #RunSql =' INSERT INTO #FinalResult
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS RNo,
R.SpnameList
FROM #TotalSPToRun R '
--PRINT #RunSql
EXEC(#RunSql)
END
DECLARE #SqlRun NVARCHAR(max),
#SpName VARCHAR(100),
#minID INT,
#maxId INT
SELECT #minID = Min(Rno),#maxId = Max(Rno)
FROM #Finalresult
WHILE ( #minID <= #maxId )
BEGIN
SELECT #SpName = Spnamelist
FROM #finalresult
WHERE Rno = #minID
SET #SqlRun=N'EXECUTE ' + #SpName+' '+CAST(#i_StartYear AS VARCHAR)+','+CAST(#i_EndYear AS VARCHAR)
SET #minID=#minID + 1
PRINT #SqlRun
EXEC(#SqlRun)
END
END try
BEGIN catch
SELECT Error_number() AS ErrorNumber,
Error_severity() AS ErrorSeverity,
Error_state() AS ErrorState,
Error_procedure() AS ErrorProcedure,
Error_line() AS ErrorLine,
Error_message() AS ErrorMessage
END catch
END

Equivalent set base query for the cursor

I have a stored procedure which uses cursor. I want to know any equivalent set base query for the cursor.
USE [T04_676]
GO
/****** Object: StoredProcedure [dbo].[proc_InsertAssessmentCast] Script Date: 3/16/2016 7:43:44 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Capgemini>
-- Create date: <12-Mar-2016>
-- Description: <This Stored procedure is used to create table 'assessment_cast' and fill data into it>
-- exec proc_InsertAssessmentCast
-- =============================================
CREATE PROCEDURE [dbo].[proc_InsertAssessmentCast]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #tmpTableNames TABLE
(
TableName varchar(250),
PatientID_ITM_ID INT,
date_ITM_ID INT,
KVSTableType INT,
Association_ITM_ID INT
)
DECLARE #tmpAssociatedColumn_ITM_ID TABLE
(
InitialTableMasterID INT
)
DECLARE #AssociatedColumn_ITM_ID INT
DECLARE #AssociatedColumn_ITM_ID_List VARCHAR(400)
DECLARE #TableName varchar(250)
DECLARE #PatientID_ITM_ID INT
DECLARE #date_ITM_ID INT
DECLARE #KVSTableType INT
DECLARE #Association_ITM_ID INT
DECLARE #SameRowID INT
DECLARE #T04PKID INT
DECLARE #T04CMID INT
DECLARE #T04Value VARCHAR(250)
DECLARE #sqlT04Value nvarchar(MAX)
DECLARE #tmpValue TABLE
(
Value varchar(250)
)
CREATE TABLE #tmpAssessmentRows
(
PrimaryKeyTableID INT,
ColumnID INT,
Value varchar(250)
)
DECLARE #sqlSameRowID NVARCHAR(250),#sqlT04_Value_Query NVARCHAR(MAX)
DECLARE #ColWithAliasTbl TABLE (colID int,colName varchar(50) )
DECLARE #PivotTBL VARCHAR(MAX)=''
DECLARE #ColID VARCHAR(MAX)
DECLARE #ChkPtntID VARCHAR(MAX)
DECLARE #ColName VARCHAR(MAX)
DECLARE #AllColID VARCHAR(MAX) = ''
DECLARE #AllColName VARCHAR(MAX) = ''
BEGIN TRY
IF EXISTS (SELECT name FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tmpAssesessment_Cast]') AND type in (N'U'))
BEGIN
DROP TABLE tmpAssesessment_Cast
END
IF EXISTS (SELECT name FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[assessment_cast]') AND type in (N'U'))
BEGIN
DROP TABLE assessment_cast
END
IF NOT EXISTS (SELECT name FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[InitialOriginalDataKVS]') AND name = N'ix_InitialOriginalDataKVS_SameRowID')
CREATE NONCLUSTERED INDEX [ix_InitialOriginalDataKVS_SameRowID] ON [dbo].[InitialOriginalDataKVS]
(
[InitialTableMasterID] ASC
)
INCLUDE ( [SameRowID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
--Insert Table names of tables having both columns: patientID and date
INSERT INTO #tmpTableNames
SELECT ITM1.TableName,ITM1.InitialTableMasterID,ITM2.InitialTableMasterID,ITM1.KVSTableType,0 AS Association_ITM_ID
FROM InitialTableMaster ITM1
INNER JOIN InitialTableMaster ITM2 ON ITM1.TableName=ITM2.TableName
WHERE ITM1.ColumnName ='patientID' AND ITM2.ColumnName ='date'
--Set Association for the column in table
UPDATE #tmpTableNames
SET Association_ITM_ID=Association
FROM InitialTableMaster ITM
INNER JOIN #tmpTableNames tmpTableNames ON tmpTableNames.TableName=ITM.TableName
WHERE Association <> 0 AND tmpTableNames.KVSTableType=1
--Do not consider tables with KVSTableType=1 having no Association
DELETE FROM #tmpTableNames
WHERE KVSTableType=1 AND Association_ITM_ID=0
SELECT TOP 1
#PatientID_ITM_ID=PatientID_ITM_ID,
#date_ITM_ID=date_ITM_ID,
#Association_ITM_ID=Association_ITM_ID
FROM #tmpTableNames
----Logic to get the associated columns ID values in list
INSERT INTO #tmpAssociatedColumn_ITM_ID
SELECT InitialTableMasterID
FROM InitialTableMaster
WHERE Association=#Association_ITM_ID and InitialTableMasterID <>#Association_ITM_ID
WHILE ((SELECT COUNT(1) FROM #tmpAssociatedColumn_ITM_ID)>0)
BEGIN
SELECT TOP 1 #AssociatedColumn_ITM_ID=InitialTableMasterID
FROM #tmpAssociatedColumn_ITM_ID
SET #AssociatedColumn_ITM_ID_List= ISNULL(#AssociatedColumn_ITM_ID_List,'') + '['+ CONVERT(NVARCHAR,#AssociatedColumn_ITM_ID) + '],'
DELETE FROM #tmpAssociatedColumn_ITM_ID
WHERE InitialTableMasterID=#AssociatedColumn_ITM_ID
END
SET #AssociatedColumn_ITM_ID_List=SUBSTRING(#AssociatedColumn_ITM_ID_List,0,LEN(#AssociatedColumn_ITM_ID_List))
print '1'
print #AssociatedColumn_ITM_ID_List
SET #sqlT04Value='
SELECT COALESCE('+ #AssociatedColumn_ITM_ID_List + ') as ''Value''
FROM [InitialOriginalDataKVS]
PIVOT(max(Value)
FOR InitialTableMasterID IN ('+ #AssociatedColumn_ITM_ID_List +')) AS PVTTable
WHERE SameRowID = '
--DECLARE GetSameRowIDs CURSOR STATIC LOCAL FOR
DECLARE GetSameRowIDs CURSOR FORWARD_ONLY READ_ONLY FAST_FORWARD FOR
SELECT sameRowID FROM InitialOriginalDataKVS
WHERE InitialTableMasterID=#PatientID_ITM_ID AND NewFlag=1
GROUP BY sameRowID
OPEN GetSameRowIDs
FETCH NEXT FROM GetSameRowIDs
INTO #SameRowID
WHILE (##FETCH_STATUS = 0) -- Inner cursor loop
BEGIN
SET #T04PKID=0
SELECT #T04PKID=PrimaryKeyTableID
FROM dbo.PrimaryKeyForPredicting
WHERE PatientID IN (SELECT value FROM dbo.InitialOriginalDataKVS
WHERE SameRowID=#SameRowID AND InitialTableMasterID=#PatientID_ITM_ID)
AND [date] IN (SELECT value FROM dbo.InitialOriginalDataKVS
WHERE SameRowID=#SameRowID AND InitialTableMasterID=#date_ITM_ID)
--Process only if the combination of patientID and date exists in 'PrimaryKeyForPredicting'
IF(ISNULL(#T04PKID,0)<> 0)
BEGIN
DELETE FROM #tmpValue
SET #T04Value=NULL
SET #sqlSameRowID=CONVERT(VARCHAR(50),#SameRowID)
SET #sqlT04_Value_Query=#sqlT04Value+#sqlSameRowID
INSERT INTO #tmpValue
EXEC sp_executesql #sqlT04_Value_Query
IF((SELECT COUNT(1) FROM #tmpValue)>0)
BEGIN
SELECT #T04Value=Value FROM #tmpValue
END
SELECT #T04CMID = ColumnID
FROM [dbo].[PrimaryKeyForModeling]
WHERE ColumnName IN (SELECT value FROM [InitialOriginalDataKVS]
WHERE SameRowID=#SameRowID AND InitialTableMasterID=#Association_ITM_ID)
IF(ISNULL(#T04CMID,0)<> 0)
BEGIN
INSERT INTO #tmpAssessmentRows
(PrimaryKeyTableID,ColumnID,Value)
VALUES(#T04PKID,#T04CMID,#T04Value)
END
END
FETCH NEXT FROM GetSameRowIDs
INTO #SameRowID
END
CLOSE GetSameRowIDs
DEALLOCATE GetSameRowIDs
SELECT PKP.PatientID,PKP.[Date],ColumnID,Value into tmpAssesessment_Cast
FROM #tmpAssessmentRows AR
INNER JOIN dbo.PrimaryKeyForPredicting PKP ON AR.PrimaryKeyTableID=PKP.PrimaryKeyTableID
order by PKP.PrimaryKeyTableID
-----------------------------
--Logic for assesment_cast table creation from the data in rows
------------------------------
INSERT INTO #ColWithAliasTbl
SELECT ColumnID,[ColumnName]
FROM [dbo].[PrimaryKeyForModeling]
WHERE ColumnID IN (SELECT Distinct ColumnID FROM tmpAssesessment_Cast)
While EXISTS (SELECT colID,colName FROM #ColWithAliasTbl)
Begin
SELECT #ColID='['+CONVERT(VARCHAR,min(colID))+'],' FROM #ColWithAliasTbl
SELECT #ColName='['+CONVERT(VARCHAR,colID)+'] AS '''+ colName+''',' FROM #ColWithAliasTbl WHERE colID = (SELECT min(colID) FROM #ColWithAliasTbl)
SET #AllColID = #AllColID+#ColID
SET #AllColName = #AllColName+#ColName
DELETE from #ColWithAliasTbl Where colID = (SELECT min(colID) FROM #ColWithAliasTbl)
End
print #AllColID
print LEN(#AllColID)
SET #AllColID = SUBSTRING(#AllColID, 1, LEN(#AllColID)-1)
print '2'
SET #AllColName = SUBSTRING(#AllColName, 1, LEN(#AllColName)-1)
print '3'
SET #PivotTBL = 'SELECT patientID, [date], '+#AllColName +
' into assessment_cast FROM (SELECT * FROM [dbo].[tmpAssesessment_Cast]) KVS
PIVOT (Max(Value) FOR [ColumnID] IN ('+#AllColID+') ) pvt order by 1'
EXEC(#PivotTBL)
--Drop temporary table
IF OBJECT_ID('dbo.tmpAssesessment_Cast', 'U') IS NOT NULL
DROP TABLE dbo.tmpAssesessment_Cast;
DROP TABLE #tmpAssessmentRows
--Return the assessment_cast table data
SELECT * FROM assessment_cast
END TRY
BEGIN CATCH
-- Raise an error with the details of the exception
DECLARE #ErrMsg nvarchar(4000), #ErrSeverity INT,#ErrorState INT
SELECT #ErrSeverity=ERROR_SEVERITY(),
#ErrMsg= ERROR_MESSAGE(),
#ErrorState=ERROR_STATE();
RAISERROR(#ErrMsg, #ErrSeverity, #ErrorState)
EXEC sp_addmessage 50005,#ErrSeverity,#ErrMsg,'us_english', 'with_log'
END CATCH
END
GO

Requesting verification of this arguably complex SQL script

I'd appreciate it if some SQL experts can take a look at this script and verify if it will work or if it can be improved in anyway (performance, ease, etc.). So, considering the following:
Leads {
LeadId INT,
SourceId TINYINT,
PersonId INT,
PhoneId INT,
EmailId INT,
AddressId INT,
ImporterId SMALLINT,
ImportedDateTime DATETIME2(7)
}
Duplicates {
DuplicateId INT,
SourceId TINYINT,
LeadId INT,
ImporterId SMALLINT,
DuplicatedDateTime DATETIME2(7)
}
How will this script perform:
-- Outside variables provided as part of a stored procedure
DECLARE #SourceId TINYINT;
DECLARE #ImporterId SMALLINT;
PRINT 'Deleting the CSVTemp table if it exists';
IF ((SELECT CASE WHEN OBJECT_ID('CSVTemp') IS NOT NULL THEN 1 ELSE 0 END) = 1)
BEGIN
DROP TABLE [CSVTemp];
END
PRINT 'Creating the CSVTemp table';
CREATE TABLE [CSVTemp](
[FirstName] NVARCHAR(48),
[LastName] NVARCHAR(48),
[Phone] BIGINT,
[Email] VARCHAR(96),
[Street] VARCHAR(64),
[Zip] INT
);
PRINT 'Performing a BULK insert into CSVTemp';
BULK INSERT [CSVTemp] FROM '{File}.csv' WITH (FIELDTERMINATOR = ',', ROWTERMINATOR = '\n');
PRINT 'Adding IDENTITY column to CSVTemp';
ALTER TABLE [CSVTemp] ADD [Id] INT IDENTITY(1,1) NOT NULL;
PRINT 'Adding PK constraint to CSVTemp';
ALTER TABLE [CSVTemp] ADD CONSTRAINT [PK_CSVTemp] PRIMARY KEY CLUSTERED(
[Id] ASC
) WITH(
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY];
PRINT 'Counting CSVTemp rows';
DECLARE #Count INT = (SELECT COUNT(1) FROM [CSVTemp]);
PRINT 'Declaring internal variables';
DECLARE #I INT = 0;
PRINT 'Looping through rows in CSVTemp';
WHILE (#I < (#Count + 1))
BEGIN
BEGIN TRANSACTION
DECLARE #FirstName NVARCHAR(48);
DECLARE #LastName NVARCHAR(48);
DECLARE #Phone BIGINT;
DECLARE #Email VARCHAR(96);
DECLARE #Street VARCHAR(64);
DECLARE #Zip INT;
SELECT #FirstName = [FirstName],
#LastName = [LastName],
#Phone = [Phone],
#Email = [Email],
#Street = [Street],
#Zip = [Zip] FROM [CSVTemp] WHERE ([Id] = #I);
DECLARE #LeadId INT = (
SELECT [Leads].[LeadId]
FROM [People].[Person]
JOIN [Management].[Leads] ON ([Leads].[PersonId] = [Person].[PersonId])
JOIN [Communication].[Phones] ON ([Leads].[PhoneId] = [Phones].[PhoneId])
WHERE (([Person].[FirstName] LIKE #FirstName) OR ([Person].[LastName] LIKE #LastName))
AND ([Phones].[PhoneId] = #Phone)
);
IF (#LeadId IS NOT NULL)
BEGIN
INSERT INTO [Management].[Duplicates]([SourceId], [LeadId], [ImporterId]) VALUES(#SourceId, #LeadId, #ImporterId);
END
ELSE
BEGIN
INSERT INTO [People].[Person]([FirstName], [LastName]) VALUES(#FirstName, #LastName);
DECLARE #PersonId INT = ##IDENTITY;
INSERT INTO [Communication].[Phones]([PhoneTypeId], [Number]) VALUES(6, #Phone);
DECLARE #PhoneId INT = ##IDENTITY;
INSERT INTO [Communication].[Emails]([Address]) VALUES(#Email);
DECLARE #EmailId INT = ##IDENTITY;
INSERT INTO [Location].[Addresses]([PostalCode], [Street]) VALUES(#Zip, #Street);
DECLARE #AddressId INT = ##IDENTITY;
INSERT INTO [Management].[Leads]([SourceId], [PersonId], [PhoneId], [EmailId], [AddressId], [ImporterId]) VALUES(#SourceId, #PersonId, #PhoneId, #EmailId, #AddressId, #ImporterId);
END
COMMIT
SET #I = (#I + 1);
END
PRINT 'Deleting CSVTemp table';
DROP TABLE [CSVTemp];
UPDATE
#Will/#Mitch, I don't know if you guys are still around, but I ended up finalizing the script by converting the WHILE loop to work with a CURSOR. I tested the script by looping through 10.5k rows and it took 3-5 seconds, which is fine with me. Sadly, I thought I fully understood what #Will was saying about the sets, but I couldn't come up with a way to improve it, so I'll leave it as is. If anyone is willing to give me an example script about what #Will was talking about, I would appreciate it, if not, then thank you #Will and #Mitch for the help so far.
Anyway, here's the updated WHILE loop that uses a CURSOR now.
DECLARE #Id INT = 0;
DECLARE C1 CURSOR READ_ONLY FOR (SELECT [Id] FROM [CSVTemp]);
OPEN C1;
FETCH NEXT FROM C1 INTO #Id;
WHILE (##FETCH_STATUS = 0)
BEGIN
BEGIN TRANSACTION
DECLARE #FirstName NVARCHAR(48);
DECLARE #LastName NVARCHAR(48);
DECLARE #Phone BIGINT;
DECLARE #Email VARCHAR(96);
DECLARE #Street VARCHAR(64);
DECLARE #Zip INT;
SELECT #FirstName = [FirstName],
#LastName = [LastName],
#Phone = [Phone],
#Email = [Email],
#Street = [Street],
#Zip = [Zip] FROM [CSVTemp] WHERE ([Id] = #Id);
DECLARE #LeadId INT = (
SELECT [Leads].[LeadId]
FROM [People].[Person]
JOIN [Management].[Leads] ON ([Leads].[PersonId] = [Person].[PersonId])
JOIN [Communication].[Phones] ON ([Leads].[PhoneId] = [Phones].[PhoneId])
WHERE (([Person].[FirstName] LIKE #FirstName) AND ([Person].[LastName] LIKE #LastName))
AND ([Phones].[Number] = #Phone)
);
IF (#LeadId IS NOT NULL)
BEGIN
INSERT INTO [Management].[Duplicates]([SourceId], [LeadId], [ImporterId]) VALUES (#SourceId, #LeadId, #ImporterId);
END
ELSE
BEGIN
INSERT INTO [People].[Person]([FirstName], [LastName]) VALUES(#FirstName, #LastName);
DECLARE #PersonId INT = SCOPE_IDENTITY();
INSERT INTO [Communication].[Phones]([PhoneTypeId], [Number]) VALUES(6, #Phone);
DECLARE #PhoneId INT = SCOPE_IDENTITY();
INSERT INTO [Communication].[Emails]([Address]) VALUES(#Email);
DECLARE #EmailId INT = SCOPE_IDENTITY();
INSERT INTO [Location].[Addresses]([PostalCode], [Street]) VALUES(#Zip, #Street);
DECLARE #AddressId INT = SCOPE_IDENTITY();
INSERT INTO [Management].[Leads]([SourceId], [PersonId], [PhoneId], [EmailId], [AddressId], [ImporterId]) VALUES(#SourceId, #PersonId, #PhoneId, #EmailId, #AddressId, #ImporterId);
END
COMMIT
FETCH NEXT FROM C1 INTO #Id;
END
CLOSE C1;
DEALLOCATE C1;
Don't use ##IDENTITY. Use SCOPE_IDENTITY():
SCOPE_IDENTITY and ##IDENTITY return
the last identity values that are
generated in any table in the current
session. However, SCOPE_IDENTITY
returns values inserted only within
the current scope; ##IDENTITY is not
limited to a specific scope.
For example, there are two tables, T1 and
T2, and an INSERT trigger is defined
on T1. When a row is inserted to T1,
the trigger fires and inserts a row in
T2. This scenario illustrates two
scopes: the insert on T1, and the
insert on T2 by the trigger.
Assuming that both T1 and T2 have
identity columns, ##IDENTITY and
SCOPE_IDENTITY will return different
values at the end of an INSERT
statement on T1. ##IDENTITY will
return the last identity column value
inserted across any scope in the
current session. This is the value
inserted in T2. SCOPE_IDENTITY() will
return the IDENTITY value inserted in
T1. This was the last insert that
occurred in the same scope. The
SCOPE_IDENTITY() function will return
the null value if the function is
invoked before any INSERT statements
into an identity column occur in the
scope.

How to store results from a query while in a stored procedure

Say I have this great query in my stored procedure.
Select * from Temp
How would I store the results of this in the same stored procedure since in the next line I want to go through it in a loop(I don't know how to do this yet either) and do stuff to it.
I found something like this
DECLARE total_count INT DEFAULT 0
SET total_count = 10;
but it seems like that does not work.
Msg 156, Level 15, State 1, Procedure csp_test, Line 3
Incorrect syntax near the keyword 'DECLARE'.
Msg 155, Level 15, State 2, Procedure csp_test, Line 3
'INT' is not a recognized CURSOR option.
Edit
Ok this is what I go so far. I have no clue what I am doing so I don't know if this is remotely right.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[csp_test]
AS
BEGIN
declare #temp2 table (
idx int identity(1,1),
field varchar(max))
insert into #temp2 (field)
Select * from temp
END
So What I think this is doing is it makes some table variable then inserts all my results from temp table into this temp2 table variable. Then I loop through them or something like that?
I don't if what I have is so far right. I then found this and not sure if this would be the next step
declare #counter int
set #counter = 1
while #counter < (select max(idx) from #temp)
begin
-- do what you want with the rows here
set #counter = #counter + 1
end
Temp Table script
USE [test]
GO
/****** Object: Table [dbo].[temp] Script Date: 07/06/2010 19:20:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[temp](
[id] [int] IDENTITY(1,1) NOT NULL,
[temp] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
CONSTRAINT [PK_temp] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
--Variable table #table
declare #table as Table (int i, ...)
insert into #table
Select * from Temp
or
--Temporary table #temp
create table #temp (int i, ...)
insert into #table
Select * from Temp
--Use it
--Finally
drop table #temp
What you found should be:
DECLARE #total_count INT DEFAULT 0
SET #total_count = 10;
Variables starts with #
For info about differences I've found this article and a stackoverflow question.
This is a handy template for creating a temp table, filling with data, then cursor through the data for some reason
-- create temp table
CREATE TABLE #tmp (field1 int, field2 varchar(10)) ON [PRIMARY]
-- populate temp table
insert into #tmp (field1, field2)
select something1, something2
from someTable
-- variables for cursor through temp table
declare #field1 int
declare #field2 varchar(10)
-- open cursor
declare myCursor Cursor for select field1, field2 from #tmp
open myCursor
-- get 1st row of data
fetch next from myCursor into #field1, #field2
-- loop through the data
while ##fetch_status = 0 begin
-- do sumthin.. data is in #field1 and #field2
-- get next row
fetch next from myCursor into #field1, #field2
end
-- get rid of cursor
close myCursor
deallocate myCursor
-- drop temp table
drop table #tmp