SQL SERVER / Generowanie losowych 'wyrazów' o losowej długości z określonego zbioru znaków

0

Witam,

Temat wpisu może jest trochę enigmatyczny ale już wyjaśniam o co mi chodzi. W SQL SERVER Potrzebuję stworzyć tabelę która będzie zawierała milion losowych danych. Ma to być imitacja tabeli która zawiera trzy kolumny (ID_Osoby, Imie_Osoby, Nazwisko_Osoby).

Jeżeli chodzi o wygenerowanie miliona rekordów ID_Osoby to tutaj nie ma problemu (jest to klucz główny który sam się inkrementuje). Problem zaczyna się przy Imieniu i Nazwisku. Nie chodzi tutaj oczywiście o prawdziwe imiona i nazwiska, chodzi raczej o ciąg znaków przypominający je np. 'sbbabs uyygsavwn'.

Nie jestem w stanie napisać kodu który właśnie wygeneruje podobne ciągi znaków z określonego wcześniej 'afabetu'. Za każdym razem dostaję albo jeden losowy znak, albo ich ciąg np. 'bcdefg mnopr'.

Zależałoby mi aby wygenerować Imiona i Nazwiska które będą się składać z losowych długości losowych znaków ze zdefiniowanego wcześniej 'alfabetu'. Jestem na etapie w którym potrzebuję funkcji która będzie powtarzać moją funkcję losową ilość razy. Wklejam mój kod poniżej:


CREATE TABLE Test (ID_Osoby integer IDENTITY(1,1) PRIMARY KEY,
Imie_Osoby varchar(25),
Nazwisko_Osoby varchar(25))
GO

DECLARE @alfabet varchar(33) = 'abcdefghijklmnoprstuówxyzęąśłżźćń', -- zbiór liter do wyboru (z których ma powstać Imie i Nazwisko)
@Row integer

SET @Row = 0 -- Ustawiam punkt startowy pętli na '0'
WHILE @Row < 1000000 -- I wskazuję ile razy system ma ją wykonać (tak długo jak punkt startowy będzie mniejszy niż '1000000')

BEGIN

 INSERT INTO Test (Imie_Osoby, Nazwisko_Osoby)
 VALUES (                                                                                            
                   (SUBSTRING (@Alfabet, CONVERT(INT, rand() * 33), 1)),   -- Imię Osoby które składa się z losowej litery 
                   (SUBSTRING (@Alfabet, CONVERT(INT, rand() * 33), 1))    -- Nazwisko Osoby które składa się z losowej litery 
		)

 SET @Row = @Row + 1                                                                    -- Określam wzrost o 1 dzięki czemu każda następny loop będzie mógł się odbyć 'od nowa' ponieważ wartość startowa będzie zawsze większa o 1 od poprzedniej, aż do 1000000

END


Tak jak pisałem wyżej, musiałbym powtórzyć tą część kodu (SUBSTRING (@alfabet, CONVERT(INT, rand() * 33), 1)) losową ilość razy aby system mógł wylosować jakąś literę z alfabetu a następnie zrobić to kolejne X razy tak aby powstało 'Imię' i 'Nazwisko'.

Jedyne rozwiązanie które przychodziło mi do głowy to:

(CONVERT(INT, rand() * 33), 1) + 2) "MNOŻONE PRZEZ" (SUBSTRING (@alfabet, CONVERT(INT, rand() * 33), 1)) - niestety powoduje to że dostajemy dane które wyglądają tak 'vvvv uuuuuu'. Czyli losowa litera powtórzona losową ilość razy.

Próbowałem bawić się z CHAR/ANSII/GET ID itp jednak w tym wypadku kluczowe jest używanie wcześniej określonego zbioru znaków.

Czy przychodzi komuś coś na myśl odnośnie rozwiązania tego problemu?

Jak zrobić żeby za każdym razem SQL wybierał nową literę i zapętlał ten proces losową liczbę razy?

Z góry dziękuję za pomoc.

1
PinkMachine napisał(a):

Jak zrobić żeby za każdym razem SQL wybierał nową literę i zapętlał ten proces losową liczbę razy?

Wykorzystaj pętle WHILE, której licznik będzie przyjmował losową wartość (a przez to napis będzie miał losową długość).

DECLARE @Alphabet VARCHAR(33) = 'abcdefghijklmnoprstuówxyzęąśłżźćń'
	, @StrLength INT
	, @LoopCount INT
	, @RandomString VARCHAR(MAX)
	, @AlphabetLength INT;

SELECT @StrLength = RAND() * 5 + 5, @LoopCount = 0, @RandomString = '', @AlphabetLength = LEN(@Alphabet);

WHILE (@LoopCount < @StrLength)
BEGIN
	SELECT @RandomString = @RandomString + 
        SUBSTRING(@Alphabet, CONVERT(int, RAND() * @AlphabetLength), 1)
	SET @LoopCount = @LoopCount + 1;
END

SELECT @RandomString
0

Dzięki za odpowiedź @Haskell

Faktycznie, twój kod generuje słowo składające się z losowej ilości losowych liter ze zbioru okreśłonego jako 'alphabet'.

W jaki sposób mam to teraz powtórzć milion razy, do każdego z wierszy w tabeli z osobna?

Próbowałem połączyć twój kod który generuje jedno słowo z moim który zapętla się milion razy i... znowu dostaję tylko jedna literę. Co więcej, liczba wygenerowanych wierszy jest zawsze równa 1-10 ( Wynika to z faktu, że pętla WHILE (@LoopCount , @StringLength) daje wynik zawsze od 1 do 10. Samo @StringLength = RAND() * 5 + 5 będzie dawało losową liczbe z przedziału od 1 - 5 i potem będzie dodawało 5. Przy próbie zamiany na RAND() * 999995 + 5 znowu liczba wierszy w tabeli jest losową liczbą od 6 do 1,000,000).

DECLARE

@alfabet varchar(33) = 'abcdefghijklmnoprstuówxyzęąśłżźćń',
@Row integer,
@StringLength INT,
@AlfabetLength INT,
@RandomString VARCHAR(MAX),
@LoopCount INT;

SELECT

@Row = 0,
@StringLength = RAND() * 5 + 5,
@LoopCount = 0, @RandomString = '',
@AlfabetLength = LEN(@alfabet);

WHILE (@LoopCount < @StringLength)
BEGIN

INSERT INTO Test (Imie_Osoby, Nazwisko_Osoby)
VALUES (
(@Randomstring + SUBSTRING (@alfabet, CONVERT(INT, RAND() * @AlfabetLength), 1)),
(@Randomstring + SUBSTRING (@alfabet, CONVERT(INT, RAND() * @AlfabetLength), 1))
)

SET @LoopCount = @LoopCount + 1
END
GO

Czy możesz na to rzucić okiem?

Z góry dzięki!

1

Ubierz kod haskela w funkcje skalarną i dodawaj na zasadzie

Insert into test values (dbo.nazwafunkci(),dbo.nazwafunkcij())

0

Dzięki Panowie za rady, udało się.

Wklejam poniżej rozwiązanie, może ktoś kiedyś będzie potrzebować:

  1. Stworzyłem WIDOK, ponieważ funkcja systemowa RAND() nie może zostać użyta wewnątrz funkcji skalarnej:
AS
SELECT RAND() RandomResult
GO```


2. Stowrzyłem FUNKCJĘ SKALARNĄ która używa WIDOKU 'RANDOM' i generuje losowe słowo o losowej długości z określonego wcześniej zbioru znaków, w.g. porady @Haskell:




CREATE FUNCTION dbo.GeneratorSlowa()
RETURNS VARCHAR(MAX)
AS BEGIN

   DECLARE @Alphabet VARCHAR(33) = 'abcdefghijklmnoprstuówxyzęąśłżźćń',
                   @StrLength INT,
                   @LoopCount INT,
                   @RandomString VARCHAR(MAX),
                   @AlphabetLength INT;

    SELECT @StrLength = (SELECT RandomResult FROM dbo.Random) * 4 + 7, @LoopCount = 0, @RandomString = '', @AlphabetLength = LEN(@Alphabet);

     WHILE (@LoopCount < @StrLength)   -- Pętla która ma za zadanie okreslanie losowej dlugosci slowa
            BEGIN
                    SELECT @RandomString = @RandomString + SUBSTRING(@Alphabet, CONVERT(INT, (SELECT RandomResult FROM dbo.Random) * @AlphabetLength), 1)
                    SET @LoopCount = @LoopCount + 1;	-- I powtórzenie czynności
            END

   RETURN @RandomString;
END



3. Na końcu połączenie wszystkiego w jedną całość przy tworzeniu Tabeli i napisaniu pętli która doda 1,000,000 losowych rekordów:


DROP TABLE Test
GO

CREATE TABLE Test (ID_Osoby integer IDENTITY(1,1) PRIMARY KEY,
Imie_Osoby varchar(25),
Nazwisko_Osoby varchar(25))
GO

DECLARE @Row integer

SET @Row = 0 -- punkt startowy 0
WHILE @Row < 1000000 -- gdy punkt startowy mniejszy niz 1,000,000 zaczynaj z kodem ponizej:
BEGIN

  INSERT INTO Test (Imie_Osoby, Nazwisko_Osoby)
  SELECT dbo.GeneratorSlowa(), dbo.GeneratorSlowa()
  SET @Row = @Row + 1                                                      -- po wprowadzeniu slow do tabeli dodaj +1 do 'Row'. Dzieki temu mamy pętle.                                                

END





4. Voilla! raz jeszcze dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1