• _simon_ (2/1/2013)


    This is my scalar function, which returns numbers between @min-2 and @max-2 (both included):

    create function GetRandom(@min int, @max-2 int)

    returns int

    as

    begin

    declare @diff int = @max-2 - @min-2 + 1

    return @min-2 + crypt_gen_random(1) % @diff

    end

    This is how I test it:

    -- This runs for about 50s on my computer.

    declare @t table (Number int)

    declare @winners table (Number int)

    declare @i int = 0

    declare @iCount int = 10

    declare @j-2 int = 0

    declare @jCount int = 100000

    while (@i < @iCount)

    begin

    delete from @t

    set @j-2 = 0

    while (@j < @jCount)

    begin

    insert into @t (Number)

    select dbo.GetRandom(1, 3)

    set @j-2 += 1

    end

    insert into @winners (Number)

    select top 1 Number

    from (

    select Number, count(*) C

    from @t

    group by Number

    ) x

    order by C desc

    set @i += 1

    end

    select Number, count(*)

    from @winners

    group by Number

    order by count(*) desc

    Output (number 1 wins in ~80% cases):

    Number

    ----------- -----------

    1 9

    2 1

    Now almost every time I run this query, the Number 1 appears slightly more often... Is there something wrong with my GetRandom function?

    Which edition and version of SQL Server are you actually using. I'm using 2k8 and I get the following error when I try to create your function...

    Msg 443, Level 16, State 1, Procedure GetRandom, Line 6

    Invalid use of a side-effecting operator 'Crypt_Gen_Random' within a function.

    You're implitly converting a VARBINARY(1) to a 4 byte int and at the machine language level, that makes a mess. If you don't think so, change the crypt_gen_random(1) to crypt_gen_random(4) and see the "impossible" happen with the output of your test.

    You can fix the problem by changing the crypt_gen_random(1) to ABS(CHECKSUM(CRYPT_GEN_RANDOM(4))).

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)