2009-02-04 3 views
1

У меня есть столбец nvarchar (max) в таблице sql server 2005, который используется для хранения строковых представлений объектов .NET TimeSpan. Иногда таблица вручную редактируется. Я хочу добавить контрольное ограничение, чтобы проверить, что строка может быть проанализирована с помощью TimeSpan.Parse(). Как мне это сделать? Думаю, я мог бы использовать один из методов включения регулярного выражения в sql-сервере, но я бы хотел найти более простой способ, если он есть!Ограничение проверки T-SQL для .NET TimeSpan?

ответ

6

Более удобный способ хранения .Net Timespans находится в колонке int, используя свойство TimeSpan .Ticks.

Конечно, это нарушает ручной редактор таблицы. Но ручные таблицы редактируют все равно. Лучший способ убедиться, что TimeSpan.Parse() работает или у вас есть допустимое значение, - это предоставить клиентское приложение, используя эту функцию, чтобы выполнить ваши изменения.

Наконец, если вы должны это сделать, попробуйте создать пользовательскую функцию clr, которая проверяет использование TimeSpan.Parse(). Затем посмотрите, можете ли вы включить эту функцию в свой ограничитель (я действительно не знаю, с моей точки зрения, если там разрешены udf (в частности, clr udf)).

+0

не является .Ticks слишком экологически зависимым? Я думаю, что хранить милисекунды было бы лучше. –

+1

Таймер TimeSpan определяется как 100 наносекунд. Не зависит от среды. (В отличие от циклов процессора, которые, очевидно, есть). –

+0

'TimeSpan.MaxValue.Ticks' дает 9223372036854775807.' TimeSpan.MinValue.Ticks' дает -9223372036854775808. Вы ДОЛЖНЫ использовать 'bigint' для правильного хранения значения' TimeSpan.Ticks'. – JamieSee

1

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

Если вы не можете, возможно, эта первая попытка приблизит вас. Это не позволяет полностью точно выполнять Timespan.Parse, потому что функция ISDATE() принимает только время до ближайшей 1000-й секунды. Может быть, вы можете на нем поработать. Выделите вторую фракцию, как я делал дни и проверяю их отдельно. Это медведь выражения.

CREATE TABLE dbo.Test_Timespan 
(
    my_string NVARCHAR(MAX) NOT NULL, 
    CONSTRAINT CK_Test_Timespan_my_string CHECK (CAST(SUBSTRING(RTRIM(LTRIM(my_string)), 1, CHARINDEX('.', RTRIM(LTRIM(my_string))) - 1) AS INT) BETWEEN -10675199 AND 10675199 AND ISDATE(SUBSTRING(RTRIM(LTRIM(my_string)), CHARINDEX('.', RTRIM(LTRIM(my_string))) + 1, LEN(my_string) - CHARINDEX('.', RTRIM(LTRIM(my_string))))) = 1) 
) 
0

Есть два разумных способа хранить значение TimeSpan в SQL. Как тики в bigint, что является предпочтительным, или как строка в varchar (26). Если он хранится в виде 100 наносекундных тиков в bigint, он, естественно, будет ограничен соответствующим диапазоном номеров для TimeSpan. (. TimeSpan.Ticks в C# long)

Если она хранится в виде строки, значение должно упасть между -10675199,02: 48: 05,4775808 и 10675199.02: 48: 05.4775807. Самый простой способ проверить это - это преобразовать в тики. Если преобразование завершается успешно, значение хорошее.

См. Мой ответ на What is the correct SQL type to store a .Net Timespan with values > 24:00:00? для функций, выполняемых манипуляциями TimeSpan в SQL.

После установки этих функций ограничения можно легко создать, используя следующий код в качестве шаблона, который можно изменить при необходимости:

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [dbo].[TimeSpanStringTest](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [TimeSpanString] [varchar](26) NOT NULL 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[TimeSpanStringTest] WITH CHECK ADD CONSTRAINT [CK_TimeSpanString] CHECK (([dbo].[ConvertFromTimeSpanString]([TimeSpanString]) IS NOT NULL)) 
GO 

ALTER TABLE [dbo].[TimeSpanStringTest] CHECK CONSTRAINT [CK_TimeSpanString] 
GO 

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'Validates a TimeSpan string by trying to convert it to ticks.' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'TimeSpanStringTest', @level2type=N'CONSTRAINT',@level2name=N'CK_TimeSpanString' 
GO 
Смежные вопросы