0

我从 Raymond Lewallen 的一些存储过程代码开始,用于密码生成器。我想创建一个触发器,每次插入新行(客户)时都会创建一个唯一的 8 个字符 ID。到目前为止我所拥有的:

    CREATE procedure dbo.AllAccessIDgenerator (
     
      @showID varchar(40)
      @accessID varchar(100) OUT
    )
    

    As
    

    Begin
       declare @codeLength int
       declare @characters varchar(100)
    
       declare @count int
       set @characters = ''
       set @codeLength = 8

    -- set A - Z (uppercase)
     
     set @count = 65
     
      while @count <=90
     
       begin
         
         set @characters = @characters + Cast(CHAR(@count) as char(1))
         
         set @count = @count + 1
     
       end
     end

    -- set 0-9
    set @count = 48  
     while @count <=57  
     begin  
      set @characters = @characters + Cast(CHAR(@count) as char(1))  
      set @count = @count + 1  
     end  
     end  
 
    set @count = 0  
    set @accessID = ''  

     while @count <= @codeLength
     
      begin
         
       set @accessID = @accessID + SUBSTRING(@characters,CAST(ABS(CHECKSUM(NEWID()))*RAND(@count) as int)%LEN(@characters)+1,1)
         
       set @count = @count + 1
     
      end
    
     end

    end
    
    GO

我如何 (a) 获取一个存储过程并使其成为 SQL Server 2008 中的触发器,以及 (b) 如果我需要测试唯一性,我该怎么做?

4

3 回答 3

1

老实说,我建议在您的领域层中执行此操作,而不是在数据库中。数据库中的域逻辑会使以后难以维护和部署。当然你可以在数据库中设置约束等来防止无效的外键值等,但是唯一值的生成是一个业务规则,属于你系统的业务规则层(即领域层/逻辑/对象)。

另外,以这种方式产生独特价值的原因是什么?身份列会更适合您的目的吗?您始终可以将标识列用作 8 字符填充值的一部分,这将确保唯一性。

于 2009-04-06T07:52:34.127 回答
1

鉴于您的要求,我会这样做

  1. 创建一个包含两列密码的表。密码和 IsUsed。
  2. 在密码列上创建唯一索引。
  3. 用你需要的尽可能多的项目填满这张表。
  4. 在您的触发器中,获取 IsUsed = 0 的第一个密码。
  5. 设置 IsUsed = 1。

显然,您应该对密码使用某种形式的加密或散列。密码永远不应存储为纯文本。我建议您搜索密码保护方法。

编辑

  1. 如果您需要密码或只是为您的客户提供唯一的 8 个字符 ID,我并不完全清楚。如果您只需要唯一 ID,那么您当然应该忽略此解决方案的加密部分。
  2. 为了填充表,我将在临时表中生成 x 数量的 ID,并选择与该表不同的选择作为插入实际表的源。
于 2009-04-06T07:28:07.087 回答
0

我将添加一些关于为此使用触发器的建议。是的,可以使用触发器来执行此操作。(与 Neil 不同,我认为这应该是数据库问题,因为所有记录都需要唯一性,而不仅仅是通过特定接口添加的记录。从数据完整性的角度来看,将这样的逻辑放在应用程序中是一个坏主意。Ata minumum make确保该文件具有唯一索引。)

但是,大多数缺乏经验的触发器开发人员认为触发器单独作用于每一行,并且不会将触发器设计为处理多行插入。你可能认为没有多行插入;大多数时候你会错的。在某些时候,您将要导入一组客户,触发器必须能够处理此问题。

现在使用您的 proc,它一次只能处理一条记录。这是一个巨大的缺陷,因为在触发器中处理它的唯一方法是使用游标或 while 循环。这非常慢,如果您需要一次添加大量客户,最终可能会锁定您的客户表数小时。

我认为 Lieven 创建一个可能的唯一密码池的想法是一个很好的想法,因为您可以在触发器中使用基于集合的逻辑来填充它。但要使其正常工作,您将需要三列(例如,用于获取接下来的 300 行的标识字段)。如果未使用的密码低于某个百分比,您还应该安排一个夜间作业以生成更多潜在密码。这样一来,事情就永远不会因为您意外地用完潜在的密码而失败。

于 2009-04-06T15:33:35.110 回答