【问题标题】:Stored Procedure insert only one record from the Temporary Table存储过程仅从临时表中插入一条记录
【发布时间】:2017-09-13 05:10:59
【问题描述】:

我一直在写这个存储过程,我对存储过程有点陌生。我一直在尝试将插入放入循环中,但逻辑不对。

基本上,下面的存储过程只将最后一行插入到表中。 但是,当我打印出临时表时,它会正确显示所有数据,但不知何故插入/更新无法正常工作

下面是存储过程的脚本。谁能告诉我,我在这里错过了什么?

--exec [dbo].[spAddIntoTemplateCalculationsTable] @templateID=1,@parameterList='0:C:Test:True:0,0:B:TEST2:False:0,0:A-b/c*a::False:0',
--@EmployeeNo = 'test'

ALTER PROCEDURE [dbo].[spAddIntoTemplateCalculationsTable]
(     -- Add the parameters for the stored procedure here
@templateID nvarchar(max),
@parameterList nvarchar(max),
@EmployeeNo nvarchar(16)
)     
AS
BEGIN


Declare @ErrorNo integer = '',

@ErrorMessage nvarchar(max) = '',
@SPName nvarchar(max) = ''

DECLARE @paramID nvarchar(MAX),@formula nvarchar(MAX), @property nvarchar(MAX),@samplesRequired nvarchar(MAX),@tUnitOfMeasures_id int,
@Pos int,@strSampleData nvarchar(MAX),@IntCounter int,@test int

      DECLARE @tmpParameterParam table
            (
                paramID nvarchar(MAX),
                  formula nvarchar(MAX),
                  property nvarchar(MAX),
                  samplesRequired nvarchar(MAX),
                  tUnitOfMeasures_id int

                  )


      SET @parameterList = LTRIM(RTRIM (@parameterList))+ ','
      SET @Pos = CHARINDEX (',', @parameterList,1)
      --SET @IntCounter = 1
            IF REPLACE(@parameterList, ',' , '') <> ''
                  begin 
                        WHILE @Pos > 0
                        BEGIN 
                              SET @strSampleData = LTRIM(RTRIM(LEFT(@parameterList, @Pos -1)))
                              IF @strSampleData  <> ''

                              BEGIN 

                                    set @paramID = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    --Remove the substring and move the string to the next token(column)
                                    set @strSampleData = substring(@strSampleData, LEN(@paramID)+2, LEN(@strSampleData))

                                    set @formula = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    --Remove the substring and move the string to the next token(column)
                                    set @strSampleData = substring(@strSampleData, LEN(@formula)+2, LEN(@strSampleData))

                                    --update tSpecScaleValidation set LastTriggeredTime=getdate() where id= @tSpecScaleValidation_id

                                    set @property = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    set @strSampleData = substring(@strSampleData, LEN(@property)+2, LEN(@strSampleData))

                                    set @samplesRequired = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    set @strSampleData = substring(@strSampleData, LEN(@samplesRequired)+4, LEN(@strSampleData))         


                                    set @tUnitOfMeasures_id = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                     --to get the last token from the string(column)
                                    set @tUnitOfMeasures_id = substring(@strSampleData, LEN(@tUnitOfMeasures_id)+1, LEN(@strSampleData))   



                                    insert into @tmpParameterParam
                                    --select @IntCounter,@strSampleData
                                    select  @paramID,@formula,@property,@samplesRequired,@tUnitOfMeasures_id


                              END
                              SET @parameterList = RIGHT(@parameterList, LEN (@parameterList) - @Pos)
                              set @Pos = CHARINDEX(',', @parameterList,1)
                              SET @IntCounter = @IntCounter + 1
                        END
                  END 

                  begin transaction t1


                  begin try
                        declare @setno int
                        select * from @tmpParameterParam
                        --begin 
                            if EXISTS (SELECT * FROM tTemplate_Calculation where id = @paramID)
                                update tTemplate_Calculation 
                                set formula=@formula,
                                property = @property , 
                                samplesRequired=@samplesRequired, 
                                tUnitOfMeasures_id=@tUnitOfMeasures_id
                                where id = @paramID
                            else
                                insert into tTemplate_Calculation 
                                select @templateID,@formula,@property,@samplesRequired,@tUnitOfMeasures_id,@EmployeeNo,getdate()
                                FROM @tmpParameterParam 

                        --end
                        commit transaction t1

                  end try

      Begin Catch 
            Select 
                  @ErrorMessage = ERROR_MESSAGE(),
                  @SPName = ERROR_PROCEDURE(),
                  @ErrorMessage = ERROR_MESSAGE();

            rollback transaction t1

            select @ErrorMessage
      End Catch

END

【问题讨论】:

  • 我试图根据临时表插入和更新记录。但它只是插入最后一行
  • 另外,我有一个检查,如果paramID为0,它应该插入,否则,更新表
  • 当表为空且转换 nvarchar 值 'False??' 时转换失败时失败到数据类型位并且使用 exec [dbo].[spAddIntoTemplateCalculationsTable] @templateID=1,@parameterList='0:C:Test:True:0,0:B:TEST2:Fals‌​e:0 执行时不插入任何内容0:Ab/c*a::False‌​:0', @EmployeeNo = 'test' 和显示的 3 行是过程中的调试选择语句。
  • 插入语句不正确,来自表变量的字段不应以@开头。您可能希望将所需的示例更改为位以外的其他值,或者将参数从 true 和 false 更改为 1 或 0。我会在过程中添加一些验证逻辑,并加强表定义以包含允许的值。更新阶段可能会导致问题,因为它只会在您的输入字符串中找到的最后一个 @paramid 更新这是您真正想要的(它永远不会找到 paramid = 0 的位置,因为标识列总是从 1 开始)?

标签: sql-server stored-procedures


【解决方案1】:

请尝试以下操作。我已经在我的 Sql server 中成功执行了。

ALTER PROCEDURE [dbo].[spAddIntoTemplateCalculationsTable]
(
  -- Add the parameters for the stored procedure here
  @templateID NVARCHAR(MAX),
  @parameterList NVARCHAR(MAX),
  @EmployeeNo NVARCHAR(16)
)
AS 
BEGIN


    DECLARE @ErrorNo INTEGER,
        @ErrorMessage NVARCHAR(MAX),
        @SPName NVARCHAR(MAX) 

    DECLARE @paramID NVARCHAR(MAX),
        @formula NVARCHAR(MAX),
        @property NVARCHAR(MAX),
        @samplesRequired NVARCHAR(MAX),
        @tUnitOfMeasures_id INT,
        @Pos INT,
        @strSampleData NVARCHAR(MAX),
        @IntCounter INT,
        @test INT

    DECLARE @tmpParameterParam TABLE
(
  paramID NVARCHAR(MAX),
  formula NVARCHAR(MAX),
  property NVARCHAR(MAX),
  samplesRequired NVARCHAR(MAX),
  tUnitOfMeasures_id INT
)


    SET @parameterList = LTRIM(RTRIM(@parameterList)) + ','
    SET @Pos = CHARINDEX(',', @parameterList, 1)
      --SET @IntCounter = 1
    IF REPLACE(@parameterList, ',', '') <> '' 
        BEGIN 
            WHILE @Pos > 0 
                BEGIN 
                    SET @strSampleData = LTRIM(RTRIM(LEFT(@parameterList, @Pos - 1)))
                    IF @strSampleData <> '' 
                        BEGIN 

                            SET @paramID = SUBSTRING(@strSampleData, 0, CHARINDEX(':', @strSampleData, 0)) 
                                    --Remove the substring and move the string to the next token(column)
                            SET @strSampleData = SUBSTRING(@strSampleData, LEN(@paramID) + 2, LEN(@strSampleData))

                            SET @formula = SUBSTRING(@strSampleData, 0, CHARINDEX(':', @strSampleData, 0)) 
                                    --Remove the substring and move the string to the next token(column)
                            SET @strSampleData = SUBSTRING(@strSampleData, LEN(@formula) + 2, LEN(@strSampleData))

                                    --update tSpecScaleValidation set LastTriggeredTime=getdate() where id= @tSpecScaleValidation_id

                            SET @property = SUBSTRING(@strSampleData, 0, CHARINDEX(':', @strSampleData, 0)) 
                            SET @strSampleData = SUBSTRING(@strSampleData, LEN(@property) + 2, LEN(@strSampleData))

                            SET @samplesRequired = SUBSTRING(@strSampleData, 0, CHARINDEX(':', @strSampleData, 0)) 
                            SET @strSampleData = SUBSTRING(@strSampleData, LEN(@samplesRequired) + 4, LEN(@strSampleData))         


                            SET @tUnitOfMeasures_id = SUBSTRING(@strSampleData, 0, CHARINDEX(':', @strSampleData, 0)) 
                                     --to get the last token from the string(column)
                            SET @tUnitOfMeasures_id = SUBSTRING(@strSampleData, LEN(@tUnitOfMeasures_id) + 1, LEN(@strSampleData))   



                            INSERT  INTO @tmpParameterParam
                                    --select @IntCounter,@strSampleData
                                    SELECT  @paramID, @formula, @property, @samplesRequired, @tUnitOfMeasures_id


                        END
                    SET @parameterList = RIGHT(@parameterList, LEN(@parameterList) - @Pos)
                    SET @Pos = CHARINDEX(',', @parameterList, 1)
                    SET @IntCounter = @IntCounter + 1
                END
        END 

    BEGIN TRANSACTION t1


    BEGIN TRY
        DECLARE @setno INT
        SELECT  *
        FROM    @tmpParameterParam
                        --begin 
        IF EXISTS ( SELECT  *
                    FROM    tTemplate_Calculation
                    WHERE   id = @paramID ) 
            UPDATE  tTemplate_Calculation
            SET     formula = @formula, property = @property, samplesRequired = @samplesRequired, tUnitOfMeasures_id = @tUnitOfMeasures_id
            WHERE   id = @paramID
        ELSE 
            INSERT  INTO tTemplate_Calculation
                    SELECT  @templateID, @formula, @property, @samplesRequired, @tUnitOfMeasures_id, @EmployeeNo, GETDATE()
                    FROM    @tmpParameterParam 

                        --end
        COMMIT TRANSACTION t1

    END TRY

    BEGIN CATCH 
        SELECT  @ErrorMessage = ERROR_MESSAGE(), @SPName = ERROR_PROCEDURE(), @ErrorMessage = ERROR_MESSAGE() ;

        ROLLBACK TRANSACTION t1

        SELECT  @ErrorMessage


    END CATCH

END

【讨论】:

  • 感谢@Rajan,但它仍然从临时表中插入最后一行 3 次。
  • 你能给我一个sql来生成表“tTemplate_Calculation”并给我一个参数列表来执行SP
  • GO /****** 对象:表 [dbo].[tTemplate_Calculation] 脚本日期:2017 年 9 月 13 日下午 2:43:55 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[tTemplate_Calculation]( [id] [int] IDENTITY(1,1) NOT NULL, [tTemplate_id] [int] NULL, [formula] [nvarchar](10) NULL, [属性] [nvarchar](50) NULL, [samplesRequired] [bit] NULL, [tUnitOfMeasures_id] [int] NULL, [employeeNo] [nvarchar](50) NULL, [dateTimeStamps] [datetime] NULL ) ON [PRIMARY] GO
  • 上面是sql表,这是我一直在使用的 exec [dbo].[spAddIntoTemplateCalculationsTable] @templateID=1,@parameterList='0:C:Test:True:0,0 :B:TEST2:False:0,0:Ab/c*a::False:0', @EmployeeNo = 'test'
  • 这里出现错误,因此,打印您在变量中设置的所有值以获取详细信息,当您使用子字符串方法时会发生什么。
【解决方案2】:

我不认为你离得那么远。我的理解是您希望在 tTemplate_Calculation 中每个参数有 1 行,所以我会更改表定义 因此 paramid 是唯一的,但不是身份类型。

CREATE TABLE [dbo].[tTemplate_Calculation]( 
[id] [int] unique, --IDENTITY(1,1) NOT NULL, 
[tTemplate_id] [int] NULL, 
[formula] [nvarchar](10) NULL, 
[property] [nvarchar](50) NULL, 
[samplesRequired] [bit] NULL, 
[tUnitOfMeasures_id] [int] NULL, 
[employeeNo] [nvarchar](50) NULL, 
[dateTimeStamps] [datetime] NULL ) 

,修改 sp 以在表变量中包含一个标识列,当您进入更新/插入阶段时,使用 @i 和 @j 变量创建一个使用偏移量的循环,并从表变量中获取传递数据回声明变量

alter PROCEDURE [dbo].[spAddIntoTemplateCalculationsTable]
(     -- Add the parameters for the stored procedure here
@templateID nvarchar(max),@parameterList nvarchar(max),@EmployeeNo nvarchar(16))     
AS
BEGIN
Declare @ErrorNo integer = '',
@ErrorMessage nvarchar(max) = '',
@SPName nvarchar(max) = '',
@i int ,
@j int
DECLARE @paramID nvarchar(MAX),@formula nvarchar(MAX), @property nvarchar(MAX),@samplesRequired nvarchar(MAX),@tUnitOfMeasures_id int,
@Pos int,@strSampleData nvarchar(MAX),@IntCounter int,@test int
DECLARE @tmpParameterParam table (id int identity , paramID nvarchar(MAX), formula nvarchar(MAX), property nvarchar(MAX), samplesRequired nvarchar(MAX),tUnitOfMeasures_id int)
set @i = 0
set @j = 0
      SET @parameterList = LTRIM(RTRIM (@parameterList))+ ','
      SET @Pos = CHARINDEX (',', @parameterList,1)
      --SET @IntCounter = 1
            IF REPLACE(@parameterList, ',' , '') <> ''
                  begin 
                        WHILE @Pos > 0
                        BEGIN 
                              SET @strSampleData = LTRIM(RTRIM(LEFT(@parameterList, @Pos -1)))
                              IF @strSampleData  <> ''

                              BEGIN 

                                    set @paramID = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    --Remove the substring and move the string to the next token(column)
                                    set @strSampleData = substring(@strSampleData, LEN(@paramID)+2, LEN(@strSampleData))

                                    set @formula = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    --Remove the substring and move the string to the next token(column)
                                    set @strSampleData = substring(@strSampleData, LEN(@formula)+2, LEN(@strSampleData))

                                    --update tSpecScaleValidation set LastTriggeredTime=getdate() where id= @tSpecScaleValidation_id

                                    set @property = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    set @strSampleData = substring(@strSampleData, LEN(@property)+2, LEN(@strSampleData))

                                    set @samplesRequired = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                    set @strSampleData = substring(@strSampleData, LEN(@samplesRequired)+4, LEN(@strSampleData))         

                                    set @tUnitOfMeasures_id = substring(@strSampleData,0, CHARINDEX(':',@strSampleData,0)) 
                                     --to get the last token from the string(column)
                                    set @tUnitOfMeasures_id = substring(@strSampleData, LEN(@tUnitOfMeasures_id)+1, LEN(@strSampleData))   

                                    insert into @tmpParameterParam
                                    --select @IntCounter,@strSampleData
                                    select  @paramID,@formula,@property,@samplesRequired,@tUnitOfMeasures_id

                              END
                              SET @parameterList = RIGHT(@parameterList, LEN (@parameterList) - @Pos)
                              set @Pos = CHARINDEX(',', @parameterList,1)
                              SET @IntCounter = @IntCounter + 1
                              set @i = @i + 1
                        END
                  END 
                  select @i as intcounter
                  begin transaction t1
                  begin try
                        declare @setno int

                        while @j < @i 
                         begin 
                              select @paramID = t.paramID ,
                                    @formula = t.formula,
                                    @property = t.property,
                                    @samplesRequired = t.samplesRequired,
                                    @tUnitOfMeasures_id = t.tUnitOfMeasures_id
                              from @tmpParameterParam t 
                               order by t.id offset @i rows fetch next 1 rows only

                            if EXISTS (SELECT * FROM tTemplate_Calculation where id = @paramid)
                                begin 
                                select 'updating' , @i, @j
                                update tTemplate_Calculation 
                                set formula= @formula,
                                property = @property , 
                                samplesRequired=@samplesRequired, 
                                tUnitOfMeasures_id=@tUnitOfMeasures_id

                                end
                            else
                                begin
                                select 'inserting' , @i, @j
                                insert into tTemplate_Calculation 
                                (   [id],
                                    [tTemplate_id] , 
                                    [formula] , 
                                    [property], 
                                    [samplesRequired], 
                                    [tUnitOfMeasures_id] , 
                                    [employeeNo] , 
                                    [dateTimeStamps])

                                select @paramid, @templateID,@formula,@property,@samplesRequired,@tUnitOfMeasures_id,@EmployeeNo,getdate()
                                end 
                            set @j =@j + 1
                         end
                        commit transaction t1
                  end try
      Begin Catch 
            Select 
                  @ErrorMessage = ERROR_MESSAGE(),
                  @SPName = ERROR_PROCEDURE(),
                  @ErrorMessage = ERROR_MESSAGE();
            rollback transaction t1
            select @ErrorMessage
      End Catch

END

当调用sp时

set nocount on
truncate table tTemplate_Calculation

exec [dbo].[spAddIntoTemplateCalculationsTable] @templateID=1,@parameterList='0:C:Test:0:0,0:B:TEST2:1:0,0:A-b/c*a::0:0', @EmployeeNo = 'test'
select * from tTemplate_Calculation

这是结果

intcounter
-----------
3


--------- ----------- -----------
inserting 3           0


-------- ----------- -----------
updating 3           1


-------- ----------- -----------
updating 3           2

id          tTemplate_id formula    property                                           samplesRequired tUnitOfMeasures_id employeeNo                                         dateTimeStamps
----------- ------------ ---------- -------------------------------------------------- --------------- ------------------ -------------------------------------------------- -----------------------
0           1            A-b/c*a                                                       0               0                  test                                               2017-09-13 13:05:12.310

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    相关资源
    最近更新 更多