【问题标题】:Converting a working script into Stored procedure将工作脚本转换为存储过程
【发布时间】:2016-07-01 17:22:24
【问题描述】:

昨天发布了这个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

工作脚本的输出:

存储过程的输出:

【问题讨论】:

  • 您真的应该帮助我们,告诉我们输出中的实际不同之处。
  • @shawnt00 添加了工作脚本和存储过程的结果。
  • 也许您应该删除所有内容并重试以确保这些行在早期测试中尚未出现在表中。
  • 我已经截断了表格并重新运行它,每次添加这些额外的行时。
  • 是的,我猜DetailsID 那时会出现乱序。

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


【解决方案1】:

您需要在第二次插入时按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

【讨论】:

  • 感谢 shwawnt00,它真的很有帮助。是的,我也更改了数据类型。
  • 看起来还没有解决问题。同样的问题再次发生!
  • @prasanth 您是否在重复使用(复制)VID?
  • 是的 tblMaster VID 可以复制。 VID 和 CharToAdd 的组合将是独一无二的。
  • @prasanth 然后您需要将该过滤器与我们放入的另一个过滤器一起添加到where 子句中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 2010-10-23
  • 2013-06-18
  • 1970-01-01
相关资源
最近更新 更多