Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it possible to have alphanumeric sequence generator in sql

I need to write a SQL query to print the following aphanumberic sequence in SQL

0001, 0002, ... , 0009, 000A, ... , 000Z, ... , 0010, 0011, ... , 001A, ... and so on till... , ZZZZ

please note: all characters are UPPERCASE.

Thanks in advance

like image 236
kanap008 Avatar asked Dec 16 '10 10:12

kanap008


People also ask

How do you create an alphanumeric sequence in SQL?

You have to create 1 sequence and 1 transforming function: CREATE SEQUENCE num_seq START WITH 6500000000 INCREMENT BY 1 MAXVALUE 9099999999; FUNCTION next_id(seq_name) RETURN VARCHAR2 IS x VARCHAR2(28); BEGIN EXECUTE IMMEDIATE 'SELECT TRIM(TO_CHAR(' || seq_name || '.

Can we generate alphanumeric value in sequence generator?

The Sequence Generator only supports numeric values.


2 Answers

You could create a function like this:

create function to_base_36 (n integer) return varchar2
is
  q integer;
  r varchar2(100);
begin
  q := n;
  while q >= 36 loop
     r := chr(mod(q,36)+case when mod(q,36) < 10 then 48 else 55 end) || r;
     q := floor(q/36);
  end loop;
  r := chr(mod(q,36)+case when mod(q,36) < 10 then 48 else 55 end) || r;
  return lpad(r,4,'0');
end;

and then use it like this:

select rownum, to_base_36(rownum)
from dual
connect by level < 36*36*36*36;

Or, without creating a function:

with digits as
( select n, chr(mod(n,36)+case when mod(n,36) < 10 then 48 else 55 end) d
  from (Select rownum-1 as n from dual connect by level < 37)
)
select d1.n*36*36*36 + d2.n*36*36 + d3.n*36 + d4.n, d1.d||d2.d||d3.d||d4.d
from digits d1, digits d2, digits d3, digits d4
like image 140
Tony Andrews Avatar answered Sep 22 '22 10:09

Tony Andrews


You could use this function:

create or replace FUNCTION SEQGEN(vinp in varchar2, iSeq in INTEGER) 
RETURN VARCHAR2 is vResult VARCHAR2(32);
  iBas INTEGER; iRem INTEGER; iQuo INTEGER; lLen CONSTANT INTEGER := 2;
BEGIN
  iBas := length(vInp);
  iQuo := iSeq;
  WHILE iQuo > 0 LOOP
    iRem := iQuo mod iBas;
    --dbms_output.put_line('Now we divide ' || lpad(iQuo,lLen,'0') || ' by ' || lpad(iBas,lLen,'0') || ', yielding a quotient of ' || lpad( TRUNC(iQuo / iBas) ,lLen,'0') || ' and a remainder of ' || lpad(iRem,lLen,'0') || ' giving the char: ' || substr(vInp, iRem, 1));
    iQuo := TRUNC(iQuo / iBas);
    If iRem < 1 Then iRem := iBas; iQuo := iQuo - 1; End If;
    vResult := substr(vInp, iRem, 1) || vResult;
  END LOOP;
  RETURN vResult;
END SEQGEN;

Try the function:

SELECT * FROM (
SELECT seqgen('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',rownum + 47989 --start value
) Output, level evt FROM dual CONNECT BY level < 1679618)  --stop value
WHERE mod(evt,50000) = 0 OR output in ('0001','0002','0009','000A','000Z',
                                       '0010','0011','001A','ZZZZ')

Note that if you change the string you must also change the start and stop value.

Read more about number systems here: Number System Conversion - Explanation

like image 27
wittrup Avatar answered Sep 20 '22 10:09

wittrup