为表中的每一行执行存储过程

时间:2018-02-22 12:08:39

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

美好的一天,

我正在计算遗留程序并遇到了一些问题,这应该很容易,但不能随我计算,至少今天不行。

我所遵循的逻辑是我在 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

3 个答案:

答案 0 :(得分:0)

可以使用动态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

答案 1 :(得分:0)

包含数据和存储过程的示例表

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 :(得分:0)

使用这样的样本数据&amp;过程:

-- 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

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

毕竟:删除程序:

DROP PROCEDURE [dbo].[MyProcedure]