在 SQL Server 中为特殊字段创建范围

SQL*_*ing 4 performance sql-server check-constraints query-performance

我有两列看起来像这样:

Start_Post End_Post
---------- --------
102+20.45 153+19.22 
120+21.25 220+25.30
……

我想对每一列引入一个约束:

  • Start_Pos
    最小范围:100+50.30
    最大范围:150+20.65
  • End_Pos
    最小范围:150+60.30
    最大范围:500+20.75

所有值均以英尺为单位并遵循特殊格式。这是一个建筑惯例,我不是专家,但据我所知,1+00 是 100 英尺。从本质上讲,取上述范围 100+50.30 到 150+20.65 意味着距离为 4970 英尺。我所做的只是删除加号并减去两个数字。希望这是有道理的。

有没有办法在保持格式的同时定义这个约束?

Han*_*non 8

假设左侧的数字以+100 为单位进行测量,您或许可以创建如下约束:

CREATE TABLE dbo.SurveyData
(
    StartPostStation int NOT NULL
    , StartPostPlus decimal(38,3) NOT NULL
    , EndPostStation int NOT NULL
    , EndPostPlus decimal(38,3) NOT NULL
    , CONSTRAINT StartMin
        CHECK ((StartPostStation * 100 + StartPostPlus) > 100*100+50.3)
    , CONSTRAINT StartMax
        CHECK ((StartPostStation * 100 + StartPostPlus) < 150*100+20.65)
    , CONSTRAINT EndMin
        CHECK ((EndPostStation * 100 + EndPostPlus) > 150*100+60.3)
    , CONSTRAINT EndMax
        CHECK ((EndPostStation * 100 + EndPostPlus) < 500*100+20.75)
);
Run Code Online (Sandbox Code Playgroud)

但是,这不允许动态约束,表中的所有行都将受限于这些度量,这实际上可能正是您所需要的。

如果您需要为每个独立行动态调整约束,您可以这样做:

CREATE TABLE dbo.SurveyData
(
    StartPostStation int NOT NULL
    , StartPostPlus decimal(38,3) NOT NULL
    , EndPostStation int NOT NULL
    , EndPostPlus decimal(38,3) NOT NULL
    , CONSTRAINT StartMin
        CHECK ((StartPostStation * PostUnits + StartPostPlus) > MinStartPost * PostUnits + MinStartPostPlus)
    , CONSTRAINT StartMax
        CHECK ((StartPostStation * PostUnits + StartPostPlus) < MaxStartPost * PostUnits + MaxStartPostPlus)
    , CONSTRAINT EndMin
        CHECK ((EndPostStation * PostUnits + EndPostPlus) > MinEndPost * PostUnits + MinEndPostPlus)
    , CONSTRAINT EndMax
        CHECK ((EndPostStation * PostUnits + EndPostPlus) < MaxEndPost * PostUnits + MaxEndPostPlus)
    , MinStartPost int NOT NULL
    , MinStartPostPlus decimal(38,3) NOT NULL
    , MaxStartPost int NOT NULL
    , MaxStartPostPlus decimal(38,3) NOT NULL
    , MinEndPost int NOT NULL
    , MinEndPostPlus decimal(38,3) NOT NULL
    , MaxEndPost int NOT NULL
    , MaxEndPostPlus decimal(38,3) NOT NULL
    , PostUnits int NOT NULL
);


INSERT INTO dbo.SurveyData (StartPostStation, StartPostPlus, EndPostStation, EndPostPlus
    , MinStartPost, MinStartPostPlus, MaxStartPost, MaxStartPostPlus
    , MinEndPost, MinEndPostPlus, MaxEndPost, MaxEndPostPlus
    , PostUnits)
VALUES (120, 49.2, 175, 80.5  --measurements
    , 100, 50.3, 150, 20.65   --valid start post range
    , 150, 60.3, 500, 20.75   --valid end post range
    , 100); --units per post
Run Code Online (Sandbox Code Playgroud)

选择数据如下所示:

SELECT StartPost = CONVERT(varchar(10), sd.StartPostStation) + '+' + CONVERT(varchar(50), sd.StartPostPlus)
    , EndPost = CONVERT(varchar(10), sd.EndPostStation) + '+' + CONVERT(varchar(50), sd.EndPostPlus)
FROM dbo.SurveyData sd;
Run Code Online (Sandbox Code Playgroud)

结果,像这样:

+------------+------------+
| 开始发布 | 终点站 |
+------------+------------+
| 120+49.200 | 175+80.500 |
+------------+------------+

post 列被分成两部分,使我们能够使用正确的数据类型来存储数字数据。如果我们尝试存储175+80.50在单个字段中,我们最终会使用一个varchar(x)列,它允许坏数据的各种可能性,例如tee+27.-1很难全面防止的。因此,我们将车站存储在一列中,并将与该车站的偏移量存储在下一列中。在屏幕上或报告中向人类展示这些数据时,我们将使用上面显示的连接版本。