【问题标题】:How to create unique serial number strings in a particular format?如何以特定格式创建唯一的序列号字符串?
【发布时间】:2016-04-25 13:21:55
【问题描述】:

我想用一些序列号填充我的 SQL Server 表以提供给其他人。它们只是有效的 UUID,与人们的电子邮件地址相关。

我可以看到 ColdFusion 提供了CreateUUID 函数,但它生成的 ID 格式为:

xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxx

遵循 8-4-4-16 结构。我只想要一些简单的东西,比如 3-3-3 格式,它对于表中的每一行(即每个客户)都是唯一的。

解决这个问题的最佳方法是什么?我不介意在 SQL 或 ColdFusion 中这样做,但我不确定如何让它们中的任何一个为我自动生成这样的字符串。 SQL Server 具有NEWID() 函数,但它再次生成不是我想要的格式的大字符串。

有什么方法可以强制 SQL 的 NewID() 或 CF 的 CreateUUID 创建 3-3-3 格式的唯一序列吗?

【问题讨论】:

  • (编辑)不确定您是指总共九 (9) 位数字还是相同长度的 uuid,只是格式化为三 (3) 组而不是四或五组。如果是后者,我认为您可以生成 uuid 并调整连字符。不过,我不是 100% 确定的。否则,现有格式是否存在特定问题或问题?虽然您当然可以 DIY,但它需要确保生成的值确实是唯一的——而不仅仅是随机的。这似乎有点像重新发明轮子......
  • 它们将用作优惠券代码,因此它们不能太长。像“XSY-20B-P7O”这样的东西比巨大的默认 UUID 更能满足我的需求。
  • 除非您生成数百万个 ID,否则即使是截断的 UUID 也不太可能发生冲突。原因是在第一组中如何考虑时间戳/时钟。只需去掉 - 并使用前 9 个字符。
  • 如果值不需要是全局唯一的,并且九个字符包含足够的组合,那可能会起作用。只是不要依赖它是不可能的。如果非唯一值会破坏代码,请务必在表中添加unique 约束(并重试代码)。

标签: sql-server coldfusion guid uuid


【解决方案1】:

您可以创建一个随机的 9 个字符的字符串,然后检查它在您的客户/人员表中是否唯一。如果不是 -> 创建一个新的随机字符串并再次检查。 (循环直到它是唯一的)。

我为此创建了 2 个函数,一个生成 9 个字符的随机字符串,另一个使用第一个函数创建一个字符串,然后检查表以查看该字符串是否存在于特定列中。

随机字符串函数:

<cffunction name="makeRandomString" returnType="string" output="false">
    <cfargument name="codeLength" type="numeric" required="no" default="9">

   <cfset var chars = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ">
   <cfset var length = codeLength>
   <cfset var result = "">
   <cfset var i = "">
   <cfset var char = "">

   <cfscript>
   for(i=1; i <= length; i++) {
      char = mid(chars, randRange(1, len(chars)),1);
      result&=char;
   }
   </cfscript>

   <cfreturn result>
</cffunction>

创建随机字符串并确保它在特定表的特定列中唯一的函数:

<cffunction name="createUniqueCode" returnType="string" output="false">

    <cfargument name="tableName" type="string" required="yes">
    <cfargument name="columnName" type="string" required="yes">
    <cfargument name="codeLength" type="numeric" required="no" default="9">

    <cfset ordercode = 0>
    <cfset ordercodecheck = 0>
    <cfloop condition="ordercodecheck eq 0">
        <cfset ordercode = #makeRandomString('#codeLength#')#>
        <cfquery name="findCode" datasource="#application.datasource#">
        select #kolomNaam# from #tableName# where #columnName# = '#ordercode#'
        </cfquery>
        <cfif findCode.recordcount eq 0>
            <cfset ordercodecheck = 1>
        </cfif>
    </cfloop>

    <cfreturn ordercode>

</cffunction>

现在您可以循环 x 次并生成 x 个始终唯一的随机代码。 (下例中的“myColumnName”为包含唯一码的列名)

<cfloop from="1" to="100" index="i">
    <cfset newCode = createUniqueCode(tableName='myTableName',columnName='myColumnName')>

    <!--- insert what to do with new code here (f.e. an insert query) the "newCode" variable holds the new unique code. --->
</cfloop>

希望对你有所帮助。

干杯

【讨论】:

  • 请记住,Web 应用程序是多线程的。在繁忙的应用程序中,由于竞争条件,仍然可能出现重复。更安全的方法是在 db 表上创建一个unique 约束。然后尝试/捕获约束异常并将其用作重试的触发器。另外 a) 不要忘记 var/local 作用域所有函数局部变量 b) 使用 cfqueryparam 和 c) 谨慎使用表/列变量,因为它可能会根据值的来源造成 SQL 注入风险。
  • 我为此创建了 2 个函数, 在发帖borrowed code 时,请务必注明出处,既是对作者的礼貌,也不会被视为剽窃。
  • 没问题,利。自从我使用它多年以来,似乎我忘记了我从哪里得到的那部分。我的回答并不是因为编写一些代码而获得“认可”,只是为了帮助其他程序员。我会尽量记住在未来给予信任。
【解决方案2】:

序列号应该是唯一的。保证您的电子邮件地址的唯一序列号的一种方法是格式化 IDENTITY 列。如果您的电子邮件表还没有 IDENTITY 列,请添加一个。假设它被命名为 Email_ID,那么下面的表达式会给你一个 XXX-XXX-XXX 形式的字符串,它保证对 email 表是唯一的。

SELECT
  STUFF(STUFF(RIGHT('000000000' + CAST(Email_ID AS VARCHAR(9)), 9), 4, 0, '-'), 8, 0, '-')
FROM
  EmailTable

【讨论】:

  • 抱歉,我看不到该代码中的列名Email_ID 在哪里?
  • @volume_one。糟糕,现已修复。
  • 这不是我的想法。我真的需要更随机的东西,比如“SYO-001-AXR”。虽然它没有多大用处,但我也不希望人们轻易地猜测组合会是什么。
【解决方案3】:

你可以使用这样的东西,它会生成你正在寻找的格式:

DECLARE @Value VARCHAR(100)
SELECT @Value = NEWID()
SELECT @Value
SELECT SUBSTRING(@Value,1,3) + '-' + SUBSTRING(@Value,10,3) + '-' + SUBSTRING(@Value,30,3)

【讨论】:

  • 格式确定,但能保证唯一吗?我怀疑不是。
  • @Leigh,你是对的,不能保证这会产生唯一的序列号。
  • 你可以尝试 newsequentialid() 来代替唯一值documentation
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多