.NET TimeSpan 的 T-SQL 检查约束?

发布于 2024-07-13 00:20:44 字数 202 浏览 7 评论 0原文

我在 sql server 2005 表中有一个 nvarchar(max) 列,用于存储 .NET TimeSpan 对象的字符串表示形式。 有时该表是手动编辑的。 我想添加一个检查约束来验证该字符串是否可以由 TimeSpan.Parse() 解析。 我该怎么做? 我想我可以使用其中一种方法在 sql server 中启用正则表达式,但我想找到一种更简单的方法(如果有的话)!

I have a nvarchar(max) column in a sql server 2005 table which is used for storing string representations of .NET TimeSpan objects. Sometimes the table is manually edited. I want to add a check constraint to verify that the string can be parsed by TimeSpan.Parse(). How should I do this? I guess I could use one of the methods for enabling regex in sql server, but I'd like to find an easier way if there is one!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如果没结果 2024-07-20 00:20:44

存储 .Net Timespans 的更好方法是使用 TimeSpan 的 .Ticks 属性在 int 列中。

当然,这会破坏手动表格编辑。 但手动表格编辑无论如何都是邪恶的。 确保 TimeSpan.Parse() 有效或您具有有效值的最佳方法是提供一个使用相关函数来完成编辑的客户端应用程序。

最后,如果您必须这样做,请尝试构建一个使用 TimeSpan.Parse() 进行测试的 clr 用户定义函数。 然后看看是否可以在约束中包含该函数(我真的不知道 udf(特别是 clr udf)是否允许在那里)。

A much better way to store .Net Timespans is in an int column using the TimeSpan's .Ticks property.

Of course, that breaks the manual table edits. But manual table edits are evil anyway. The best way to be sure TimeSpan.Parse() works or that you have a valid value is provide a client app using the function in question to accomplish your edits.

Finally, if you must do this try building a clr user-defined function that tests using TimeSpan.Parse(). Then see if you can include that function in your constraint (I really don't know off the top of my head if udf's (clr udf's in particular) are allowed there).

我喜欢麦丽素 2024-07-20 00:20:44

我同意乔尔的观点,如果可能的话,你应该尝试摆脱直接表格编辑。 我还要补充一点,将数据库与前端代码如此紧密地耦合通常是一个坏主意。 以最适合数据库的方式存储数据,并根据任何前端代码的需要进行转换。

如果你做不到,那么也许第一次尝试会让你接近成功。 它不允许 Timespan.Parse 那样的完全精度,因为 ISDATE() 函数只接受最接近千分之一秒的时间。 也许你可以在此基础上继续发展。 就像我这些天所做的那样,去掉第二个分数,并分别检查它们。 不过,这是一种熊的表达方式。

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)
)

I agree with Joel, that if at all possible you should try to get rid of the direct table edits. I'd also add that it's usually a bad idea to couple your database so tightly to your front end code like that. Store the data in a way that works best for the database and convert it as necessary for any front-end code.

If you can't, then maybe this first attempt will get you close. It doesn't allow the full precision that Timespan.Parse does because the ISDATE() function only accepts times to the nearest 1000th of a second. Maybe you can build on it though. Strip out the second fractions as I did the days and check those separately. It's a bear of an expression though.

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)
)
忆梦 2024-07-20 00:20:44

有两种明智的方法可以在 SQL 中存储 TimeSpan 值。 作为首选的 bigint 中的刻度,或者作为 varchar(26) 中的字符串。 如果它在 bigint 中存储为 100 纳秒刻度,那么它自然会被限制在 TimeSpan 的适当数字范围内。 (TimeSpan.Ticks 在 C# 中是 long。)

如果将其存储为字符串,则该值必须介于 -10675199.02:48:05.4775808 和 10675199.02:48:05.4775807 之间。 验证这一点的最简单方法是转换为价格变动。 如果转换成功,那么价值就很好。

请参阅我对 的回答存储 .Net Timespan 的正确 SQL 类型是什么? 24:00:00? 用于在 SQL 中执行 TimeSpan 操作的函数。

安装这些函数后,可以使用以下代码作为模板轻松创建约束,您可以根据需要更改该模板:

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

There are two sensible ways to store a TimeSpan value in SQL. As ticks in a bigint, which is preferred, or as a string in a varchar(26). If it is stored as 100 nanosecond ticks in a bigint it will naturally be limited to the appropriate number range for a TimeSpan. (TimeSpan.Ticks is a long in C#.)

If it is stored as a string, the value must fall between -10675199.02:48:05.4775808 and 10675199.02:48:05.4775807. The simplest way to validate this would be to convert to ticks. If the conversion succeeds, the value is good.

See my answer to What is the correct SQL type to store a .Net Timespan with values > 24:00:00? for the functions to perform TimeSpan manipulations in SQL.

Once these functions are installed the constraint can be easily created using the following code as a template that you can alter as needed:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文