首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >生成用户友好的字母数字id (如企业id、SKU)的选项有哪些?

生成用户友好的字母数字id (如企业id、SKU)的选项有哪些?
EN

Stack Overflow用户
提问于 2008-10-20 00:56:33
回答 5查看 4.8K关注 0票数 16

以下是要求:

必须是字母数字,8-10个字符,以便它是用户友好的。这些将作为唯一键存储在数据库中。我使用Guids作为主键,因此选择使用GUids来生成这些唯一的Ids会更好。

我正在考虑一个基数为n的转换器,它接受Guid并将其转换为8个字符的唯一字符串。

短,轻量级的算法是首选的,因为它将经常被调用。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-10-20 01:10:31

您可以考虑base 36.,因为它可以处理字母和数字。考虑从集合中删除I(眼睛)和O (Oh),这样它们就不会与1(1)和0(0)混淆。有些人可能还会抱怨2和Z。

票数 8
EN

Stack Overflow用户

发布于 2008-10-20 21:26:28

代码语言:javascript
运行
复制
8 characters - perfectly random - 36^8 = 2,821,109,907,456 combinations
10 characters - perfectly random - 36^10 = 3,656,158,440,062,976 combinations
GUID's - statistically unique* - 2^128 = 340,000,000,000,000,000,000,000,000,000,000,000,000 combinations

* Is a GUID unique 100% of the time? [stackoverflow]

您的GUID ->字符转换的问题;虽然您的GUID在统计上是唯一的,但通过采用任何子集,您可以减少随机性并增加冲突的机会。你当然不会想要创建非唯一的SKU。

解决方案1:

使用与对象和业务规则相关的数据创建SKU。

即,可能存在使对象唯一的属性的小组合( (a natural key) )。组合自然密钥的元素,对它们进行编码和压缩,以创建SKU。通常,您只需要一个日期-时间字段(即CreationDate)和一些其他属性来实现这一点。你可能会在sku的创建中有很多漏洞,但是sku更适合你的用户。

假设:

代码语言:javascript
运行
复制
Wholesaler, product name, product version, sku
Amazon,     IPod Nano,    2.2,             AMIPDNN22
BestBuy,    Vaio,         3.2,             BEVAIO32

解决方案2:

一种方法,它保留一个数字范围,然后按顺序释放它们,并且永远不会两次返回相同的数字。你仍然可以在范围内得到空洞。虽然你可能不需要生成足够的sku,但要确保你的需求允许这样做。

一种实现是在数据库中有一个具有计数器的key表。计数器在事务中递增。重要的一点是,软件中的方法不是递增1,而是抓取一个块。伪c#代码如下所示。

代码语言:javascript
运行
复制
-- what the key table may look like
CREATE TABLE Keys(Name VARCHAR(10) primary key, NextID INT)
INSERT INTO Keys Values('sku',1)

// some elements of the class
public static SkuKeyGenerator 
{
    private static syncObject = new object();
    private static int nextID = 0;
    private static int maxID = 0;
    private const int amountToReserve = 100;

    public static int NextKey()
    {
        lock( syncObject )
        {
            if( nextID == maxID )
            {
                ReserveIds();
            }
            return nextID++;
        }
    }
    private static void ReserveIds()
    {
        // pseudocode - in reality I'd do this with a stored procedure inside a transaction,
        // We reserve some predefined number of keys from Keys where Name = 'sku'
        // need to run the select and update in the same transaction because this isn't the only
        // method that can use this table.
        using( Transaction trans = new Transaction() ) // pseudocode.
        {
             int currentTableValue = db.Execute(trans, "SELECT NextID FROM Keys WHERE Name = 'sku'");
             int newMaxID = currentTableValue + amountToReserve;
             db.Execute(trans, "UPDATE Keys SET NextID = @1 WHERE Name = 'sku'", newMaxID);

             trans.Commit();

             nextID = currentTableValue;
             maxID = newMaxID;
        }
    } 

这里的想法是预留足够的键,这样代码就不会经常访问数据库,因为获取键范围是一项开销很大的操作。您需要很好地了解需要保留的密钥数量,以平衡密钥丢失(应用程序重启)和过快耗尽密钥并返回数据库。这个简单的实现无法重用丢失的键。

因为此实现依赖于数据库和事务,所以您可以让应用程序并发运行,并且所有应用程序都生成惟一的键,而无需经常访问数据库。

注意上面是基于Patterns of Enterprise Application Architecture (Fowler)第222页的key table的。该方法通常用于在不需要数据库标识列的情况下生成主键,但您可以看到如何根据您的目的对其进行调整。

票数 10
EN

Stack Overflow用户

发布于 2008-10-20 01:12:20

如果你正在寻找“用户友好的”,你可能想试着使用完整的单词,而不是简单地将其缩短/字母数字,因此,类似于:

代码语言:javascript
运行
复制
words = [s.strip().lower() for s in open('/usr/share/dict/canadian-english') if "'" not in s]
mod = len(words)

def main(script, guid):
    guid = hash(guid)

    print "+".join(words[(guid ** e) % mod] for e in (53, 61, 71))

if __name__ == "__main__":
    import sys
    main(*sys.argv)

它会产生类似如下的输出:

代码语言:javascript
运行
复制
oranjestad+compressing+wellspring
padlock+discommoded+blazons
pt+olenek+renews

这很有趣。否则,简单地获取guid的前8-10个字符或guid的sha1/md5散列可能是最好的选择。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/217253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档