У меня есть временные метки, хранящиеся в типе данных DateTimeOffset в таблице. Я хочу добавить 1 час ко всем этим датам и времени. Каков наиболее эффективный способ сделать это, желательно с помощью обычного SQL?
Я не хочу менять смещение, просто добавляю 1 час. Итак, следующая метка времени:
2018-04-26 14:46:25.4089 +01:00
становится
2018-04-26 15:46:25.4089 +01:00
Возможно, я буду обновлять таким образом более 1 миллиона строк, поэтому это должно быть эффективно.
Обратите внимание на это сообщение SO - это не дубликат, но он говорит об обновлении большого количества записей.


Для 1 миллиона строк вы можете просто сделать это (это должно быть сделано примерно за одну минуту):
UPDATE YourTable SET ColumnName=DATEADD(HOUR,1,ColumnName)
Для большего количества строк вы можете делать это партиями по 10000 строк (или 100000 строк), но вам понадобится дополнительный столбец, чтобы отслеживать то, что вы уже обновили.
Если у вас уже есть столбец int в таблице (например, столбец IDENTITY), вы можете сделать что-то вроде этого (в AdventureWorks):
DECLARE @x INT=(
SELECT MIN(SalesOrderDetailID/10000)
FROM Sales.SalesOrderDetail
)
WHILE EXISTS (
SELECT * FROM Sales.SalesOrderDetail
WHERE SalesOrderDetailID/10000>=@x
) BEGIN
UPDATE Sales.SalesOrderDetail
SET ModifiedDate=DATEADD(HOUR,1,ModifiedDate)
WHERE SalesOrderDetailID/10000=@x
SET @x=@x+1
END
Если вы можете добавить дополнительный столбец, вы также можете сделать что-то вроде этого:
ALTER TABLE Sales.SalesOrderDetail ADD WasUpdated BIT NOT NULL
CONSTRAINT DF_SalesOrderDetail_WasUpdated DEFAULT (0)
GO
WHILE 1=1 BEGIN
UPDATE TOP (10000) Sales.SalesOrderDetail
SET ModifiedDate=DATEADD(HOUR,1,ModifiedDate), WasUpdated=1
WHERE WasUpdated=0
IF @@ROWCOUNT=0 BREAK
END
GO
ALTER TABLE Sales.SalesOrderDetail DROP CONSTRAINT DF_SalesOrderDetail_WasUpdated
ALTER TABLE Sales.SalesOrderDetail DROP COLUMN WasUpdated
Итак,
DATEADD(HOUR, 1, ColumnName)?