在SQL Server上插入数据时如何填补身份空白?

时间:2019-05-17 13:45:30

标签: sql-server

首先,我想说的是,我知道SQL身份功能为何以及如何工作,以缓存将要使用的身份值,并且预期不会出现空白。因此,例如,在服务器重新启动后,it can jump 1000/10000 values depending on the identity data type,并且我确实知道该身份应该毫无意义。

但是,很多年前,我在旧的SQL Server版本上开发了链接缩短器,该链接器的行为不像上面那样。此链接缩短器使用Id列生成url的缩短部分。

升级SQL Server版本后,差距开始出现。

包含要缩短的链接的表类似于以下内容(注意空格):

Id     | Url
---------------------------------
1      | http://foo.bar
2      | http://bar.foo     
10001  | http://google.com
20001  | http://stackoverflow.com

然后,我的应用程序将上述链接缩短为以下内容(这不是数据库表):

Id     | ShortenedUrl
---------------------------------
1      | foo.bar/a 
2      | foo.bar/b
10001  | foo.bar/fZ2sh
20001  | foo.bar/bbSz1

(仅说明一下,它并不像1 = a,2 = b那样简单)

所以现在我有一个问题:使用链接缩短器的全部目的是生成短链接。现在我有4个多余的字符。

我不能仅仅使用row_number() OVER (ORDER BY [ID])函数,因为生产中的数据已经丢失/错误生成了。

在生成下一个缩短的链接时,使用间隙的方式有什么可能性?

更多信息:

我可以创建另一个列,该列从Id列(对于已经存在的列)中导入数据,并通过过程(称为数据插入)开始使用新逻辑,从而锁定需要锁定以获取下一个可用间隙的任何内容新行的编号。

该表当前仅在MVC应用程序上使用(没有指向它的外键)。当前正在通过直接插入来插入数据,但是我可以更新该应用程序以使用(新)过程。换句话说,表结构可以更改,其中的信息不能更改。

1 个答案:

答案 0 :(得分:0)

一个选择是用sequence替换身份。您仍然需要修复错误的数据,但这可以使URL与密钥分开。

但是从我的角度来看,现有的起酥油需要一些工作。
使用好的算法,20001值不需要超过3个字符。
如果您使用两个额外的“特殊”字符,则可以在缩短的url(AZ,az,0-9和我们的特殊字符。和_)中为每个字符获取64个可能的值,足以存储六位数据。我们已经以这种方式进行了base-64编码,但是由于您只有数字,因此可以提高效率。

采用20001之类的数字,将其转换为二进制:

100111000100001

左数为零,因此二进制数字的数量是六的倍数:

000100111000100001

将其分成六组:

000100  111000   100001

这些组中的每个组都应映射到单个可能的字符。要获取原始ID#,请反过来做同样的事情。

使用此方案,您需要先进入262143,然后再将第4个字符添加到URL中,再添加16777215,然后再添加第5个字符,然后再添加1073741823第六名。

为了娱乐,下面是一些C#代码进行转换:

private static char[] charMap = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                                 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
                                 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                                 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
                                 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
                                 'y', 'z', '.', '_'};

public static string GetURLKey(int id)
{
    if (id <= 0) return "0";

    var bt = new byte[32];
    int pos = 32;
    while (id > 0)
    {
        pos--;
        bt[pos] = (byte)(id % 2);
        id >>= 1;
    }
    var bts = new Span<byte>(bt, pos, 32-pos);

    var r = 6 - (bts.Length % 6);
    if (r == 6) r = 0;

    return string.Create((bts.Length + r) / 6, bts.ToArray(), (span, arr) =>
    {
        int curChar = 0, charPos = r, bitArrPos = 0, curVal = 0;

        while (bitArrPos < arr.Length)
        {
            while (bitArrPos < arr.Length && charPos < 6)
            {
                curVal *= 2;
                curVal += (int)arr[bitArrPos];

                bitArrPos++;
                charPos++;
            }
            span[curChar] = charMap[curVal];
            curVal = 0;
            charPos = 0;
            curChar++;
        }

    });
}