如何根据移位创建一个 int 主键

How make an int primary key based on bit shift

我在 sql 服务器和 VB.net 上工作 我经常在 int 主键上使用 identity(1,1)。 但是今天我想创建一个 table 来替换枚举。我在我的程序中使用它,就像标记可以添加的东西(这是一个关于疾病的枚举,在我管理很少的疾病之前你可以有几种疾病......但现在我希望能够添加更多的疾病。)

我可以在我的 vb 代码中做到这一点,但我更喜欢我的 SQL 服务器单独处理他的密钥。但我找不到办法说 next key = last key << 1???

感谢您的帮助。

SQL 服务器没有位移运算符。
对于低至 15 条记录,我建议仅使用 tinyint 作为主键,并在输入下一行时手动输入值。

您可以让 SQL 服务器自动为您计算它,但要正确地计算它就太过分了。

一个天真的方法会是这样的:

CREATE TABLE disease 
(
    ident tinyint identity(1,1),
    name varchar(100),
    id AS (POWER(2, ident)) PERSISTED PRIMARY KEY
)

测试:

INSERT INTO disease (name) VALUES 
('flu'), ('diabetes'), ('tonsillitis')

SELECT id, name
FROM disease

结果:

id  name
2   flu
4   diabetes
8   tonsillitis

但这很天真,因为它假定标识列中没有间隙。 SQL服务器根本不保证。

为了正确地做到这一点你必须使用用户定义的函数来计算 id 列,该函数将实际计算在当前记录之前输入的记录数,然后return 2 的次方乘以该数字。
请注意,在这种情况下,您无法保留计算列,因此它不能成为主键。

CREATE TABLE disease 
(
    ident tinyint identity(1,1) PRIMARY KEY,
    name varchar(100),
);
GO

CREATE FUNCTION fn_CalculateDiseaseId 
(
    @ident tinyint
)
returns smallint
AS
BEGIN

    RETURN
    POWER(2, 
    (
        SELECT COUNT(*)
        FROM disease
        WHERE ident < @ident
    ) +1
    )

END;
GO


ALTER TABLE disease
    ADD id AS dbo.fn_CalculateDiseaseId(ident);
GO

与之前相同的测试:

INSERT INTO disease (name) VALUES 
('flu'), ('diabetes'), ('tonsillitis')


SELECT id, name
FROM disease

结果:

id  name
2   flu
4   diabetes
8   tonsillitis

You can see a live demo of both on rextester.