【问题标题】:Executing stored procedure for each line in table为表中的每一行执行存储过程
【发布时间】:2018-02-22 12:08:38
【问题描述】:

早安,

我正在找出一个遗留程序并遇到了一些问题,这应该很容易,但我无法计算,至少今天不是。

我追求的逻辑是我在 table1 中有值,我希望将其提供给存储过程 proc1 并将结果保存到 Table2强>。

目前这是由不同的用户手动填写填充变量的字符串来调用的。工作语法例如:

exec [dbo].[Proc1] @var1=N'10010015',@var2='2008-03-31 00:00:00', @var3=50000

我尝试了类似的东西

declare var1 varchar, var2 varchar, var3 int
insert into table2 (result1, result2, result3) 
Select * from 
[dbo].[Proc1] (
  select @var1 = var1_tab1, 
         @var2 = var2_tab1 
         from table1
)

对于常规函数,我只需按正确顺序输入变量,但该过程需要@var1 格式。而且我不允许更改功能。

以前的尝试只是给了我不正确的语法。任何如何解决此类问题的想法将不胜感激。 .


**编辑:**

是的,它是重复的。或者至少我用另一个来创建解决方案。

写的太多了。太久没读。下面的工作。

我不明白的事情,但现在有道理:

-只要输入与过程定义的顺序相同,您就可以在不显式设置变量的情况下执行过程。

-您可以只将结果插入到表中,因为返回(来自此特定过程)是选择的。

DECLARE @var1 int, 
@var2 int,
@var3 float,
@var4 datetime,

DECLARE cur CURSOR FOR SELECT var1, var2, var3, var4 FROM table1
OPEN cur

FETCH NEXT FROM cur INTO @var1, @var2, @var3, @var4

WHILE @@FETCH_STATUS = 0 BEGIN
    insert into table2   EXEC [procedure] @var1, @var2, @var3, 0, '', NULL, @var4
    FETCH NEXT FROM cur INTO @var1, @var2, @var3, @var4
END

CLOSE cur    
DEALLOCATE cur

【问题讨论】:

  • 发帖前搜索 - 总是。 Passing columns 将表作为存储过程的参数是一个常见问题,inserting 结果集也是如此。
  • 我相信您正在寻找的是与交叉应用一起使用的功能。您不能在 select 语句中调用 SP。试着把你的 SP 写成一个函数。
  • 这个SP实际上是做什么的?遍历表中的每一行会很慢。根据它在做什么,使用其他东西可能更容易,比如内联表值函数。虽然不知道 [proc1] 做了什么,但我无法提供更多。

标签: sql-server tsql sql-server-2012


【解决方案1】:

带有数据和存储过程的示例表

IF OBJECT_ID('dbo.table1') IS NOT NULL
DROP TABLE table1

CREATE TABLE table1 (var1 VARCHAR(20),var2 VARCHAR(20),var3 INT)

INSERT INTO Table1 
SELECT '10010015','2008-03-31 00:00:00','50000' UNION ALL
SELECT '10010025','2008-03-21 00:00:00','40000' UNION ALL
SELECT '10010035','2008-03-29 00:00:00','50000' UNION ALL
SELECT '10010045','2008-03-30 00:00:00','60000' UNION ALL
SELECT '10010055','2008-03-28 00:00:00','70000'

IF OBJECT_ID('dbo.table2') IS NOT NULL
DROP TABLE table2
CREATE TABLE table2 (result1 VARCHAR(10),result2 VARCHAR(10),result3 INT )


IF OBJECT_ID('dbo.Proc1') IS NOT NULL
DROP PROCEDURE Proc1
GO
CREATE PROCEDURE Proc1
(
 @var1 VARCHAR(10)
,@var2 VARCHAR(20)
,@var3 INT
)
AS
BEGIN

INSERT INTO table2 (result1, result2, result3) 
SELECT @var1, @var2 ,@var3

END
GO

使用Dynamic Sql和While循环,我们将参数传递给sp,依次将执行结果保存在table2中

DECLARE   @var1 varchar(10)
         ,@var2 varchar(20)
         ,@var3 INT 
         ,@SQL NVARCHAR(MAX)
         ,@MInID INT
         ,@MaxID INT

;WIth Cte
AS
(
SELECT ROW_NUMBER()OVER(ORDER BY var1) AS Id,* FROM table1
)
SELECT @MInID = MIN(ID ),@MaxID = MAX(ID ) FROM cte

WHILE (@MInID<=@MaxID)
BEGIN
        ;WIth Cte
        AS
        (
        SELECT ROW_NUMBER()OVER(ORDER BY var1) AS Id,* FROM table1
        )
        SELECT @var1=var1,@var2=var2,@var3=var3 
        FROM cte WHERE ID=@MInID

        SET @SQL='
        EXEC [dbo].[Proc1] @var1='''+CAST(@var1 AS VARCHAR(10))+''',@var2='''+CAST(@var2 AS VARCHAR(20))+''', @var3='+CAST(@var3 AS VARCHAR(10))
        PRINT @SQL
        EXEC(@SQL)
        SET @MInID=@MInID+1
END

SELECT * FROM table2

结果

result1         result2          result3
------------------------------------------
10010015    2008-03-31 00:00:00  50000
10010025    2008-03-21 00:00:00  40000
10010035    2008-03-29 00:00:00  50000
10010045    2008-03-30 00:00:00  60000
10010055    2008-03-28 00:00:00  70000

【讨论】:

    【解决方案2】:

    可以使用动态 SQL 无需循环

        DECLARE @T1 TABLE (Col1 NVARCHAR(10), Col2 NVARCHAR(10) , Col3 INT)
        /*Sample Data*/
        INSERT INTO @T1 (Col1 ,Col2, Col3 )
        SELECT '100100' , CONVERT(NVARCHAR(10),CAST(GETDATE() AS DATE),120), 5000
        UNION ALL
        SELECT '100200' , CONVERT(NVARCHAR(10),CAST(GETDATE()-1 AS DATE),120), 6000
        UNION ALL 
        SELECT '103200' , CONVERT(NVARCHAR(10),CAST(GETDATE()-2 AS DATE),120), 7000
        UNION ALL 
        SELECT '103400' , CONVERT(NVARCHAR(10),CAST(GETDATE()-3 AS DATE),120), 9000
    
        DECLARE @Sql NVARCHAR(MAX)=''
        SELECT @Sql+= 'EXEC YourSP @Var1 ='''+T.Col1+''' , @Var2 = '''+T.Col2+''' , @var3 = '+CONVERT(NVARCHAR(30),T.Col3)+';'+CHAR(10)     
        FROM @T1 T
        PRINT @sql
        EXEC sp_executesql @Sql
    

    【讨论】:

      【解决方案3】:

      有了这样的样本数据和程序:

      -- CREATE FAKE PROCEDURE AS AN EXAMPLE:
      IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MyProcedure]') AND type in (N'P', N'PC'))
      DROP PROCEDURE [dbo].[MyProcedure]
      GO
      CREATE  PROCEDURE [dbo].[MyProcedure] @A1 varchar(1),@A2 varchar(1),@id INT
      AS BEGIN
          --switch chars, and multiplay intiger:
          SELECT @A2,@A1,@id*10
      END
      GO
      
      --CREATE TABLES:
      DECLARE @table1 TABLE (var1 VARCHAR(1), var2 VARCHAR(1), var3 INT)
      DECLARE @table2 TABLE (res1 VARCHAR(1), res2 VARCHAR(1), res3 INT)
      -- START DATA:
      INSERT INTO @table1 VALUES ('a','b',1),('m','n',2),('x','y',3)
      SELECT * from @table1
      

      输出@table1

      var1 var2 var3
      ---- ---- ----
      a    b    1
      m    n    2
      x    y    3
      

      解决方案可以通过使用CURSOR来实现:

      DECLARE @var1 varchar(20)
      DECLARE @var2 varchar(20)
      DECLARE @var3 int
      
      DECLARE @Cursor as CURSOR;
      SET @Cursor = CURSOR FOR
          SELECT var1, var2, var3 
          FROM @table1
      
      OPEN @Cursor;
      FETCH NEXT FROM @Cursor INTO @var1, @var2, @var3;
      
      WHILE @@FETCH_STATUS = 0
      BEGIN
          INSERT INTO @table2 (res1, res2, res3)
              EXEC MyProcedure @var1, @var2, @var3
      
          FETCH NEXT FROM @Cursor INTO @var1, @var2, @var3;
      END
      
      CLOSE @Cursor;
      DEALLOCATE @Cursor;
      
      
      select * from @table2
      

      输出:@table2*

      res1 res2 res3
      ---- ---- ----
      b    a    10
      n    m    20
      y    x    30
      

      注意:以上两部分应作为单个查询一起运行

      毕竟:丢弃 fake 程序:

      DROP PROCEDURE [dbo].[MyProcedure]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-15
        • 2017-11-01
        • 2017-03-28
        • 1970-01-01
        • 2017-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多