Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
Нужна генерация строки вида:
А3Р2-Ю9С0-Л5К5-Ф1П2
То есть
[А...Я][0-9][А...Я][0-9]-[А...Я][0-9][А...Я][0-9]-[А...Я][0-9][А...Я][0-9]
Я не знаю, стоит ли пытаться это делать средствами SQL через хранимую процедуру, поэтому первое что пришло в голову это
подключить готовое решение на c++.

Что посоветуете?


PS Microsoft SQL Server 2012 X64 Express
18 авг 16, 20:32    [19560218]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
Точнее готовое решение это сферический конь в вакуме. Готового решение нет, но я могу написать на C# или C++ генератор.
Думаю на sql тоже могу написать с помощью NEWID() или rand, checksum и так далее
18 авг 16, 20:37    [19560239]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37254
Смотря сколько данных надо генерировать. Если мало, можно обычным rand() в функции наляпать, если нужна производительность, то лучше в clr, скорее всего быстрее скалярки окажется.

Сообщение было отредактировано: 18 авг 16, 21:11
18 авг 16, 21:11    [19560411]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6802
Kimel,

RAND 16 цифр и взять их из строки букв там где надо... думаю время это не заёмёт
18 авг 16, 21:15    [19560421]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
 with a as
 (
  select
   'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЭЮЯ' as c,
   '0123456789' as d
 ),
 b as
 (
  select
   substring(c, cast(rand(checksum(newid())) * 33 + 1 as int), 1) +
   substring(d, cast(rand(checksum(newid())) * 10 + 1 as int), 1) +
   substring(c, cast(rand(checksum(newid())) * 33 + 1 as int), 1) +
   substring(d, cast(rand(checksum(newid())) * 10 + 1 as int), 1) as s
  from
   a
 ),
 c as
 (
  select
   t1.s + '-' + t2.s + '-' + t3.s + '-' + t4.s as identifier
  from
   b t1 cross join
   b t2 cross join
   b t3 cross join
   b t4
 )
 select identifier from c;
18 авг 16, 21:53    [19560541]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
invm,

Сначала удивился такому простому решению. Потом пощёлкал и получил
0Щ9-Г3Ш2-П3Д0-Я1С3
то есть иногда вместо чётырёх 3 . Можете не утруждать себя, я уже почти написал 100% рабочий вариант, выложу сюда его потом.
18 авг 16, 23:11    [19560890]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
iljy
Member

Откуда:
Сообщений: 8711
Kimel,

а если не просто щелкать, а подумать, как работает округление в плавающей арифметике, простейшее исправление дает полностью рабочий простой вариант.

 with a as
 (
  select
   'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЭЮЯ' as c,
   '0123456789' as d
 ),
 b as
 (
  select
   substring(c, cast(floor(rand(checksum(newid())) * 33) as int) + 1, 1) +
   substring(d, cast(floor(rand(checksum(newid())) * 10) as int) + 1, 1) +
   substring(c, cast(floor(rand(checksum(newid())) * 33) as int) + 1, 1) +
   substring(d, cast(floor(rand(checksum(newid())) * 10) as int) + 1, 1) as s
  from
   a
 ),
 c as
 (
  select
   t1.s + '-' + t2.s + '-' + t3.s + '-' + t4.s as identifier
  from
   b t1 cross join
   b t2 cross join
   b t3 cross join
   b t4
 )
 select identifier from master..spt_values cross apply c 
 --where LEN(identifier) != 19;
18 авг 16, 23:31    [19560966]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
iljy,


Спасибо.

Я тоже уже дописал свой говнокод
+
DECLARE @rand_string varchar(max),@rand_number varchar(max), @i int
set @i = 1
set @rand_string = ''
set @rand_number = ''

-- создаём в 2 раза больше цифр чем символов в требуемой строке
WHILE (LEN(@rand_string) < 16) 
BEGIN
set @rand_string += (SELECT CONVERT(varchar(max),ROUND(RAND(CHECKSUM(NEWID())) * 1000000.0, 0)))
END

-- создаём 10 случайных цифр
WHILE (LEN(@rand_number) < 10) 
BEGIN
set @rand_number += (SELECT CONVERT(varchar(max),ROUND(RAND(CHECKSUM(NEWID())) * 1000000.0, 0)))
END

-- создаём строку случайных символов
DECLARE @alphabet varchar(30), @nubmers varchar(10)
SET @alphabet = ('ААЯЯУУООЮЮБВГДЕЖЖЗИИКЛМНСФЦЧШЫ') -- 30 букв

declare @final_random_string varchar(max), @temp_string int
set @final_random_string = ''
set @temp_string = 0
set @i = 1
WHILE (LEN(@final_random_string) < 8)
BEGIN

	SET @temp_string = CONVERT(int,SUBSTRING(@rand_string, @i, 2))
	SET @final_random_string +=  
	 CASE 
			WHEN @temp_string < 30
			THEN (select SUBSTRING(@alphabet, @temp_string, 1))
			WHEN @temp_string >= 30 and @temp_string < 60
			THEN (select SUBSTRING(@alphabet, @temp_string-30, 1))
			WHEN @temp_string >= 60 and @temp_string < 90
			THEN (select SUBSTRING(@alphabet, @temp_string-60, 1))
			WHEN @temp_string >= 90 and @temp_string < 100
			THEN (select SUBSTRING(@alphabet, @temp_string-90, 1))
		END		

	SET @i += 2
END 


--создаём конечный вариант ID

SET @final_random_string = SUBSTRING(@final_random_string,1,8)
SET @rand_number = SUBSTRING(@rand_number,1,8) 
DECLARE @finalID varchar(24) 
set @finalID = ''
set @i = 1
WHILE (@i <= 8)
BEGIN
	set @finalID +=
		case 
			when  @i = 3 or @i = 5 or @i = 7
			then '-'
			else ''
		end
	set @finalID += (select SUBSTRING(@final_random_string, @i, 1))
	set @finalID += (select SUBSTRING(@rand_number, @i, 1))
	set @i += 1

END

select @finalID

который работает конечно же не так шустро, но я в нём на 100% уверен, что он не выдаст мне какую-то ошибку округления или ещё что-то в этом роде.
Я просто пошёл путём быдлокодера
сначала всё что нужно сгенерировал, а потом распарсил. Такие вот дела. Мб на с++ это бы работало бы быстрее чем на SQL всётаки sql не для процедурного быдлокода.

Я изучу ваш вариант, попробую разобраться как работает и мб буду именно его юзать, потому что он более православный.
19 авг 16, 00:13    [19561073]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
iljy,

я заметил что опять выдаёт вроде этого
1Щ2-Ё44-Ъ4П5-Ё2З3
Щ1Е9-З7Ч3-Ю59-Ь3Ё4

то есть пропускает букву
19 авг 16, 00:25    [19561098]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
iljy,

я его подправил, теперь норм
вот как надо
 with a as
 (
  select
   'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЭЮЯ' as c,
   '0123456789' as d
 ),
 b as
 (
  select
   substring(c, cast(floor(rand(checksum(newid())) * 32) as int) + 1, 1) +
   substring(d, cast(floor(rand(checksum(newid())) * 10) as int) + 1, 1) +
   substring(c, cast(floor(rand(checksum(newid())) * 32) as int) + 1, 1) +
   substring(d, cast(floor(rand(checksum(newid())) * 10) as int) + 1, 1) as s
  from
   a
 ),
 c as
 (
  select
   t1.s + '-' + t2.s + '-' + t3.s + '-' + t4.s as identifier
  from
   b t1 cross join
   b t2 cross join
   b t3 cross join
   b t4
 )
 select identifier from master..spt_values cross apply c 
19 авг 16, 00:27    [19561103]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
iljy
Member

Откуда:
Сообщений: 8711
Kimel,

ха, ну конечно, там буква Ы пропущена, так что да, на 32 надо умножать. ну или букву добавить.
19 авг 16, 01:45    [19561206]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
Считайте это рекламой мопеда :)
19 авг 16, 23:00    [19566193]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
andrey odegov,

в чём принципиальное различие?
можно ведь и так
 substring(c, cast(floor(rand(checksum(newid())) * LEN(c)) as int) + 1, 1) 


есть какая-то разница?
19 авг 16, 23:07    [19566248]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
andrey odegov,

спасибо за ваше решение.
Оно лучше и я понял только сейчас почему.
Так как этот скрипт я бы хотел использовать в функции, да не в табличной, а в скалярной, то отсутствие rand упрощает задачу.
25 авг 16, 09:56    [19587739]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Вот так прикольнее. С "Ы"

declare
    @s varchar(43)='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ0123456789'
  , @r varbinary(20)=hashbytes('sha1', cast(newid() as varchar(36)))
  , @v varchar(19);
with 
r as (select 1 d union all select d+1 from r where d<16)
select @v = (
select ''+s
from r
outer apply (select d*10, substring(@s, cast(substring(@r, d, 1) as tinyint)%43+1, 1)
             union all   
             select d*10+1, '-' where d%4=0 and d<16
             ) f(f, s)
order by f
for xml path('')
);
select @v;
5 сен 16, 18:06    [19630130]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Тот же вариант, в более красивом виде
select
(
select s
from (select hashbytes('sha1', cast(newid() as varchar(36)))) v(v)
cross join  (values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16)) r(d)
outer apply (select d*2, choose(cast(substring(v, d, 1) as tinyint)%43+1, 'А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ь','Ы','Ъ','Э','Ю','Я','0','1','2','3','4','5','6','7','8','9')
             union all   
             select d*2+1, '-' where d%4=0 and d<16
             ) f(f, s)
order by f
for xml path(''), type
).value('.','varchar(19)');

Топикстартеру искренее спасибо за то, что дал возможность размяться мозгу
5 сен 16, 20:12    [19630505]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Только сейчас понял, что буквы с цифрами надо чередовать. Ну, можно тем же путем, с той же идеей.
5 сен 16, 20:16    [19630515]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Тогда вот, с чередованием цифр и букв

select
(
select s
from (select hashbytes('sha1', cast(newid() as varchar(36)))) v(v)
cross join  (values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16)) r(d)
outer apply (select d*2, 
                     case when d%2=1 
					        then choose(cast(substring(v, d, 1) as tinyint)%33+1, 'А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ь','Ы','Ъ','Э','Ю','Я')
					        else choose(cast(substring(v, d, 1) as tinyint)%10+1, '0','1','2','3','4','5','6','7','8','9')
                     end
             union all   
             select d*2+1, '-' where d%4=0 and d<16
             ) f(f, s)
order by f
for xml path(''), type
).value('.','varchar(19)');
5 сен 16, 20:23    [19630532]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Ну и на финал

select cast(
(
select s+''
from (select hashbytes('sha1', cast(newid() as varchar(36)))) v(v)
cross join  (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16)) r(d)
outer apply 
    (select d*2+1, '-' where d%4=0 and d<16
     union all
     select d*2, choose(d%2+1, cast(substring(v, d, 1)%10 as varchar), IsNull(char(NullIf(ascii('А')+substring(v, d, 1)%33, ascii('а'))), 'Ё'))
    ) f(f, s)
order by f
for xml path('')
) as varchar(19));
5 сен 16, 21:14    [19630620]     Ответить | Цитировать Сообщить модератору
 Re: Генерация случайной string по определённой маске  [new]
olgoosha
Member [скрыт]

Откуда:
Сообщений: 5
Гавриленко Сергей Алексеевич,

советую тебе на СИ такое сгенерить
6 сен 16, 00:22    [19631085]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить