Отфильтровать «специальные» символы из CRYPT_GEN_RANDOM () - PullRequest
0 голосов
/ 16 февраля 2012
SELECT CRYPT_GEN_RANDOM(4) as SAMPLEDATA

для каждого выбора вышеуказанная функция будет генерировать случайное значение буквенно-цифрового числа, но некоторое время она также генерировала специальные символы, в таком случае как я могу избежать использования специальных символов с помощью хранимой процедуры sql

Ответы [ 2 ]

0 голосов
/ 16 февраля 2012

Занимая немного идеи @ JNK.Предполагая, что вы на самом деле используете только буквенно-цифровые символы, этот регистр не имеет значения, и самая длинная строка, которая вам понадобится, составляет 36 символов, вы можете сначала создать представление:

CREATE VIEW dbo.RetrieveNewID
AS
    SELECT [NewID] = NEWID();
GO

Затем создайте эту функцию:

CREATE FUNCTION dbo.GenerateRandomNumbersLetters
(
    @NumberOfCharacters TINYINT
)
RETURNS VARCHAR(32)
AS
BEGIN
    RETURN 
    (
        SELECT LEFT(REPLACE([NewID], '-', ''), @NumberOfCharacters)
        FROM dbo.RetrieveNewID
    );
END
GO

Мои результаты:

SELECT r = dbo.GenerateRandomNumbersLetters(4);
SELECT r = dbo.GenerateRandomNumbersLetters(4);
SELECT r = dbo.GenerateRandomNumbersLetters(4);

r
----
EA93
9D32
B229

Все будет в порядке, если вы делаете это в режиме «одна-две».Если вы пытаетесь сгенерировать эту функцию для набора, она станет менее эффективной по мере увеличения набора.Пример:

SELECT r = dbo.GenerateRandomNumbersLetters(i) FROM
(
    SELECT i = 1 
    UNION ALL SELECT i = 2 
    UNION ALL SELECT i = 3
) AS x;

Я не ожидаю, что это будет особенно хорошо работать с большим набором данных.


Теперь, если вы хотите использовать символы, которые находятся за пределами наборавозможно в GUID (AZ / 0-9), вы можете сделать это с помощью таблицы.Предполагая то же самое представление выше, мы можем создать таблицу и заполнить ее любыми символами, которые мы хотим быть доступными для генератора случайных чисел (который включает символы вне строго алфавитно-цифровых, но все же может исключить любые «специальные» символы, которые вы не хотитерассмотрим).

CREATE TABLE dbo.RandomCharacters
(
    Digit NVARCHAR(1) COLLATE Latin1_General_CS_AI PRIMARY KEY
);

;WITH x AS 
(
    SELECT TOP (200) i = ROW_NUMBER() OVER (ORDER BY [object_id])
    FROM sys.all_objects
    ORDER BY [object_id]
)
INSERT dbo.RandomCharacters 
SELECT NCHAR(i) FROM x
WHERE (i BETWEEN 65 AND 90)  -- A-Z
   OR (i BETWEEN 97 AND 122) -- a-z
   OR (i BETWEEN 48 AND 57)  -- 0-9
   OR (i IN (42, 126, 181)); -- *, ~, µ

Теперь функция, которая делает магию (опять же, все зависит от уловки, которая позволяет нам ссылаться на NEWID() в функции, скрывая ее в виде):

CREATE FUNCTION dbo.GenerateRandomCharacters
(
    @NumberOfCharacters TINYINT
)
RETURNS NVARCHAR(255)
AS
BEGIN
    RETURN
    (
        SELECT (SELECT x.Digit FROM (
            SELECT TOP (@NumberOfCharacters) r.Digit 
            FROM dbo.RandomCharacters AS r
            CROSS JOIN dbo.RetrieveNewID AS d
            ORDER BY CONVERT(VARBINARY(36), d.[NewID])
        ) AS x
        FOR XML PATH(''), TYPE).value('.[1]','nvarchar(max)')
    );
END
GO

Мои результаты:

SELECT r = dbo.GenerateRandomCharacters(4);
SELECT r = dbo.GenerateRandomCharacters(4);
SELECT r = dbo.GenerateRandomCharacters(4);

r 
----
H~1r
Dfn2
µHxF

В этом последнем решении дубликаты не поддерживаются.Я также не ожидаю, что производительность будет большой на больших наборах данных.Но вы можете иметь более 32 символов.: -)

0 голосов
/ 16 февраля 2012

CRYPT_GEN_RANDOM() генерирует varbinary, который плохо переводится в текст.

Если вы просто хотите получить случайное буквенно-цифровое значение, вы можете использовать что-то вроде GUID, используя NEWID(), чтобы получить тот же эффект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...