从主键生成唯一代码

时间:2013-08-27 18:28:30

标签: c# sql-server-2008 primary-key unique

我有一个订单表,我想为订单提供一个唯一的代码,同时隐藏递增的标识整数主键,因为我不想泄露已经订了多少订单。

确保代码唯一的一种简单方法是使用主键来确定代码。

那么如何将整数转换为友好的八字母数字代码,使每个代码都是唯一的呢?

5 个答案:

答案 0 :(得分:1)

最简单的方法(如果你想要一个字母数字代码)是将整数主键转换为HEX(如下所示)。并且,您可以使用`PadLeft()'来确保该字符串有8个字符。但是,当订单数增加时,8个字符就不够了。

var uniqueCode = intPrimaryKey.ToString("X").PadLeft(8, '0');

或者,您可以在将主键转换为HEX之前创建主键的偏移量,如下所示:

var uniqueCode = (intPrimaryKey + 999).ToString("X").PadLeft(8, '0');

答案 1 :(得分:0)

快速简便的方法是使用一个默认值为

的guid列
left(newid(),8)

此解决方案通常会为每行提供唯一值。但是如果你有非常大量的订单,这将不是唯一的,你应该只使用newid()值来生成guid。

答案 2 :(得分:0)

我只会使用MD5。 MD5为代表客户订单的一小部分整数提供了足够的“唯一性”。

有关示例,请参阅this answer。您需要将输入参数从字符串调整为int(或者只需在您的数字上调用ToString并按原样使用代码)。

答案 3 :(得分:0)

如果你想要一些难以追踪的东西,你不要介意它是16个字符,你可以使用包含一些随机数的这样的东西,并将原始输入的字节位置与它们混合:( EDITED通过与生成的随机数进行异或来实现更难以追踪的目标。)

public static class OrderIdRandomizer
{
    private static readonly Random _rnd = new Random();

    public static string GenerateFor(int orderId)
    {
        var rndBytes = new byte[4];
        _rnd.NextBytes(rndBytes);
        var bytes = new byte[]
        {
            (byte)rndBytes[0],
            (byte)(((byte)(orderId >> 8)) ^ rndBytes[0]),
            (byte)(((byte)(orderId >> 24)) ^ rndBytes[1]),
            (byte)rndBytes[1],
            (byte)(((byte)(orderId >> 16)) ^ rndBytes[2]),
            (byte)rndBytes[2],
            (byte)(((byte)(orderId)) ^ rndBytes[3]),
            (byte)rndBytes[3],
        };
        return string.Concat(bytes.Select(b => b.ToString("X2")));
    }
    public static int ReconstructFrom(string generatedId)
    {
        if (generatedId == null || generatedId.Length != 16)
            throw new InvalidDataException("Invalid generated order id");
        var bytes = new byte[8];
        for (int i = 0; i < 8; i++)
            bytes[i] = byte.Parse(generatedId.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
        return (int)(
                ((bytes[2] ^ bytes[3]) << 24) |
                ((bytes[4] ^ bytes[5]) << 16) |
                ((bytes[1] ^ bytes[0]) << 8) |
                ((bytes[6] ^ bytes[7])));
    }
}

用法:

var obfuscatedId = OrderIdRandomizer.GenerateFor(123456);
Console.WriteLine(obfuscatedId);
Console.WriteLine(OrderIdRandomizer.ReconstructFrom(obfuscatedId));

缺点:如果算法已知,则显然很容易破解。 优点:它是完全自定义的,即不是像MD5这样的既定算法,如果您不知道正在使用什么算法,可能更容易猜测/破解。

答案 4 :(得分:0)

假设创建的订单总数不会接近池中标识符总数的任何值,一种合理有效的方法是简单地生成随机标识符并查看它是否已被使用;继续生成新的标识符,直到找到之前未使用过的标识符。