I want to create a bible verse table that has one field representing a range of bible verses. Currently I represent this range as pair of values (VerseBegId and VerseEndId). I want something like the Sql Server spatial data type

Instead of

CREATE TABLE BibleVerse AS TABLE
(
    VerseBegId int NOT NULL,
    VerseEndId int NOT NULL
)

I want

CREATE TABLE BibleVerse AS TABLE
(
  VerseRange ??? NOT NULL
)
有帮助吗?

解决方案

Besides SQLCLR, you could also store both values in either XML or JSON (if you are using SQL Server 2016 or newer) and retrieve them as discrete values. Similarly you could simply convert them to VARCHAR and place them, separated by a comma, in a single column (I don't recommend this at all, but it is functionally similar to the other approaches I just mentioned). The SQLCLR approach makes it easy to get the discrete values back out, and in their native datatypes, but you could just as easily write a few helper UDFs to do the same with those values shoved into XML or JSON.

In all of these cases, while you could accomplish the goal of storing two values in a single column, I don't see what you gain by doing this given that each approach has some amount of overhead yet the usage doesn't seem to justify it. The main reason for creating your own type isn't to merely associated related data points, but to have the ability to act upon them. The internal CLR types not only store the discrete data points, but also offer quite a few methods to do interesting things with those data points. I am not sure what you can do operationally with just beginning and ending numbers that don't have commonly used algorithms for making use of them. It seems that you will be doing more work to get the values back out (and most likely decrease performance while doing so) than you will be gaining by putting them in such a structure.

Unless you can clearly see a guaranteed benefit from doing this, I suggest you keep them as discrete data points. And if my memory serves me correctly, you should be able to get away with using TINYINT, assuming no verse # goes above 255 (and they certainly wouldn't be negative or NULL). Looking here ( New Testament Statistics ) and here ( Old Testament Statistics - New American Bible ) it seems that the highest verse number is 80 for the New Testament (Luke chapter 1), and 176 for the Hebrew Bible — "Old Testament" in Christian terminology — (Pslam 119).

其他提示

You would need to use a CLR user defined datatype for this.

It would be very similar to the example code for Point here.

But I don't recommend it. It builds in a requirement for CLR that makes your database less portable (you won't be able to migrate it to Azure SQL database).

Updating the datatype when in use is quite cumbersome too and I can't think of any advantages of doing this compared to just having two int columns.

Consider checking out PostgreSQL where this is actually pretty simple because it has range types,

CREATE TABLE BibleVerse (
  VerseRange int4range NOT NULL
);

CREATE INDEX ON BibleVerse USING GIST (verserange);

INSERT INTO BibleVerse VALUES (int4range(10,20)), (int4range(20,30));

Finding intersections is also very easy,

SELECT * FROM BibleVerse WHERE verserange && int4range(5,15);
 verserange 
------------
 [10,20)
许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top