Как насчет этого?
SQL> create table users
2 (username varchar2(20) primary key);
Table created.
SQL> create or replace procedure p_un (par_first_name in varchar2,
2 par_last_name in varchar2)
3 is
4 l_username users.username%type;
5 l_letter users.username%type;
6 l_digit users.username%type;
7 retval users.username%type;
8 begin
9 l_username := upper(substr(par_first_name, 1, 1) || par_last_name);
10
11 select max(regexp_substr(u.username, '^\w+')) l_letter,
12 max(regexp_substr(u.username, '\d+$')) l_digit
13 into l_letter,
14 l_digit
15 from users u
16 where u.username like l_username ||'%'
17 and ( substr(u.username, length(l_username) + 1, 1) between '1' and '9'
18 or ( regexp_substr(u.username, '\d$') is null
19 and substr(u.username, length(l_username) + 1, 1) is null
20 )
21 )
22 and ( to_number(regexp_substr(username, '\d$')) =
23 (select max(to_number(regexp_substr(u1.username, '\d$')))
24 from users u1
25 where u1.username like l_username ||'%'
26 and ( substr(u1.username, length(l_username) + 1, 1) between '1' and '9'
27 or ( regexp_substr(u1.username, '\d$') is null
28 and substr(u1.username, length(l_username) + 1, 1) is null
29 )
30 )
31 )
32 or regexp_substr(u.username, '\d$') is null
33 );
34
35 if l_letter is null then
36 retval := upper(l_username);
37 else
38 retval := upper(l_username || to_char(to_number(nvl(l_digit, 0)) + 1));
39 end if;
40
41 dbms_output.put_line('l_username = ' || l_username||', letter = '|| l_letter||
42 ', digit = '||l_digit ||', new username = ' || retval);
43 insert into users (username) values (retval);
44 end;
45 /
Procedure created.
Что это делает?
SELECT
(в строке 11) ищет существующие имена пользователей, которые
- выглядит как новое имя пользователя (которое состоит из первой буквы имени и всей фамилии) (строка 16)
- содержит число в конце (строка 17)
- или номер вообще отсутствует (строки 18, 19)
- но, если там есть номер, выберите МАКС. Номер (строка 23)
- если такого имени пользователя не существует, вернуть его значение по умолчанию (строка 36)
- если он существует, добавьте
1
к номеру MAX и присоедините его к значению имени пользователя по умолчанию (строка 38)
Тестирование:
SQL> exec p_un('Tom', 'Kelly');
l_username = TKELLY, letter = , digit = , new username = TKELLY
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Kelly');
l_username = TKELLY, letter = TKELLY, digit = , new username = TKELLY1
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Kelly');
l_username = TKELLY, letter = TKELLY1, digit = 1, new username = TKELLY2
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Ke');
l_username = TKE, letter = , digit = , new username = TKE
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Ke');
l_username = TKE, letter = TKE, digit = , new username = TKE1
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Kelly');
l_username = TKELLY, letter = TKELLY2, digit = 2, new username = TKELLY3
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Ke');
l_username = TKE, letter = TKE1, digit = 1, new username = TKE2
PL/SQL procedure successfully completed.
SQL> exec p_un('Tom', 'Ke');
l_username = TKE, letter = TKE2, digit = 2, new username = TKE3
PL/SQL procedure successfully completed.
Результат:
SQL> select * From users;
USERNAME
--------------------
TKE
TKE1
TKE2
TKE3
TKELLY
TKELLY1
TKELLY2
TKELLY3
8 rows selected.