3

编辑:它将用作员工唯一编号(必须是随机顺序)

我有一个有列的表

id(auto-increment), uniqueNumber, and some other field

对于每条插入的记录,我想为 uniqueNumber 生成一个 6 位数的唯一编号,

现在我通过触发器得到这个

Create TRIGGER [dbo].[trgUniqueCode] ON [dbo].[testtable]
FOR INSERT
AS
declare @id int;
DECLARE @Upper INT
DECLARE @Lower INT
declare @result int
select @id=i.id from inserted i;
SET @Lower = 100000 
SET @Upper = (select top 1(isnull(UniqueNumber,999999)) from testtable) 
set @result =(ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0))
update testtable set UniqueNumber = @result where ID=@id

我不确定这种方法是否有效,我正在寻找生成(优先时间执行)的最佳方法,或者我将在 C# 中生成唯一编号??

4

8 回答 8

8

生成您尚未分配的所有号码的列表。打乱列表并创建一个包含随机 ID 和递增索引的新表。当你需要一个新的ID时,选择索引最小的那个;将其从未使用的 ID 表中删除,并将其作为您的新 ID 返回。

于 2013-03-11T21:56:39.283 回答
3

您可以使用以下方法从 SQL Server 获取精确的 6 位长随机数:

SELECT CAST((RAND() * (899999) + 100000) as int) 

我使用以下代码使用随机生成的数字更新表中的字段:

第一部分是一个函数,每当向表中插入新行时都会调用该函数。

CREATE VIEW ViewRndNum
AS
SELECT CAST((RAND() * (899999) + 100000) as int);


CREATE FUNCTION [dbo].[GetID](@Counter int = 0)
RETURNS int
AS
BEGIN
    DECLARE @RandNumber as int;
    DECLARE @iEmployeeCode as int;
    DECLARE @iExistingEmployeeCode as int;


    IF (@Counter < 20) 
        BEGIN
        SELECT @iEmployeeCode = RndNum
                    FROM ViewRndNum;


        SELECT @iExistingEmployeeCode = EmployeeCode FROM dbo.Employees WHERE EmployeeCode = @iEmployeeCode
        IF @iExistingEmployeeCode = @iEmployeeCode 
            BEGIN
                SET @Counter = @Counter + 1
                SELECT @iEmployeeCode = [dbo].[GetID](@Counter)
            END
        END
    ELSE
        SET @iEmployeeCode = 99999999
RETURN @iEmployeeCode
END
GO

CREATE TABLE [dbo].[Employees](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [EmployeeType] [int] NULL,
    [EmployeeID] [bigint] NULL,
    [EmployeeCode] [int] NULL,
    [Employee] [varchar](max) NULL,
    [CreatedDate] [datetime] NULL,
    [LastSeen] [datetime] NULL,
 CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

ALTER TABLE [dbo].[Employees] ADD  CONSTRAINT [DF_Employees_EmployeeCode]  DEFAULT ([dbo].[getID]((0))) FOR [EmployeeCode]
GO
于 2013-03-11T21:46:32.820 回答
2

事务处理 SQL:

select floor(rand()*1000000-1)

C#:

Random rnd = new Random();
int rslt = rnd.Next(100000, 999999);

要生成唯一值,您最好的方法是增加一。产生独特价值的其他方式在计算上变得越来越低效。

此外,您可能想要使用散列函数,它们提供“几乎”唯一的值。但那是我不太熟悉的地方。

第三种选择是使用GUIDs 作为唯一标识符。它们在计算上非常有效,并且即使跨越域边界也保证是唯一的。但是,它们大约有 80 个符号,而不仅仅是 6 个 :)

于 2013-03-11T21:43:09.863 回答
2

编辑:糟糕,错过了“必须是随机顺序”的要求。对于那个很抱歉。

对此,我提出了一种完全不同的方法来解决这个问题。我认为您应该推迟“必须是随机的”业务要求。这是为了什么?

根据我的经验,这通常是因为经理不希望出现“鲍勃是在爱丽丝之后被雇用的,爱丽丝的员工 id 是 1987 年所以鲍勃的必须是 1988 年”这样的场景。我对此的回答是“那又怎样?”。知道 Bob 的员工 ID 不应该帮助攻击者 - 如果这样做,那么组织的安全性就会出现更大的问题。

在实施上述出色答案时需要考虑和尝试的事情。

我原来的错误答案:

为什么不使用自动增量字段?

在 SQL Server 中,按如下方式创建列。

create table dbo.Whatever (
    id int not null identity( 100000, 1 ) ,
    …

您还应该创建一个主键约束或一个唯一约束来强制唯一性,以及可能创建一个检查约束来强制下限和上限(分别为 100000 和 999999)。

create table dbo.Whatever (
    id int not null identity( 100000, 1 ) 
        constraint id_u unique 
        constraint id_bounds check ( id between 100000 and 999999 ) ,
    …

这绝对必须是6位数字吗?您可以按照其他地方的建议使用唯一标识符吗?NEWID() 函数意味着您不会遇到尝试同时为多个会话生成唯一编号的序列化问题。

于 2013-03-11T21:48:58.547 回答
1

我在 SQL Server 2012 中使用以下代码创建了一个简单的订单表,其中 ODRID 是自定义格式的销售订单 ID。

CREATE TABLE [dbo].[OrderTransaction](
[OrderID] [bigint] IDENTITY(1,1) NOT NULL,
[ODRID]  AS (right('ES00000000'+CONVERT([nvarchar](10),[OrderID]),(11))),
[OrganisationID] [bigint] NOT NULL,
[SubTotal] [int] NOT NULL,
[Discount] [int] NOT NULL,
[TotalAmount] [bigint] NOT NULL,
[CreatedBy] [int] NULL,
[CreatedDate] [datetime] NULL,
[ModifieddBy] [int] NULL,
[ModifiedDate] [datetime] NULL,
CONSTRAINT [PK_OrderTransaction] PRIMARY KEY CLUSTERED 
(
[OrderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
于 2016-12-29T11:28:12.950 回答
0

C#

Random rand = new Random();
int randomNumber = rand.Next(100000, 999999);

在 SQL 中有点难:

http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/sql-server-set-based-random-numbers

于 2013-03-11T21:44:11.787 回答
0
function random_numbers($digits,$id) {
$min = pow(10, $digits - 1);
$max = pow(10, $digits) - 1;
$number = mt_rand($min, $max);
$count = strlen($id);
$ssn_id = substr($number, $count);
$ssn_id = trim($id.$ssn_id);
return $ssn_id;
}

echo random_numbers(9,145);
于 2014-04-01T07:07:39.117 回答
0

用这个 -

DECLARE @NewPINGenerated Int = CONVERT(numeric(12,0),RAND() * 899999) + 100000
DECLARE @SMS VARCHAR(100)='Message Here '+CAST(@NewPINGenerated as varchar)
于 2018-10-10T10:37:16.390 回答