【问题标题】:Call stored procedure for each row from select从选择中调用每一行的存储过程
【发布时间】:2019-05-15 03:35:36
【问题描述】:

我的选择语句中有一堆记录。我必须从该选择中为每一行调用某些存储过程。我知道这可以用游标完成(我已经在 SO 上找到了关于这个的答案——但它们都很老了)。我很好奇今天在现代版本的 SQL Server 中是否还有其他可能性?

我的选择:

SELECT USER_KEY, USER_WHK FROM BAUSER WHERE USER_STA = '1'

我的插入:

EXEC sp_BAUSCA_BASE 
  @iUSCA_KEY = NULL
, @iCAET_KEY = 150000003
, @iUSER_KEY = --user key from select
, @iENTE_KEY = 110000001
, @dUSCA_DAT = GETDATE()
, @cUSCA_STA = '1'
, @cUSCA_SRT = '1'
, @iUserId = 160000230
, @cTask = '2'

【问题讨论】:

  • 你在那个sp里面做了什么SQL不能做的?理想情况下,您应该只从选择中插入,而不是使用游标。当然,除非你在存储过程中做一些非常时髦的事情,比如调用某个东西的加密 API……
  • PROblem 是 USCA_KEY - 它是通过调用另一个存储过程在存储过程中生成的。

标签: sql-server sql-server-2016


【解决方案1】:

您可以使用Cursor 归档此需求,我为您制作了一个演示,这可能会对您有所帮助。

有关光标的更多信息,您可以访问此link

演示

DECLARE 
@iUSCA_KEY  NVARCHAR(50) ,
@iCAET_KEY  NVARCHAR(50) ,
@iUSER_KEY  NVARCHAR(50) ,
@iENTE_KEY  NVARCHAR(50) ,
@dUSCA_DAT  DATETIME,
@cUSCA_STA  NVARCHAR(50) ,
@cUSCA_SRT  NVARCHAR(50) ,
@iUserId    INT,
@cTask      NVARCHAR(50) 

DECLARE MY_data CURSOR LOCAL FAST_FORWARD
FOR
    SELECT  
    iUSCA_KEY,  
    iCAET_KEY , 
    iUSER_KEY , 
    iENTE_KEY , 
    dUSCA_DAT,  
    cUSCA_STA,  
    cUSCA_SRT , 
    iUserId ,   
    cTask      
    FROM    BAUSER WHERE USER_STA = '1'


OPEN MY_data
FETCH NEXT FROM MY_data INTO @iUSCA_KEY,@iCAET_KEY,@iUSER_KEY,@iENTE_KEY,@dUSCA_DAT,@cUSCA_STA,@cUSCA_SRT,@iUserId,@cTask  
WHILE @@FETCH_STATUS = 0
    BEGIN

       EXEC sp_BAUSCA_BASE 
            @iUSCA_KEY = @iUSCA_KEY
            , @iCAET_KEY = @iCAET_KEY
            , @iUSER_KEY = @iUSER_KEY
            , @iENTE_KEY = @iENTE_KEY
            , @dUSCA_DAT = @dUSCA_DAT
            , @cUSCA_STA = @cUSCA_STA
            , @cUSCA_SRT = @cUSCA_SRT
            , @iUserId = @iUserId
            , @cTask = @cTask

        FETCH NEXT FROM MY_data INTO  @iUSCA_KEY,@iCAET_KEY,@iUSER_KEY,@iENTE_KEY,@dUSCA_DAT,@cUSCA_STA,@cUSCA_SRT,@iUserId,@cTask  
    END
CLOSE MY_data
DEALLOCATE MY_data

【讨论】:

  • 那么即使在今天,除了光标之外就没有其他可用的机制了吗?
  • @FrenkyB,没错。我只是注意到此类游标应始终声明为 LOCAL FAST_FORWARD 以获得最佳性能和最低保留锁定。问候和欢迎!
【解决方案2】:

我说的是修正,但据我了解,循环会占用更多资源。

不过,您也可以通过循环来完成。

请注意,我无法对其进行测试,因为我没有源数据和您拥有的 SP,但我确信该脚本是防弹的:

DECLARE     @LOOP       INT
,           @iUSCAKEY   INT
,           @iCAETKEY   INT
,           @iUSERKEY   INT
,           @iENTEKEY   INT
,           @cUSCASTA   VARCHAR(10)
,           @cUSCASRT   VARCHAR(10)
,           @iUserId    BIGINT
,           @cTask  VARCHAR(100)

DECLARE @TBL AS TABLE   (
                            ID INT PRIMARY KEY IDENTITY
                        ,   iUSCA_KEY   INT
                        ,   iCAET_KEY   INT
                        ,   iUSER_KEY   INT
                        ,   iENTE_KEY   INT
                        ,   cUSCA_STA   VARCHAR(10)
                        ,   cUSCA_SRT   VARCHAR(10)
                        ,   iUserId     BIGINT
                        ,   cTask       VARCHAR(100)

                        )

INSERT INTO @TBL        (
                            iUSCA_KEY
                        ,   iCAET_KEY
                        ,   iUSER_KEY
                        ,   iENTE_KEY
                        ,   cUSCA_STA
                        ,   cUSCA_SRT
                        ,   iUserId
                        ,   cTask

                        )
                        SELECT
                            iUSCA_KEY
                        ,   iCAET_KEY
                        ,   iUSER_KEY
                        ,   iENTE_KEY
                        ,   cUSCA_STA
                        ,   cUSCA_SRT
                        ,   iUserId
                        ,   cTask
                        FROM BAUSER
                        WHERE USER_STA = '1'


        SELECT @LOOP = MIN(ID) FROM @TBL
        WHILE @LOOP IS NOT NULL

            BEGIN

                    SELECT
                        @iUSCAKEY   =   iUSCA_KEY
                    ,   @iCAETKEY   =   iCAET_KEY
                    ,   @iUSERKEY   =   iUSER_KEY
                    ,   @iENTEKEY   =   iENTE_KEY
                    ,   @cUSCASTA   =   cUSCA_STA
                    ,   @cUSCASRT   =   cUSCA_SRT
                    ,   @iUserId    =   iUserId
                    ,   @cTask      =   cTask
                    FROM    @TBL
                    WHERE   ID  =   @LOOP

                    EXEC sp_BAUSCA_BASE 
                      @iUSCA_KEY    =   @iUSCAKEY
                    , @iCAET_KEY    =   @iCAETKEY
                    , @iUSER_KEY    =   @iUSERKEY
                    , @iENTE_KEY    =   @iENTEKEY
                    , @dUSCA_DAT    =   GETDATE()
                    , @cUSCA_STA    =   @cUSCASTA
                    , @cUSCA_SRT    =   @cUSCASRT
                    , @iUserId      =   @iUserId
                    , @cTask        =   @cTask

                SELECT @LOOP = MIN(ID) FROM @TBL WHERE ID > @LOOP

            END

让我知道它是否有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-30
    • 2014-09-17
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多