T-SQL로 임의 문자열 생성


95

T-SQL을 사용하여 의사 난수 영숫자 문자열을 생성하려면 어떻게 하시겠습니까? 달러 기호, 대시 및 슬래시와 같은 문자를 어떻게 제외 하시겠습니까?

답변:


40

특히 테스트를 위해 무작위 데이터를 생성 할 때 데이터를 무작위로 만들지 만 재현 가능하게 만드는 것이 매우 유용합니다. 비결은 랜덤 함수에 명시 적 시드를 사용하여 동일한 시드로 테스트를 다시 실행할 때 정확히 동일한 문자열을 다시 생성하도록하는 것입니다. 다음은 재현 가능한 방식으로 객체 이름을 생성하는 함수의 간단한 예입니다.

alter procedure usp_generateIdentifier
    @minLen int = 1
    , @maxLen int = 256
    , @seed int output
    , @string varchar(8000) output
as
begin
    set nocount on;
    declare @length int;
    declare @alpha varchar(8000)
        , @digit varchar(8000)
        , @specials varchar(8000)
        , @first varchar(8000)
    declare @step bigint = rand(@seed) * 2147483647;

    select @alpha = 'qwertyuiopasdfghjklzxcvbnm'
        , @digit = '1234567890'
        , @specials = '_@# '
    select @first = @alpha + '_@';

    set  @seed = (rand((@seed+@step)%2147483647)*2147483647);

    select @length = @minLen + rand(@seed) * (@maxLen-@minLen)
        , @seed = (rand((@seed+@step)%2147483647)*2147483647);

    declare @dice int;
    select @dice = rand(@seed) * len(@first),
        @seed = (rand((@seed+@step)%2147483647)*2147483647);
    select @string = substring(@first, @dice, 1);

    while 0 < @length 
    begin
        select @dice = rand(@seed) * 100
            , @seed = (rand((@seed+@step)%2147483647)*2147483647);
        if (@dice < 10) -- 10% special chars
        begin
            select @dice = rand(@seed) * len(@specials)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);
            select @string = @string + substring(@specials, @dice, 1);
        end
        else if (@dice < 10+10) -- 10% digits
        begin
            select @dice = rand(@seed) * len(@digit)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);
            select @string = @string + substring(@digit, @dice, 1);
        end
        else -- rest 80% alpha
        begin
            declare @preseed int = @seed;
            select @dice = rand(@seed) * len(@alpha)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);

            select @string = @string + substring(@alpha, @dice, 1);
        end

        select @length = @length - 1;   
    end
end
go

테스트를 실행할 때 호출자는 테스트 실행과 관련된 임의의 시드를 생성 한 다음 (결과 테이블에 저장) 다음과 유사하게 시드를 따라 전달합니다.

declare @seed int;
declare @string varchar(256);

select @seed = 1234; -- saved start seed

exec usp_generateIdentifier 
    @seed = @seed output
    , @string = @string output;
print @string;  
exec usp_generateIdentifier 
    @seed = @seed output
    , @string = @string output;
print @string;  
exec usp_generateIdentifier 
    @seed = @seed output
    , @string = @string output;
print @string;  

2016-02-17 업데이트 : 아래의 설명을 참조하십시오. 원래 절차에는 무작위 시드를 진행하는 방식에 문제가있었습니다. 코드를 업데이트하고 언급 된 개별 문제도 수정했습니다.


내 예에서 다시 시드하는 것은 대부분 요점을 설명하기위한 것입니다. 실제로 호출 시퀀스가 ​​나중에 결정적인 한 세션 당 한 번 RNG를 시드하기에 충분합니다.
Remus Rusanu

2
나는 이것이 오래된 스레드라는 것을 알고 있지만 코드는 시드 192804 및 529126에 대해 동일한 문자열을 반환합니다
davey

1
@RemusRusanu 나는 또한 davey의 의견에 대한 응답에 관심이 있습니다
l --''''''--------- '' '' '' '' '' ''

시드는 공식으로 전진합니다 @seed = rand(@seed+1)*2147483647. 값 529126의 경우 다음 값은 1230039262이고 다음 값은 192804입니다. 그 후에도 시퀀스는 동일하게 계속됩니다. 출력은 첫 번째 문자에 따라 SUBSTRING(..., 0, ...)달라야 하지만 off-by-one 오류 때문이 아닙니다. 인덱스 0에 대해 빈 문자열을 반환하고 529126의 경우 생성 된 첫 번째 문자를 '숨 깁니다'. 수정은 @dice = rand(@seed) * len(@specials)+1인덱스를 1 기반으로 만들기 위해 계산 하는 것입니다.
Remus Rusanu

이 문제는 무작위 시리즈가 공통 값에 도달하면 동일하게 진행된다는 사실에서 발생합니다. 필요한 경우 자체를 무작위로 만들고 초기 시드에서만 결정 +1하여 피할 수 있습니다 rand(@seed+1). 이렇게하면 시리즈가 동일한 값에 도달하더라도 즉시 분기됩니다.
Remus Rusanu

202

GUID 사용

SELECT @randomString = CONVERT(varchar(255), NEWID())

매우 짧은 ...


7
+1, 아주 쉽습니다. RIGHT / SUBSTRING과 결합하여 필요한 길이로 자릅니다.
Johannes Rudolph

2
나는 이것을 좋아합니다-달콤하고 간단합니다. "예측 가능성"기능은 없지만 데이터 생성에 적합합니다.
madhurtanwani

6
UUID가 생성되는 방식으로 인해 고유하거나 무작위가 아니므 로 UUID를 자르기 위해 RIGHT / SUBSTRING을 사용 하지 마십시오 !
ooxi

1
이것은 좋지만 이것을 사용하는 경우 다음을 읽어보십시오. blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx- 참고 GUID는 요점에 관계없이 Microsoft의 UUID 구현입니다. ooxi가 언급했듯이 UUID를 자르는 방법에주의해야합니다.
Clarence Liu

7
NEWID ()의 알파 문자는 16 진수이므로 나머지 알파벳이 아닌 AF 만 얻습니다. 그런 의미에서 제한적입니다.
smoore4

51

첫 번째 예와 유사하지만 더 많은 유연성이 있습니다.

-- min_length = 8, max_length = 12
SET @Length = RAND() * 5 + 8
-- SET @Length = RAND() * (max_length - min_length + 1) + min_length

-- define allowable character explicitly - easy to read this way an easy to 
-- omit easily confused chars like l (ell) and 1 (one) or 0 (zero) and O (oh)
SET @CharPool = 
    'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789.,-_!$@#%^&*'
SET @PoolLength = Len(@CharPool)

SET @LoopCount = 0
SET @RandomString = ''

WHILE (@LoopCount < @Length) BEGIN
    SELECT @RandomString = @RandomString + 
        SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 1)
    SELECT @LoopCount = @LoopCount + 1
END

나는 이것을 더 유연하게 만드는 다른 기능 중 하나를 언급하는 것을 잊었습니다. @CharPool에서 문자 블록을 반복하여 특정 문자에 대한 가중치를 증가시켜 선택 가능성을 높일 수 있습니다.


1
+1 좋은 루틴입니다. 저장 프로 시저의 일부로 사용하고 있습니다.
Marcello Miorelli

2
좋은 솔루션입니다. 불행히도 그것은 udf 내에서 작동하지 않습니다. 어떤 이유로 "함수 내에서 부작용 연산자 'rand'를 잘못 사용했습니다."라는 오류가 발생합니다.
rdans

12
SUBSTRING () 호출에서이 함수에 버그가 있습니다. CONVERT(int, RAND() * @PoolLength) + 1(추가 된 +1 참고) 이어야합니다 . T-SQL의 SUBSTRING은 인덱스 1로 시작하므로이 함수는 때때로 빈 문자열을 추가하고 (인덱스가 0 인 경우) @CharPool.
Dana Cartwright

@Dana Cartwright는 내 요구 사항에 대해 도와 주시겠습니까?. 10 영숫자 또는 12 영숫자 일련 번호와 같은 위의 Charpool을 사용하여 일련 번호의 일정한 길이가 필요한 경우 어떻게 저장 프로 시저를 변경합니까? 프런트 엔드에서는 Charpool을 사용하여 100 또는 200과 같이 생성 할 총 일련 번호를 제공합니다. 일련 번호의 최소 길이는 10에서 최대 14입니다 (매개 변수로도 제공됨)
Prathap Gangireddy

@PrathapGangireddy 한 사람에 대한 의견 질문에 대한 적절한 장소되지 않습니다, 질문을하시기 바랍니다
다나 카트 라이트

31

다음 코드를 사용하여 짧은 문자열을 반환합니다.

SELECT SUBSTRING(CONVERT(varchar(40), NEWID()),0,9)

2
16 진수 문자 만 반환 : 0-9 & AF
jumxozizi

19

SQL Server 2008 이상을 실행하는 경우 새 암호화 함수 crypt_gen_random ()을 사용한 다음 base64 인코딩을 사용하여 문자열로 만들 수 있습니다. 최대 8000 자까지 작동합니다.

declare @BinaryData varbinary(max)
    , @CharacterData varchar(max)
    , @Length int = 2048

set @BinaryData=crypt_gen_random (@Length) 

set @CharacterData=cast('' as xml).value('xs:base64Binary(sql:variable("@BinaryData"))', 'varchar(max)')

print @CharacterData

16

저는 T-SQL 전문가는 아니지만 이미 사용한 가장 간단한 방법은 다음과 같습니다.

select char((rand()*25 + 65))+char((rand()*25 + 65))

이렇게하면 두 개의 문자 (AZ, ascii 65-90)가 생성됩니다.


11
select left(NEWID(),5)

이것은 guid 문자열에서 가장 왼쪽에있는 5 개의 문자를 반환합니다.

Example run
------------
11C89
9DB02

1
이 솔루션은 프로덕션 시스템에 적합하지 않지만 수천 개 정도 후에는 매우 쉽게 중복을 얻을 수 있지만 디버깅 또는 테스트하는 동안 임의의 문자열을 얻는 빠르고 쉬운 방법에는 매우 유용합니다.
Ian1971 2014

이 방법을 사용하여 500 번의 로그인에 대해 임의의 4 자리 비밀번호를 생성했으며이 방법은 완벽하게 작동합니다. 예, 빅 데이터 및 기타 목적의 경우 더 많은 문자를 사용합니다.
Hammad Khan 2014

1
NEWID ()는 안전한 암호에 대해 충분히 무작위로 간주되지 않으므로 요구 사항에 따라주의해야합니다. 5 개의 문자를 사용하면 약 1500 개의 레코드 후에 충돌이 발생합니다. 4 개의 문자를 사용하면 내 테스트에서 55-800 개의 레코드에서 충돌이 발생합니다.
Ian1971 2014

@ Ian1971 임시 암호로, 여전히 괜찮습니다. ATM 카드에 4 자리 핀을 주었다고 가정 해 보겠습니다. 다른 800 번째 사용자에게도 동일한 핀이 발급 될 수 있지만, 귀하의 비밀번호로 그의 카드를 사용할 가능성은 거의 없습니다. 임시 액세스에 괜찮은 거의 임의의 숫자입니다.
Hammad Khan 2014

6

다음은 임의의 영숫자 생성기입니다.

print left(replace(newid(),'-',''),@length) //--@length is the length of random Num.

16 진수 문자 만 반환 : 0-9 & AF
jumxozizi

5

임의의 문자 하나에 대해 다음을 사용할 수 있습니다.

select substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                 (abs(checksum(newid())) % 26)+1, 1)

newid()대 사용의 중요한 차이점은 rand()여러 행을 반환하는 경우 newid()각 행에 대해 별도로 계산되는 반면 rand()전체 쿼리에 대해 한 번 계산 된다는 것 입니다.


4

이것은 나를 위해 일했습니다. ID에 대해 세 개의 임의의 영숫자 문자를 생성해야했지만 최대 15 개 정도의 길이로 작동 할 수 있습니다.

declare @DesiredLength as int = 3;
select substring(replace(newID(),'-',''),cast(RAND()*(31-@DesiredLength) as int),@DesiredLength);

16 진수 문자 만 반환 : 0-9 & AF
jumxozizi

네, 맞아요. > "F"문자를 얻지 못하기 때문에 실제로 "영숫자"가 아닙니다.
브라이언

3

좋은 답변이 많이 있지만 지금까지는 사용자 정의 가능한 문자 풀을 허용하지 않으며 열의 기본값으로 작동합니다. 나는 다음과 같이 할 수 있기를 원했습니다.

alter table MY_TABLE add MY_COLUMN char(20) not null
  default dbo.GenerateToken(crypt_gen_random(20))

그래서 저는 이것을 생각해 냈습니다. 수정하는 경우 하드 코딩 된 숫자 32에주의하십시오.

-- Converts a varbinary of length N into a varchar of length N.
-- Recommend passing in the result of CRYPT_GEN_RANDOM(N).
create function GenerateToken(@randomBytes varbinary(max))
returns varchar(max) as begin

-- Limit to 32 chars to get an even distribution (because 32 divides 256) with easy math.
declare @allowedChars char(32);
set @allowedChars = 'abcdefghijklmnopqrstuvwxyz012345';

declare @oneByte tinyint;
declare @oneChar char(1);
declare @index int;
declare @token varchar(max);

set @index = 0;
set @token = '';

while @index < datalength(@randomBytes)
begin
    -- Get next byte, use it to index into @allowedChars, and append to @token.
    -- Note: substring is 1-based.
    set @index = @index + 1;
    select @oneByte = convert(tinyint, substring(@randomBytes, @index, 1));
    select @oneChar = substring(@allowedChars, 1 + (@oneByte % 32), 1); -- 32 is the number of @allowedChars
    select @token = @token + @oneChar;
end

return @token;

end

2

나는 이것이 좋은 대답이 많은 오래된 질문이라는 것을 알고 있습니다. 그러나 이것을 발견했을 때 나는 Saeid Hasani의 TechNet에 대한 최신 기사도 발견했습니다.

T-SQL : 임의 암호 생성 방법

솔루션은 암호에 초점을 맞추지 만 일반적인 경우에 적용됩니다. Saeid는 솔루션에 도달하기 위해 다양한 고려 사항을 통해 작업합니다. 매우 유익합니다.

기사에 포함 된 모든 코드 블록을 포함하는 스크립트는 TechNet Gallery 를 통해 별도로 제공 되지만 기사부터 시작하겠습니다.


1

내가 개발 한이 절차를 사용하여 입력 변수에 표시 할 수있는 문자를 간단히 지정하고 길이도 정의 할 수 있습니다. 이 형식이 잘되기를 바랍니다. 저는 스택 오버플로가 처음입니다.

IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND object_id = OBJECT_ID(N'GenerateARandomString'))
DROP PROCEDURE GenerateARandomString
GO

CREATE PROCEDURE GenerateARandomString
(
     @DESIREDLENGTH         INTEGER = 100,                  
     @NUMBERS               VARCHAR(50) 
        = '0123456789',     
     @ALPHABET              VARCHAR(100) 
        ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
     @SPECIALS              VARCHAR(50) 
        = '_=+-$£%^&*()"!@~#:', 
     @RANDOMSTRING          VARCHAR(8000)   OUT 

)

AS

BEGIN
    -- Author David Riley
    -- Version 1.0 
    -- You could alter to one big string .e.e numebrs , alpha special etc
    -- added for more felxibility in case I want to extend i.e put logic  in for 3 numbers, 2 pecials 3 numbers etc
    -- for now just randomly pick one of them

    DECLARE @SWAP                   VARCHAR(8000);      -- Will be used as a tempoary buffer 
    DECLARE @SELECTOR               INTEGER = 0;

    DECLARE @CURRENTLENGHT          INTEGER = 0;
    WHILE @CURRENTLENGHT < @DESIREDLENGTH
    BEGIN

        -- Do we want a number, special character or Alphabet Randonly decide?
        SET @SELECTOR  = CAST(ABS(CHECKSUM(NEWID())) % 3 AS INTEGER);   -- Always three 1 number , 2 alphaBET , 3 special;
        IF @SELECTOR = 0
        BEGIN
            SET @SELECTOR = 3
        END;

        -- SET SWAP VARIABLE AS DESIRED
        SELECT @SWAP = CASE WHEN @SELECTOR = 1 THEN @NUMBERS WHEN @SELECTOR = 2 THEN @ALPHABET ELSE @SPECIALS END;

        -- MAKE THE SELECTION
        SET @SELECTOR  = CAST(ABS(CHECKSUM(NEWID())) % LEN(@SWAP) AS INTEGER);
        IF @SELECTOR = 0
        BEGIN
            SET @SELECTOR = LEN(@SWAP)
        END;

        SET @RANDOMSTRING = ISNULL(@RANDOMSTRING,'') + SUBSTRING(@SWAP,@SELECTOR,1);
        SET @CURRENTLENGHT = LEN(@RANDOMSTRING);
    END;

END;

GO

DECLARE @RANDOMSTRING VARCHAR(8000)

EXEC GenerateARandomString @RANDOMSTRING = @RANDOMSTRING OUT

SELECT @RANDOMSTRING

1

때때로 우리는 사랑, 친절, 휴가 등 많은 무작위적인 것들을 필요로합니다. 나는 몇 년 동안 몇 가지 무작위 생성기를 수집했으며, 이것들은 Pinal Dave와 내가 한 번 찾은 stackoverflow 답변입니다. 아래 참조.

--Adapted from Pinal Dave; http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/
SELECT 
    ABS( CAST( NEWID() AS BINARY( 6)) %1000) + 1 AS RandomInt
    , CAST( (ABS( CAST( NEWID() AS BINARY( 6)) %1000) + 1)/7.0123 AS NUMERIC( 15,4)) AS RandomNumeric
    , DATEADD( DAY, -1*(ABS( CAST( NEWID() AS BINARY( 6)) %1000) + 1), GETDATE()) AS RandomDate
    --This line from http://stackoverflow.com/questions/15038311/sql-password-generator-8-characters-upper-and-lower-and-include-a-number
    , CAST((ABS(CHECKSUM(NEWID()))%10) AS VARCHAR(1)) + CHAR(ASCII('a')+(ABS(CHECKSUM(NEWID()))%25)) + CHAR(ASCII('A')+(ABS(CHECKSUM(NEWID()))%25)) + LEFT(NEWID(),5) AS RandomChar
    , ABS(CHECKSUM(NEWID()))%50000+1 AS RandomID

1
편리한 랜덤 생성기 모음을 게시 해 주셔서 감사합니다
iiminov

1

여기에 오늘 생각해 낸 답변이 있습니다 (기존 답변이 마음에 들지 않았기 때문에).

이것은 임의의 문자열의 임시 테이블을 생성하고을 기반으로 newid()하지만 사용자 지정 문자 집합 (0-9 및 AF 이상), 사용자 지정 길이 (최대 255, 제한은 하드 코딩되지만 변경됨) 및 사용자 지정 임의 레코드 수.

다음은 소스 코드입니다 (주석이 도움이되기를 바랍니다).

/**
 * First, we're going to define the random parameters for this
 * snippet. Changing these variables will alter the entire
 * outcome of this script. Try not to break everything.
 *
 * @var {int}       count    The number of random values to generate.
 * @var {int}       length   The length of each random value.
 * @var {char(62)}  charset  The characters that may appear within a random value.
 */

-- Define the parameters
declare @count int = 10
declare @length int = 60
declare @charset char(62) = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'

/**
 * We're going to define our random table to be twice the maximum
 * length (255 * 2 = 510). It's twice because we will be using
 * the newid() method, which produces hex guids. More later.
 */

-- Create the random table
declare @random table (
    value nvarchar(510)
)

/**
 * We'll use two characters from newid() to make one character in
 * the random value. Each newid() provides us 32 hex characters,
 * so we'll have to make multiple calls depending on length.
 */

-- Determine how many "newid()" calls we'll need per random value
declare @iterations int = ceiling(@length * 2 / 32.0)

/**
 * Before we start making multiple calls to "newid", we need to
 * start with an initial value. Since we know that we need at
 * least one call, we will go ahead and satisfy the count.
 */

-- Iterate up to the count
declare @i int = 0 while @i < @count begin set @i = @i + 1

    -- Insert a new set of 32 hex characters for each record, limiting to @length * 2
    insert into @random
        select substring(replace(newid(), '-', ''), 1, @length * 2)

end

-- Now fill the remaining the remaining length using a series of update clauses
set @i = 0 while @i < @iterations begin set @i = @i + 1

    -- Append to the original value, limit @length * 2
    update @random
        set value = substring(value + replace(newid(), '-', ''), 1, @length * 2)

end

/**
 * Now that we have our base random values, we can convert them
 * into the final random values. We'll do this by taking two
 * hex characters, and mapping then to one charset value.
 */

-- Convert the base random values to charset random values
set @i = 0 while @i < @length begin set @i = @i + 1

    /**
     * Explaining what's actually going on here is a bit complex. I'll
     * do my best to break it down step by step. Hopefully you'll be
     * able to follow along. If not, then wise up and come back.
     */

    -- Perform the update
    update @random
        set value =

            /**
             * Everything we're doing here is in a loop. The @i variable marks
             * what character of the final result we're assigning. We will
             * start off by taking everything we've already done first.
             */

            -- Take the part of the string up to the current index
            substring(value, 1, @i - 1) +

            /**
             * Now we're going to convert the two hex values after the index,
             * and convert them to a single charset value. We can do this
             * with a bit of math and conversions, so function away!
             */

            -- Replace the current two hex values with one charset value
            substring(@charset, convert(int, convert(varbinary(1), substring(value, @i, 2), 2)) * (len(@charset) - 1) / 255 + 1, 1) +
    --  (1) -------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------------
    --  (2) ---------------------------------^^^^^^^^^^^^^^^^^^^^^^11111111111111111111111^^^^-------------------------------------
    --  (3) --------------------^^^^^^^^^^^^^2222222222222222222222222222222222222222222222222^------------------------------------
    --  (4) --------------------333333333333333333333333333333333333333333333333333333333333333---^^^^^^^^^^^^^^^^^^^^^^^^^--------
    --  (5) --------------------333333333333333333333333333333333333333333333333333333333333333^^^4444444444444444444444444--------
    --  (6) --------------------5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555^^^^----
    --  (7) ^^^^^^^^^^^^^^^^^^^^66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666^^^^

            /**
             * (1) - Determine the two hex characters that we'll be converting (ex: 0F, AB, 3C, etc.)
             * (2) - Convert those two hex characters to a a proper hexadecimal (ex: 0x0F, 0xAB, 0x3C, etc.)
             * (3) - Convert the hexadecimals to integers (ex: 15, 171, 60)
             * (4) - Determine the conversion ratio between the length of @charset and the range of hexadecimals (255)
             * (5) - Multiply the integer from (3) with the conversion ratio from (4) to get a value between 0 and (len(@charset) - 1)
             * (6) - Add 1 to the offset from (5) to get a value between 1 and len(@charset), since strings start at 1 in SQL
             * (7) - Use the offset from (6) and grab a single character from @subset
             */

            /**
             * All that is left is to add in everything we have left to do.
             * We will eventually process the entire string, but we will
             * take things one step at a time. Round and round we go!
             */

            -- Append everything we have left to do
            substring(value, 2 + @i, len(value))

end

-- Select the results
select value
from @random

저장 프로시 저는 아니지만 하나로 바꾸는 것은 그리 어렵지 않습니다. 또한 끔찍하게 느리지 않습니다 (길이가 60 인 1,000 개의 결과를 생성하는 데 ~ 0.3 초가 걸렸는데, 이는 제가 개인적으로 필요로하는 것보다 더 많은 것입니다). 이것은 제가하고있는 모든 문자열 변이에 대한 저의 초기 관심사 중 하나였습니다.

여기서 중요한 점은 난수 생성기를 직접 만들려고하는 것이 아니라 캐릭터 세트가 제한되지 않는다는 것입니다. 나는 단순히 SQL에있는 임의의 생성기를 사용하고 있습니다 (이 있다는 것을 알고 rand()있지만 테이블 결과에는 좋지 않습니다). 바라건대이 접근법은 여기에서 지나치게 단순한 (즉, 단지 newid())과 지나치게 복잡한 (즉, 사용자 정의 난수 알고리즘) 의 두 가지 답변을 결합하기를 바랍니다 .

또한 짧고 (댓글 제외) 이해하기 쉬우 며 (적어도 저에게는), 이는 항상 제 책에서 플러스입니다.

그러나이 방법은 시드 할 수 없으므로 매번 실제로 무작위가 될 것이며 어떤 신뢰성 수단으로도 동일한 데이터 세트를 복제 할 수 없습니다. OP는 그것을 요구 사항으로 나열하지 않았지만 어떤 사람들은 그런 종류의 것을 찾는다는 것을 알고 있습니다.

나는 내가 여기 파티에 늦었다는 것을 알고 있지만 누군가가 이것이 유용하다고 생각할 것입니다.


0

나는 우연히 이 블로그 게시물 나는 현재 프로젝트에 (이상한 형식 죄송합니다) 사용하고 있음이에 대해 다음 저장 프로 시저 해낸 다음, 첫째 :

CREATE PROCEDURE [dbo].[SpGenerateRandomString]
@sLength tinyint = 10,
@randomString varchar(50) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @counter tinyint
DECLARE @nextChar char(1)
SET @counter = 1
SET @randomString = 

WHILE @counter <= @sLength
BEGIN
SELECT @nextChar = CHAR(48 + CONVERT(INT, (122-48+1)*RAND()))

IF ASCII(@nextChar) not in (58,59,60,61,62,63,64,91,92,93,94,95,96)
BEGIN
SELECT @randomString = @randomString + @nextChar
SET @counter = @counter + 1
END
END
END

0

SQL 2000에서 사용하려는 문자가있는 테이블을 만들고 newid ()로 정렬 된 해당 테이블에서 문자를 선택하는 뷰를 만든 다음 해당 뷰에서 상위 1 개 문자를 선택하여이 작업을 수행했습니다.

CREATE VIEW dbo.vwCodeCharRandom
AS
SELECT TOP 100 PERCENT 
    CodeChar
FROM dbo.tblCharacter
ORDER BY 
    NEWID()

...

SELECT TOP 1 CodeChar FROM dbo.vwCodeCharRandom

그런 다음보기에서 문자를 끌어와 필요에 따라 연결할 수 있습니다.

편집 : 스테판의 반응에 영감을 받아 ...

select top 1 RandomChar from tblRandomCharacters order by newid()

뷰가 필요하지 않습니다 (사실 제가 왜 그렇게했는지 잘 모르겠습니다. 코드는 몇 년 전의 것입니다). 테이블에서 사용할 문자를 계속 지정할 수 있습니다.


0

여기 New Id를 기반으로하는 것이 있습니다.

with list as 
(
    select 1 as id,newid() as val
         union all
    select id + 1,NEWID()
    from    list   
    where   id + 1 < 10
) 
select ID,val from list
option (maxrecursion 0)

16 진수 문자 만 반환 : 0-9 & AF
jumxozizi

0

공유하거나 커뮤니티에 환원하겠다고 생각했습니다. ASCII 기반이며 솔루션은 완벽하지는 않지만 잘 작동합니다. 고란 ​​B.

/* 
-- predictable masking of ascii chars within a given decimal range
-- purpose: 
--    i needed an alternative to hashing alg. or uniqueidentifier functions
--    because i wanted to be able to revert to original char set if possible ("if", the operative word)
-- notes: wrap below in a scalar function if desired (i.e. recommended)
-- by goran biljetina (2014-02-25)
*/

declare 
@length int
,@position int
,@maskedString varchar(500)
,@inpString varchar(500)
,@offsetAsciiUp1 smallint
,@offsetAsciiDown1 smallint
,@ipOffset smallint
,@asciiHiBound smallint
,@asciiLoBound smallint


set @ipOffset=null
set @offsetAsciiUp1=1
set @offsetAsciiDown1=-1
set @asciiHiBound=126 --> up to and NOT including
set @asciiLoBound=31 --> up from and NOT including

SET @inpString = '{"config":"some string value", "boolAttr": true}'
SET @length = LEN(@inpString)

SET @position = 1
SET @maskedString = ''

--> MASK:
---------
WHILE (@position < @length+1) BEGIN
    SELECT @maskedString = @maskedString + 
    ISNULL(
        CASE 
        WHEN ASCII(SUBSTRING(@inpString,@position,1))>@asciiLoBound AND ASCII(SUBSTRING(@inpString,@position,1))<@asciiHiBound
         THEN
            CHAR(ASCII(SUBSTRING(@inpString,@position,1))+
            (case when @ipOffset is null then
            case when ASCII(SUBSTRING(@inpString,@position,1))%2=0 then @offsetAsciiUp1 else @offsetAsciiDown1 end
            else @ipOffset end))
        WHEN ASCII(SUBSTRING(@inpString,@position,1))<=@asciiLoBound
         THEN '('+CONVERT(varchar,ASCII(SUBSTRING(@Inpstring,@position,1))+1000)+')' --> wrap for decode
        WHEN ASCII(SUBSTRING(@inpString,@position,1))>=@asciiHiBound
         THEN '('+CONVERT(varchar,ASCII(SUBSTRING(@inpString,@position,1))+1000)+')' --> wrap for decode
        END
        ,'')
    SELECT @position = @position + 1
END

select @MaskedString


SET @inpString = @maskedString
SET @length = LEN(@inpString)

SET @position = 1
SET @maskedString = ''

--> UNMASK (Limited to within ascii lo-hi bound):
-------------------------------------------------
WHILE (@position < @length+1) BEGIN
    SELECT @maskedString = @maskedString + 
    ISNULL(
        CASE 
        WHEN ASCII(SUBSTRING(@inpString,@position,1))>@asciiLoBound AND ASCII(SUBSTRING(@inpString,@position,1))<@asciiHiBound
         THEN
            CHAR(ASCII(SUBSTRING(@inpString,@position,1))+
            (case when @ipOffset is null then
            case when ASCII(SUBSTRING(@inpString,@position,1))%2=1 then @offsetAsciiDown1 else @offsetAsciiUp1 end
            else @ipOffset*(-1) end))
        ELSE ''
        END
        ,'')
    SELECT @position = @position + 1
END

select @maskedString

나는 내 솔루션이 임의의 문자 생성이 아니라 예측 가능한 문자열 난독 화라는 것을 알고 있습니다 ... :)
Goran B.

0

이것은 다른 답변 중 하나와 같은 시드와 함께 rand를 사용하지만 모든 호출에 시드를 제공 할 필요는 없습니다. 첫 번째 호출에서 제공하는 것으로 충분합니다.

이것은 내 수정 된 코드입니다.

IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND object_id = OBJECT_ID(N'usp_generateIdentifier'))
DROP PROCEDURE usp_generateIdentifier
GO

create procedure usp_generateIdentifier
    @minLen int = 1
    , @maxLen int = 256
    , @seed int output
    , @string varchar(8000) output
as
begin
    set nocount on;
    declare @length int;
    declare @alpha varchar(8000)
        , @digit varchar(8000)
        , @specials varchar(8000)
        , @first varchar(8000)

    select @alpha = 'qwertyuiopasdfghjklzxcvbnm'
        , @digit = '1234567890'
        , @specials = '_@#$&'
    select @first = @alpha + '_@';

    -- Establish our rand seed and store a new seed for next time
    set  @seed = (rand(@seed)*2147483647);

    select @length = @minLen + rand() * (@maxLen-@minLen);
    --print @length

    declare @dice int;
    select @dice = rand() * len(@first);
    select @string = substring(@first, @dice, 1);

    while 0 < @length 
    begin
        select @dice = rand() * 100;
        if (@dice < 10) -- 10% special chars
        begin
            select @dice = rand() * len(@specials)+1;
            select @string = @string + substring(@specials, @dice, 1);
        end
        else if (@dice < 10+10) -- 10% digits
        begin
            select @dice = rand() * len(@digit)+1;
            select @string = @string + substring(@digit, @dice, 1);
        end
        else -- rest 80% alpha
        begin
            select @dice = rand() * len(@alpha)+1;

            select @string = @string + substring(@alpha, @dice, 1);
        end

        select @length = @length - 1;   
    end
end
go

0

SQL Server 2012+ 에서는 일부 (G) UID의 바이너리를 연결 한 다음 결과에 대해 base64 변환을 수행 할 수 있습니다.

SELECT 
    textLen.textLen
,   left((
        select  CAST(newid() as varbinary(max)) + CAST(newid() as varbinary(max)) 
        where   textLen.textLen is not null /*force evaluation for each outer query row*/ 
        FOR XML PATH(''), BINARY BASE64
    ),textLen.textLen)   as  randomText
FROM ( values (2),(4),(48) ) as textLen(textLen)    --define lengths here
;

더 긴 문자열이 필요하거나 =결과에 문자가 표시 + CAST(newid() as varbinary(max))되는 경우 하위 선택에 더 추가해야합니다 .


0

그래서 저는 위의 많은 답변을 좋아했지만 본질적으로 조금 더 무작위적인 것을 찾고있었습니다. 또한 제외 된 문자를 명시 적으로 호출하는 방법을 원했습니다. 아래는 CRYPT_GEN_RANDOM암호화 난수를 얻기 위해 를 호출하는보기를 사용하는 내 솔루션 입니다. 내 예에서는 8 바이트 인 난수 만 선택했습니다. 이 크기를 늘리고 원하는 경우 함수의 시드 매개 변수를 활용할 수도 있습니다. 다음은 설명서 링크입니다. https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sql

CREATE VIEW [dbo].[VW_CRYPT_GEN_RANDOM_8]
AS
SELECT CRYPT_GEN_RANDOM(8) as [value];

뷰를 생성하는 이유 CRYPT_GEN_RANDOM는 함수에서 직접 호출 할 수 없기 때문 입니다.

거기서부터 길이를 받아들이는 스칼라 함수와 제외 된 문자의 쉼표로 구분 된 문자열을 포함 할 수있는 문자열 매개 변수를 만들었습니다.

CREATE FUNCTION [dbo].[fn_GenerateRandomString]
( 
    @length INT,
    @excludedCharacters VARCHAR(200) --Comma delimited string of excluded characters
)
RETURNS VARCHAR(Max)
BEGIN
    DECLARE @returnValue VARCHAR(Max) = ''
        , @asciiValue INT
        , @currentCharacter CHAR;

    --Optional concept, you can add default excluded characters
    SET @excludedCharacters = CONCAT(@excludedCharacters,',^,*,(,),-,_,=,+,[,{,],},\,|,;,:,'',",<,.,>,/,`,~');

    --Table of excluded characters
    DECLARE @excludedCharactersTable table([asciiValue] INT);

    --Insert comma
    INSERT INTO @excludedCharactersTable SELECT 44;

    --Stores the ascii value of the excluded characters in the table
    INSERT INTO @excludedCharactersTable
    SELECT ASCII(TRIM(value))
    FROM STRING_SPLIT(@excludedCharacters, ',')
    WHERE LEN(TRIM(value)) = 1;

    --Keep looping until the return string is filled
    WHILE(LEN(@returnValue) < @length)
    BEGIN
        --Get a truly random integer values from 33-126
        SET @asciiValue = (SELECT TOP 1 (ABS(CONVERT(INT, [value])) % 94) + 33 FROM [dbo].[VW_CRYPT_GEN_RANDOM_8]);

        --If the random integer value is not in the excluded characters table then append to the return string
        IF(NOT EXISTS(SELECT * 
                        FROM @excludedCharactersTable 
                        WHERE [asciiValue] = @asciiValue))
        BEGIN
            SET @returnValue = @returnValue + CHAR(@asciiValue);
        END
    END

    RETURN(@returnValue);
END

다음은 함수를 호출하는 방법의 예입니다.

SELECT [dbo].[fn_GenerateRandomString](8,'!,@,#,$,%,&,?');

~ 건배


0

그것은 매우 간단합니다. 그것을 사용하고 즐기십시오.

CREATE VIEW [dbo].[vwGetNewId]
AS
SELECT        NEWID() AS Id

Creat FUNCTION [dbo].[fnGenerateRandomString](@length INT = 8)
RETURNS NVARCHAR(MAX)
AS
BEGIN

DECLARE @result CHAR(2000);

DECLARE @String VARCHAR(2000);

SET @String = 'abcdefghijklmnopqrstuvwxyz' + --lower letters
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + --upper letters
'1234567890'; --number characters

SELECT @result =
(
    SELECT TOP (@length)
           SUBSTRING(@String, 1 + number, 1) AS [text()]
    FROM master..spt_values
    WHERE number < DATALENGTH(@String)
          AND type = 'P'
    ORDER BY
(
    SELECT TOP 1 Id FROM dbo.vwGetNewId
)   --instead of using newid()
    FOR XML PATH('')
);

RETURN @result;

END;

0

이렇게하면 Base64 범위 (위, 아래, 숫자, + 및 /)에서 96 자 길이의 문자열이 생성됩니다. 3 개의 "NEWID ()"를 추가하면 Base64 패딩 (=)없이 길이가 32만큼 늘어납니다.

    SELECT 
        CAST(
            CONVERT(NVARCHAR(MAX),
                CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
            ,2) 
        AS XML).value('xs:base64Binary(xs:hexBinary(.))', 'VARCHAR(MAX)') AS StringValue

이것을 세트에 적용하는 경우 해당 세트에서 무언가를 도입하여 NEWID ()가 다시 계산되도록하십시오. 그렇지 않으면 매번 동일한 값을 얻게됩니다.

  SELECT 
    U.UserName
    , LEFT(PseudoRandom.StringValue, LEN(U.Pwd)) AS FauxPwd
  FROM Users U
    CROSS APPLY (
        SELECT 
            CAST(
                CONVERT(NVARCHAR(MAX),
                    CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), U.UserID)  -- Causes a recomute of all NEWID() calls
                ,2) 
            AS XML).value('xs:base64Binary(xs:hexBinary(.))', 'VARCHAR(MAX)') AS StringValue
    ) PseudoRandom

0

SQL Server 2016 이상에서 주어진 바이트 길이의 암호화 무작위 문자열을 생성하는 매우 간단하고 상대적으로 효율적인 표현식은 다음과 같습니다.

--Generates 36 bytes (48 characters) of base64 encoded random data
select r from OpenJson((select Crypt_Gen_Random(36) r for json path)) 
  with (r varchar(max))

바이트 길이는 인코딩 된 크기와 동일하지 않습니다. 기사 의 다음을 사용하여 변환하십시오.

Bytes = 3 * (LengthInCharacters / 4) - Padding

0

이 기사의 다양한 유용한 답변을 바탕으로 내가 좋아하는 몇 가지 옵션의 조합을 얻었습니다.

DECLARE @UserId BIGINT = 12345 -- a uniqueId in my system
SELECT LOWER(REPLACE(NEWID(),'-','')) + CONVERT(VARCHAR, @UserId)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.