Returning 6-character values that do not overlap is quite tricky. As Costa mentions, the canonical solution is to use UUIDs. There are pretty much guaranteed to be unique. But they are not 6 characters.
If they did not need to be "random", you could generate a number and convert it to the format you want:
select concat(substring(c.chars, (v.n / power(len(c.chars), 5)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n / power(len(c.chars), 4)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n / power(len(c.chars), 3)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n / power(len(c.chars), 2)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n / power(len(c.chars), 1)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n / power(len(c.chars), 0)) % len(c.chars) + 1, 1)
)
from (values (0), (1), (100), (1000), (10000), (100000), (1000000), (10000000), (100000000)) v(n) cross join
(values ('2346789abcdefghjkmnpqrtuvwxyz')) c(chars);
Here is a db<>fiddle. For the n
value, you could use a sequence or if you never need more than one value per second, the number of seconds since some cutoff value.
Note that you could "tweak" the above to make it look more random. For instance, you can multiply v.n
times some large random number:
select concat(substring(c.chars, (v.n * 1000117 / power(len(c.chars), 5)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n * 1000117 / power(len(c.chars), 4)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n * 1000117 / power(len(c.chars), 3)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n * 1000117 / power(len(c.chars), 2)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n * 1000117 / power(len(c.chars), 1)) % len(c.chars) + 1, 1),
substring(c.chars, (v.n * 1000117 / power(len(c.chars), 0)) % len(c.chars) + 1, 1)
)
from (values (cast(0 as bigint)), (1), (100), (1000), (10000), (100000), (1000000), (10000000), (100000000)) v(n) cross join
(values ('2346789abcdefghjkmnpqrtuvwxyz')) c(chars);
This is probably good enough for what you want to do.
Absent that, brute force is an option. There are only 594,823,321 different values. This easily fits into a table. So you could generate them and then use the table to be sure you don't get duplicates.