将工作脚本转换为存储过程

时间:2016-07-01 17:22:25

标签: sql-server sql-server-2008-r2 sql-server-2014

昨天发布了此question并获得了solution。解决方案脚本工作正常,但当我将其转换为存储过程时,它会产生错误的结果。无法确定我在哪里弄乱代码。

表架构:

CREATE TABLE [dbo].[VMaster](
    [VID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [VName] [varchar](30) NOT NULL
)
GO

CREATE TABLE [dbo].[TblMaster](
    [SID] [int] IDENTITY(1,1) NOT NULL Primary Key,
    [VID] [int] NOT NULL,
    [CreatedDate] [datetime] default (getdate()) NOT NULL,
    [CharToAdd] [varchar](10) NOT NULL,
    [Start] [int]  NOT NULL,
    [End] [int] NOT NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[TblDetails](
    [DetailsID] [int] IDENTITY(1,1) NOT NULL Primary Key,
    [SID] [int] NOT NULL,
    [Sno] [int] NOT NULL,
    [ConcatenatedText] [varchar](20) NOT NULL,
    [isIssued] [bit] default (0) NOT NULL,
    [isUsed] [bit] default (0) NOT NULL
)
GO

ALTER TABLE [dbo].[TblMaster]  WITH CHECK ADD CONSTRAINT [fk_SI_id] FOREIGN KEY([VID])
REFERENCES [dbo].[VMaster] ([VID])
GO

ALTER TABLE [dbo].[TblMaster] CHECK CONSTRAINT [fk_SI_id]
GO

工作解决方案:

CREATE FUNCTION [dbo].[udf-Create-Range-Number] (@R1 money,@R2 money,@Incr money)

-- Syntax Select * from [dbo].[udf-Create-Range-Number](0,100,2)

Returns 
@ReturnVal Table (RetVal money)

As
Begin
    With NumbTable as (
        Select NumbFrom = @R1
        union all
        Select nf.NumbFrom + @Incr
        From NumbTable nf
        Where nf.NumbFrom < @R2
    )
    Insert into @ReturnVal(RetVal)

    Select NumbFrom from NumbTable Option (maxrecursion 32767)

    Return
End


Declare @Table table (SID int,VID int,CreateDate DateTime,CharToAdd varchar(25),Start int, [End] Int)
Insert Into @Table values
(1,1,'2016-06-30 19:56:14.560','ABC',1,5),
(2,1,'2016-06-30 19:56:14.560','XYZ',10,20),
(3,2,'2016-06-30 19:56:14.560','P1',10,15)

Declare @Min int,@Max int
Select @Min=min(Start),@Max=max([End]) From @Table

Select B.SID
      ,Sno = A.RetVal
      ,ConcetratedText = concat(B.CharToAdd,A.RetVal)
 From (Select RetVal=Cast(RetVal as int) from [dbo].[udf-Create-Range-Number](@Min,@Max,1)) A
 Join @Table B on A.RetVal Between B.Start and B.[End]
 Order By B.Sid,A.RetVal

存储过程(这会产生比工作解决方案更多的记录!!)

CREATE PROCEDURE [dbo].[Add_Details]
(
    @VID          INT,
    @CreatedDate     DATETIME,
    @CharToAdd      VARCHAR(10),
    @Start       INT,
    @End         INT
)
AS
SET NOCOUNT ON

BEGIN
    DECLARE @SID INT

    INSERT INTO [dbo].[TblMaster] (VID, CreatedDate, CharToAdd, Start, [End]) 
    VALUES (@VID, @CreatedDate, @CharToAdd, @Start, @End)
    SET @SID = SCOPE_IDENTITY()

    DECLARE @Min INT, @Max INT
    SELECT @Min = @Start, @Max = @End

    INSERT INTO [dbo].[TblDetails] (SID, Sno, [ConcatenatedText])
    SELECT @SID
          ,Sno = A.RetVal
          ,ConcatenatedText = CONCAT(B.CharToAdd,A.RetVal)
     FROM (SELECT RetVal = CAST(RetVal AS INT) FROM [dbo].[udf-Create-Range-Number](@Min,@Max,1)) A 
            JOIN dbo.TblMaster B ON A.RetVal BETWEEN B.Start AND B.[End]
     ORDER BY B.SID,A.RetVal

END
GO


Declare @tmp datetime
Set @tmp = getdate()

EXEC    [dbo].[Add_Details]
        @VID = 1,
        @CreatedDate = @tmp,
        @CharToAdd = 'ABC',
        @Start = 1,
        @End = 5

EXEC    [dbo].[Add_Details]
        @VID = 1,
        @CreatedDate = @tmp,
        @CharToAdd = 'XYZ',
        @Start = 10,
        @End = 20

EXEC    [dbo].[Add_Details]
        @VID = 2,
        @CreatedDate = @tmp,
        @CharToAdd = 'P1',
        @Start = 10,
        @End = 15

输出工作脚本:

enter image description here

存储过程的输出:

enter image description here

1 个答案:

答案 0 :(得分:2)

您需要在第二个插页上按VID进行过滤。它从以前的执行中获取行。因为它只拾取范围重叠的其他行,所以它并不总是这样做。多运行一次程序,你会看到重复放大了很多。它在原始代码中没有这样做的原因是因为您使用的是每次运行时都重新创建的临时表。

INSERT INTO [dbo].[TblDetails] (SID, Sno, [ConcatenatedText])
SELECT @SID
      ,Sno = A.RetVal
      ,ConcatenatedText = CONCAT(B.CharToAdd,A.RetVal)
FROM (
    SELECT RetVal = CAST(RetVal AS INT)
    FROM [dbo].[udf-Create-Range-Number](@Min,@Max,1)) A 
        JOIN dbo.TblMaster B ON A.RetVal BETWEEN B.Start AND B.[End]
    WHERE B.VID = @VID -- <<<---------
)

另外,我强烈建议您更改该功能,以便输入int而不是money