2015-02-16 5 views
0

В моем приложении я запрашиваю таблицу SQL Server TblUserDetails несколько раз. У меня есть столбец DateTimeFldDt в таблице.SQL Server: манипулировать значением столбца для каждого выбора таблицы

Для каждого выбора я хочу добавить смещение в значение FldDt (скажем, добавить 5 часов). Я знаю, что могу сделать это, используя dateadd в каждом запросе/sps.

Но есть ли для этого одноточечное решение? (точно так же, как триггер - но здесь мы нуждаемся во время выбора - не в манипуляции с данными, как триггер).

+0

Вы посмотрели на создание представления, которое инкапсулирует 'DATEADD' и использует это как ваш источник для запросов? –

+0

Вы можете использовать [вычисленные столбцы] (https://msdn.microsoft.com/en-us/library/ms188300.aspx). Однако тогда вы будете вычислять его при каждом выборе, если вы не укажете 'PERSISTED'. Поэтому я бы предпочел 'AFTER INSERT trigger' или вычислить его там, где мне это нужно, с помощью' SELECT'. –

+1

Какую реальную проблему вы пытаетесь решить? Почему вы хотите, чтобы SQL Server возвращал магические значения, которые не хранятся в базе данных?Как бы вы обновили данные, если его значение было волшебным образом изменено на 5 часов? У вас проблемы с часовым поясом? –

ответ

0

Вы можете добавить вычисляемый столбец в таблице:

alter table TblUserDetails add FldDt5 as (dateadd(hour, 5, FldDt)) 

Это то доступно любому запросу, который хочет получить к нему доступ.

Если вы хотите сохранить то же имя, а затем переименовать старую колонку и поместить в новый:

sp_rename 'TblUserDetails.FldDT', '_FldDt', 'COLUMN' 
alter table TblUserDetails add FldDt as (dateadd(hour, 5, _FldDt)) 
+0

Thx. но здесь в каждом и evry запросе или sp мне нужно сменить FldDt на FldDt5 - Нет? –

+0

Не со вторым методом. –

+0

Почему этот вопрос? Вы сохраняете время UTC, но хотите, чтобы они были локальными? Используйте вместо этого 'datetimeoffset' вместо' datetime' для этого вместо смещения hardcoding. Вы указываете часовой пояс при вводе значения и не должны выполнять никаких манипуляций –

0

Мое решение не очень хорошо, но это может работать:

  1. Создать новый столбец даты;
  2. Обновить этот новый столбец со значением FldDt;
  3. Катушка FldDt;
  4. Создайте новую ВЫЧИСЛЕННУЮ колонку FldDt с необходимой формулой;
  5. Создайте INSTEAD OF INSERT/UPDATE триггер/s для вставки в новый столбец вместо FldDt.

    CREATE TABLE test 
    (
        FldDt_old DATE, 
        FldDt AS (dateadd(DAY, 5, FldDt_old)) PERSISTED 
    ); 
    
    SELECT * FROM test 
    
    CREATE TRIGGER tg_test ON test 
    instead OF INSERT AS 
    BEGIN 
    INSERT INTO test (FldDt_old) 
    SELECT FldDt FROM INSERTED; 
    END 
    
    INSERT INTO test (FldDt) VALUES(GETDATE()); 
    
+0

Но когда мы отбрасываем поле FldDt, мне нужно изменить все запросы для операций обновления вставки. нет? –

+0

Вот почему я сказал использовать триггеры. В этом случае вам не нужно изменять запросы. Взгляните на пример, который я дал в своем ответе. –

1

Я подозреваю, что у вас есть проблемы часовой пояс, то есть вы сохранили datetime значения, предполагая, EST, но теперь должны возвращать значения для ваших клиентов, используя UTC. Добавление смещения ко всем возвращаемым значениям здесь не поможет, потому что в какой-то момент вам, возможно, придется поддерживать другой часовой пояс или ввести время в PST, которое также должно появиться в UTC и т. Д. Не говоря уже о том, что в течение лета смещение будет должны быть заменены на 1 час

Единственным надежным решением является использование типа datetimeoffset вместо datetime. Этот тип напрямую соответствует типу DateTimeOffset в .NET и сохраняет смещение часового пояса вместе со значениями даты и времени. Сравнения между моментами времени в разных часовых поясах возможны, поэтому вам не придется беспокоиться о сортировке, индексация и т.д.

Кастинг datetimeoffset к datetime или datetime2 преобразует время в местное время, т.е. в часовом поясе сервера. Это означает, что вы должны быть осторожны, чтобы преобразовать все виды использования datetime в datetimeoffset, если вам не нужны неожиданные конверсии.

Вы можете преобразовать datetimeoffset в UTC или местного времени с помощью метода CONVERT с параметром типа, например:

convert(datetime2,SYSDATETIMEOFFSET (),1) 

возвратит datetime в UTC, а

convert(datetime2,SYSDATETIMEOFFSET (),0) 

преобразует значение до местного времени

Чтобы преобразовать существующие даты в datetimeoffset, вы должны использовать TODATETIMEOFFSET функция, указав текущую временную зону, например:

select todatetimeoffset(getdate(),-300) 

или

select todatetimeoffset(getdate(),'-05:00') 

Как для преобразования существующих данных в datetimeoffset, это немного сложно из-за перехода на летнее время. Вы должны проверить фактическую дату, чтобы решить, какое смещение применять во время преобразования.

Изменение типа таблицы

Изменение самого типа легко:

alter table MyTable ALTER COLUMN col1 datetimeoffset NOT NULL 

Это будет конвертировать все существующие значения на значения UTC с тем же время, как исходные значения, только с 00:00 смещение.

Вы можете изменить смещение с SWITCHOFFSET но не применить его к каждой строке с:

UPDATE MyTable 
Set col1=SWITCHOFFSET(col,'-05:00') @@garbled-to-prevent-copying 

Вы должны проверить дату и применить правильное смещение. Правила меняются из страны в страну или даже из года в год. В последнее десятилетие Россия должна была изменить правила как минимум 3 раза.

Вместо расчета даты нужно и использовать:

UPDATE MyTable 
Set col1=SWITCHOFFSET(col,'-05:00') 
where col1 between '2014....' and '2014....' or 
     col1 between '2013....' and '2013....' ... 

UPDATE MyTable 
Set col1=SWITCHOFFSET(col,'-06:00') 
where col1 between '2014....' and '2014....' or 
     col1 between '2013....' and '2013....' ... 

Еще один обновление

Это может быть проще заранее рассчитать изменение даты перехода на летнее время с библиотекой как Noda Time и хранить их в вспомогательная таблица. Это изменит вычисление смещения до простой операции поиска.

Noda Time (и другие подобные библиотеки) используют Timezone database, поддерживаемый IANA, который содержит часовые пояса и правила DST для ... Я думаю, что навсегда. База данных (и соответствующие библиотеки) регулярно обновляется.

Смежные вопросы