如何在表中创建一个返回随机数的存储过程

时间:2012-11-26 12:18:49

标签: asp.net sql-server sql-server-2008 stored-procedures

我想创建一个返回(11111,99999)

之间的随机数的存储过程

如果表中不存在数字

我使用这个复杂的函数来做,但我需要将其转换为存储过程

    Function GiveRandomStudentNumber() As String
s:
        Dim rnd As New Random
        Dim st_num As String = rnd.Next(11111, 99999)
        Dim cmd As New SqlCommand("select count(0) from student where st_num = " & st_num,con)
        dd.con.Open()
        Dim count As Integer = cmd.ExecuteScalar()
        dd.con.Close()
        If count <> 0 Then
            GoTo s
        Else
            Return st_num
        End If
    End Function

此函数可以正常工作,但我需要将其转换为存储过程..

提前致谢...

2 个答案:

答案 0 :(得分:2)

CREATE PROCEDURE [dbo].[Select_RandomNumber] 
(
@Lower INT, --11111-- The lowest random number
@Upper INT --99999-- The highest random number
)
AS
BEGIN

    IF NOT (@Lower < @Upper) RETURN -1

    --TODO: If all the numbers between Lower and Upper are in the table,
    --you should return from here
    --RETURN -2

    DECLARE @Random INT;
    SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)

    WHILE  EXISTS (SELECT * FROM YourTable WHERE randCol = @Random)
    BEGIN

        SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
    END

    SELECT @Random
END

答案 1 :(得分:0)

创建学生ID表。用X和Y之间的ID填写。每次要使用ID时,将其从表中删除。

create table [FreeIDs] (
  [ID] int, 
  [order] uniqueidentifier not null default newid() primary key);
insert into [FreeIDs] ([ID]) values (11111),(11112),...,(99999);

to get a free ID:

    with cte as (
      select top(1) [ID]
      from [FreeIDs] 
      order by [order])
    delete cte
    output deleted.ID;

持久的预定义订单可加快生成新ID。

顺便说一句,如果你想要“优化”表格,那就去数字表:

with Digits as (
    select Digit 
    from (
        values (0), (1), (2), (3), (4), (5), 
            (6), (7), (8), (9)) as t(Digit)),
Numbers as (
    select u.Digit + t.Digit*10 +h.Digit*100 + m.Digit*1000+tm.Digit*10000 as Number
    from Digits u
    cross join Digits t
    cross join Digits h
    cross join Digits m
    cross join Digits tm)
select top(1) Number 
from Numbers
where Number between 11111 and 99999
and Number not in (
    select ID 
    from Students)
order by (newid());

就是不要。随机化集合的要求是性能杀手,并且消除现有(使用过的)ID的连接也是有问题的。但最重要的是,解决方案在并发下失败,因为多个请求可以获得相同的ID(并且随着空闲ID数量的减少而增加)。当然,与原始代码或Kaf的答案一样,语义等效的天真逐行的慢行处理具有完全相同的问题,但也很简单。当除了其中一个ID之外的其他所有ID都值得测试解决方案时,在等待随机数生成器达到累积奖金时观察灯光昏暗......