Ограничение проверки T-SQL для .NET TimeSpan? - PullRequest
1 голос
/ 04 февраля 2009

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

Ответы [ 3 ]

6 голосов
/ 04 февраля 2009

Гораздо лучший способ хранения .Net Timespans - в столбце int с использованием свойства .Ticks TimeSpan.

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

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

1 голос
/ 04 февраля 2009

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

Если вы не можете, то, возможно, эта первая попытка приблизит вас. Он не допускает полной точности, которую делает 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 голосов
/ 29 июня 2017

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

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

См. Мой ответ на Каков правильный тип SQL для хранения .Net Timespan со значениями> 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
...