使用循环执行存储过程并组合结果

时间:2015-06-02 04:02:25

标签: sql sql-server stored-procedures union

我在SQL Server 2008中有一个存储过程。

此存储过程(让我们称之为sp1),接受ID(字符串),FromDate,ToDate并返回col1,col2,col3

我试图改变sp1以接受IDList(ID1,ID2,...,IDn),但这是我的想法。

我需要帮助创建一个接受IDList,FromDate,ToDate的新SP(让我们称之为SP2),然后使用id列表循环并调用SP1并将结果联合起来。

我希望我很清楚...

这是原始的SP,如果你能接受UnitIMEIList它也会很棒:

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

谢谢

1 个答案:

答案 0 :(得分:-1)

为了其他Google用户的利益:)

我自己做了一切!

我为此创建了一个名为“SandBox”的数据库。

创建一个示例表:

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

放一些数据(如果你很懒:) :):

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

创建接受单个ID的SP: *这只是一个示例...不要忘记它 - 我知道我可以发送多个ID作为参数......

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

现在为新的SP允许多次执行上述SP(正是我所寻找的):

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

感觉就像测试一样吗? 来吧:

USE [SandBox]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[spGetMultiple]
    @StudentIDList = N'3,2,1'

SELECT  'Return Value' = @return_value

GO
祝你好运!