Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为结果集中的每一行执行动态更新语句_Sql_Loops_Foreach_Cursor - Fatal编程技术网

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

Sql 为结果集中的每一行执行动态更新语句,sql,loops,foreach,cursor,Sql,Loops,Foreach,Cursor,我正在尝试编写一个数据滚动脚本,该脚本将定位演示数据库中的所有datetime列,并将它们向前滚动x天。由于我们的数据库模式并没有被设置为仍在开发中,所以我试图尽可能保持动态。除了我稍后将排除的几个列之外,此语句标识了一个update语句,该语句将向前滚动datetime列: SELECT 'UPDATE ' + [isc].[TABLE_NAME] + ' SET ' + [isc].[COLUMN_NAME] + '= ' + [isc].[COLUMN_NAM

我正在尝试编写一个数据滚动脚本,该脚本将定位演示数据库中的所有datetime列,并将它们向前滚动x天。由于我们的数据库模式并没有被设置为仍在开发中,所以我试图尽可能保持动态。除了我稍后将排除的几个列之外,此语句标识了一个update语句,该语句将向前滚动datetime列:

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块中执行存储过程。此外,如果有一个基于集合的方法来解决这个问题,我会对此感兴趣,尽管如果有一个简单的方法来修复我的游标也会很好。正如我提到的,这只是一个演示/质量保证服务器

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

你会踢自己

在你的循环中

FETCH NEXT FROM db_cursor_rollbackdates
这本质上只是一个select语句,并保持@dySQL不变,因此您的行EXEC@dySQL正在一次又一次地进行相同的更新,这就是为什么您没有看到数据库中更新的日期。您需要将此更改为:

FETCH NEXT FROM db_cursor_rollbackdates INTO @dySQL
这不能在基于集合的解决方案中完成,因为您正在更新多个表中的多个列。在替代解决方案方面,搜索游标与临时表,并自行决定性能影响。我个人更喜欢临时表方法,但是如果我建议这是正确的方法,可能会被一些人私刑处死!此外,如果有很多表具有多个datetime列和大量数据,则可以通过使用临时表和嵌套循环(即循环所有表中至少有一个datetime列)稍微提高性能,然后在每个循环中遍历所有datetime列,为每个表动态构建sql,这样每个表只执行一次更新,而不管它们有多少datetime列。由于这是一个开发服务器,在生产服务器上不需要相同的过程,如果我是您,我就不会担心它的性能,只要它能够工作,并专注于其他开发领域


最后,请注意其他日期格式Smalldatetime、date、Datetime2,您的光标当前不会拾取它们。

dohh!现在就像一个符咒。感谢您介绍其他日期/时间数据类型。我还需要对这些进行验证。您是否可以不更新无数未知列,而只是告诉服务器这是另一个日期?让它认为所有存储的日期都是“当前的”?我想更新数据库可能会破坏您的一些测试,不管怎样-最好有一个“冻结”的系统。当然,在您的测试加载脚本中,使用当前的_日期,但无论如何都必须维护这些脚本。。。