昨天发布了此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
输出工作脚本:
存储过程的输出:
答案 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
。