【问题标题】:Update Statement in a Stored Procedure存储过程中的更新语句
【发布时间】:2011-05-10 20:41:57
【问题描述】:

我有一个名为 Active 的存储过程,代码是:

CREATE PROCEDURE dbo.Active
        (
          @ID INT ,
          @Source VARCHAR(25)
        )
    AS 
        BEGIN
            DECLARE @SQL NVARCHAR(MAX)
            DECLARE @SchemaName SYSNAME
            DECLARE @TableName SYSNAME
            DECLARE @DatabaseName SYSNAME
            DECLARE @BR CHAR(2)
            SET @BR = CHAR(13) + CHAR(10) 


        SELECT  @SchemaName = Source_Schema ,
                @TableName = Source_Table ,
                @DatabaseName = Source_Database
        FROM    Source
        WHERE   ID = @ID


        SET @SQL = 'UPDATE Source_Table' + @BR
            + 'SET __ACTIVE = CASE WHEN rn = 1 THEN 1 ELSE 0 END' + @BR
            + 'FROM   ( ' + @BR + 'SELECT ROW_NUMBER() OVER (PARTITION BY '
            + @Source + ' ORDER BY __REC_ID DESC) AS rn
        ,  * FROM ' + @DatabaseName + '.' + @SchemaName + '.' + @TableName
            + @BR + ') Source_Table' + @BR          

        EXEC @SQL

    END 

问题是我在另一个过程中使用 thsi 过程,所以每次该过程运行时,该过程也会运行并对整个表进行更新。

该更新的主要原因是检查表上的重复项并将重复项设置为 0,其余设置为 1。

我不想对整个表运行此更新,但我希望仅对活动重复项运行更新。

有办法吗?

【问题讨论】:

    标签: sql sql-server sql-server-2008 stored-procedures dynamic-sql


    【解决方案1】:

    重申您的问题。您正在从另一个存储过程调用上述存储过程。我假设父程序决定了您所说的“活动重复”。如果是这种情况,那么您有几个选择:

    1) 临时表,让第一个过程创建一个全局临时表并在嵌套过程中使用它。之后一定要清理干净。

    --Base procedure creates global temp table with proper values;
    SELECT ID 
    INTO ##ActiveDups
    FROM DUPTABLE
    WHERE SOMECONDITION = SOMECONDITION
    
    --Join global temp table on query
    SET @SQL = 'UPDATE Source_Table' + @BR
        + 'SET __ACTIVE = CASE WHEN rn = 1 THEN 1 ELSE 0 END' + @BR
        + 'FROM   ( ' + @BR + 'SELECT ROW_NUMBER() OVER (PARTITION BY '
        + @Source + ' ORDER BY __REC_ID DESC) AS rn
        ,  * FROM ' + @DatabaseName + '.' + @SchemaName + '.' + @TableName
        + @BR + ') Source_Table' + @BR 
        + ' INNER JOIN ##ActiveDups ad ON ad.ID = Source_Table.ID'
    
    --Drop global temp table
    DROP TABLE ##ActiveDups
    

    2) 参数,将逗号分隔的列表传递给嵌套过程并使用INEXISTS 子句进行过滤。不是很可扩展。 (见添加的参数和查询的最后一行)

    CREATE PROCEDURE dbo.Active
    (
        @ID INT ,
        @Source VARCHAR(25),
        @List VARCHAR(MAX)
    )
    
    --...
    
    SET @SQL = 'UPDATE Source_Table' + @BR
        + 'SET __ACTIVE = CASE WHEN rn = 1 THEN 1 ELSE 0 END' + @BR
        + 'FROM   ( ' + @BR + 'SELECT ROW_NUMBER() OVER (PARTITION BY '
        + @Source + ' ORDER BY __REC_ID DESC) AS rn
        ,  * FROM ' + @DatabaseName + '.' + @SchemaName + '.' + @TableName
        + @BR + ') Source_Table' + @BR 
        + ' WHERE SOMECONDITION IN ' @List
    

    3) 将逻辑添加到您的动态 SQL 以获取正确的结果。 (见最后一行,这是附加的。我无法为你确定这个逻辑可能是什么。)

    SET @SQL = 'UPDATE Source_Table' + @BR
        + 'SET __ACTIVE = CASE WHEN rn = 1 THEN 1 ELSE 0 END' + @BR
        + 'FROM   ( ' + @BR + 'SELECT ROW_NUMBER() OVER (PARTITION BY '
        + @Source + ' ORDER BY __REC_ID DESC) AS rn
        ,  * FROM ' + @DatabaseName + '.' + @SchemaName + '.' + @TableName
        + @BR + ') Source_Table' + @BR 
        + ' WHERE SOMECONDITION = SOMECONDITION'
    

    【讨论】:

    • @Sam - 如果您不了解临时表、参数或动态 SQL(已在您的查询中),您可能不应该编辑此代码。 一点知识是危险的。
    • @JNK 这是否意味着您不想让任何人学习。如果我知道一切,为什么我会在这里发布我的问题,而不是我自己做。仅供参考,我已经创建了上述程序
    • @sam,不,这意味着只有有经验的人才能进行这种难度级别的查询。这不是刚刚学习的人应该触及的东西,因为如果你做错了,你可能会对你的数据库产生巨大的影响。你会期待刚刚学习网球的人在温布尔顿打球吗?
    • @HLGEM 刚刚学习 SQL 的人不会创建这种类型的过程吧?为此,我只是在上述过程中遗漏了一些逻辑,我在这里发布了我的问题。
    • @Sam - 我的意思不是侮辱,而是强烈的警告。临时表和参数很基础,动态SQL很危险。
    猜你喜欢
    • 1970-01-01
    • 2013-08-30
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多