为结果集中的每一行执行动态更新语句

时间:2012-02-01 21:10:25

标签: sql loops foreach cursor

我正在尝试编写一个数据滚动脚本,该脚本将在 demo 数据库中找到所有日期时间列,并将它们向前滚动x天。我试图保持这个尽可能动态,因为我们的数据库模式没有设置(仍处于开发阶段)。除了几个列(稍后我将在后面排除)之外,此语句标识将向前滚动日期时间列的更新语句:

SELECT 

    'UPDATE ' + [isc].[TABLE_NAME] + ' SET ' +
    [isc].[COLUMN_NAME] + 
    '= ' + [isc].[COLUMN_NAME] + '+ ' + 
    CAST(@DaysToRollForward AS NVARCHAR(5))  AS DySQL

FROM [INFORMATION_SCHEMA].COLUMNS AS isc
INNER JOIN [INFORMATION_SCHEMA].tables AS ist
    ON [ist].[TABLE_NAME] = [isc].[TABLE_NAME]
        WHERE [isc].[DATA_TYPE] = 'datetime'
            AND [ist].[TABLE_TYPE] = 'base table' 

我不反对使用游标,因为这只是一个演示服务器,并且永远不会真正看到很多负载。我们这样做是为了保持记录的最新状态,以便我们始终在应用程序中显示数据。我已经尝试了下面的游标,它没有执行UPDATE语句。有任何想法吗?我有正确的想法吗?我在这里看到了一些帮助帖子,但大多数都是在BEGIN - END块中执行存储过程。此外,如果有一个基于集合的方法,我会对此感兴趣,虽然如果有一个简单的修复我的光标也可以。正如我所提到的,这只是一个demo / qa服务器。

USE [sCRMDB1_demo]

GO

DECLARE @OrganizationId BIGINT
DECLARE @dySQL NVARCHAR(256)
DECLARE @DaysToRollForward INT


SET @DaysToRollForward = 7

DECLARE db_cursor_rollbackdates CURSOR FOR

SELECT 
    'UPDATE ' + [isc].[TABLE_NAME] + ' SET ' +
    [isc].[COLUMN_NAME] + 
    '= ' + [isc].[COLUMN_NAME] + '+ ' + 
    CAST(@DaysToRollForward AS NVARCHAR(5))  AS DySQL

FROM [INFORMATION_SCHEMA].COLUMNS AS isc
INNER JOIN [INFORMATION_SCHEMA].tables AS ist
    ON [ist].[TABLE_NAME] = [isc].[TABLE_NAME]
        WHERE [isc].[DATA_TYPE] = 'datetime'
            AND [ist].[TABLE_TYPE] = 'base table' 


OPEN db_cursor_rollbackdates
FETCH NEXT FROM db_cursor_rollbackdates INTO @dySQL

WHILE @@FETCH_STATUS = 0

BEGIN
    --PRINT CAST(@dySQL AS NVARCHAR(200))
    EXEC (@dySQL)
    FETCH NEXT FROM db_cursor_rollbackdates
END

CLOSE db_cursor_rollbackdates
DEALLOCATE db_cursor_rollbackdates

1 个答案:

答案 0 :(得分:0)

你会踢自己......

你在循环中

FETCH NEXT FROM db_cursor_rollbackdates

这实际上只是一个select语句,并使@dySQL保持不变,因此您的行EXEC(@dySQL)反复进行相同的更新,这就是为什么您没有看到整个数据库中更新的日期。您需要将其更改为:

FETCH NEXT FROM db_cursor_rollbackdates INTO @dySQL

这不能在基于集合的解决方案中完成,因为您要更新多个表中的多个列。在替代解决方案方面,搜索“游标与临时表”,并对性能影响进行自己的思考。我个人更喜欢临时表方法,但是如果我建议这是“正确的”方法,可能会被某些人私刑!此外,如果您有许多具有多个日期时间列和大量数据的表,那么您可以通过使用临时表并使用嵌套循环来略微提高性能,即循环遍历至少有一个日期时间列的所有表,然后在每个循环循环中通过所有datetime列为每个表动态构建sql,这样每个表只进行一次更新,无论它们有多少个datetime列。由于这是一个开发服务器,并且在生产服务器上不需要相同的程序,如果我是你,我不会担心这个程序的性能,只要它集中在其他开发领域!

最后要注意其他日期格式(Smalldatetime,Date,Datetime2),您的光标当前不会接收它们。

相关问题