Generate 6 numbers without repetition from the set 1 ... 49 - sql

I need to generate 6 numbers without repetition from 1 to 49.
I have something like that:
create table zadanie1(
NAZWISKO varchar2(30),
PUNKTY number,
ID number,
constraint stud1_nazw primary key(NAZWISKO)
);
create or replace procedure "LOTTO" IS
pkt number;
begin
loop
BEGIN
pkt := round(dbms_random.value(1,14),0);
INSERT INTO ZADANIE1(PUNKTY) VALUES (pkt);
exit;
Exception When DUP_VAL_ON_INDEX Then 0;
END;
end loop;
END;
but this doesn't seem to work. Can somebody help me ?

SQL> select num
2 from (select rownum num
3 from dual
4 connect by level <= 49
5 order by dbms_random.value)
6 where rownum <= 6;
NUM
----------
10
6
9
12
22
14

Just put the 49 numbers in a table and use
SELECT SOME_NUMBER FROM
(
SELECT SOME_NUMBER
FROM TABLE_OF_NUMBERS
ORDER BY DBMS_RANDOM.VALUE()
)
WHERE ROWNUM < 7

ok, thx for answer. I need to add column for this table. and for every row(user) add 6 number like in lottery.
create table zadanie1(
user varchar2(30),
PUNKTY number,
ID number,
constraint stud1_nazw primary key(NAZWISKO)
);

Related

Inserting random from a given string

My purpose is to write an insert statement that adds a random value from a given string, more specifically if the person is married, single or a widower. I needed to first populate my table with hundreds of random entries because I need to run Autotrace on it and check its optimization. In any event, I first created the table, then populated all the columns, except for the one concerning marital status. Then I wanted to write a different INSERT statement just for that because I thought it might be easier then putting it into the plSQL block I made to populate the table. Here is my code:
create table employees(
id_employee integer not null,
name varchar2(50) not null,
surname varchar2(50) not null,
marital_status varchar2(50),
birthday date);
ALTER TABLE employees ADD CONSTRAINT employees_pk PRIMARY KEY ( id_employee );
declare
id_employee integer:= 1;
begin
while id_employee <= 20 loop
insert into employees values (id_employee, dbms_random.string('l', 10), dbms_random.string('l', 10), null, TO_DATE(
TRUNC(
DBMS_RANDOM.VALUE(TO_CHAR(DATE '2016-01-01','J')
,TO_CHAR(DATE '2020-12-31','J')
)
),'J'
));
id_employee:= id_employee + 1;
end loop;
end;
Now that I've managed this and it worked, I just need to create an INSERT statement to basically modify the null value that is on every entry's marital_status column. But as I stated earlier, I want to have a statement that will return either (married, single, widower). Can this be achieved? Or is it not possible to give a command to extract a random value from a given string?
If I understood you correctly, you don't need PL/SQL at all - everything can be done in a single insert statement (or select, if you prefer). Here's how:
SQL> CREATE TABLE employees
2 (
3 id_employee INTEGER PRIMARY KEY,
4 name VARCHAR2 (50) NOT NULL,
5 surname VARCHAR2 (50) NOT NULL,
6 marital_status VARCHAR2 (50),
7 birthday DATE
8 );
Table created.
SQL> CREATE SEQUENCE seqes;
Sequence created.
Insert sample rows:
SQL> INSERT INTO employees (id_employee,
2 name,
3 surname,
4 marital_status,
5 birthday)
6 SELECT seqes.NEXTVAL id_employee,
7 DBMS_RANDOM.string ('l', 10) name,
8 DBMS_RANDOM.string ('l', 10) surname,
9 --
10 CASE
11 WHEN MOD (seqes.NEXTVAL, 3) = 0 THEN 'single'
12 WHEN MOD (seqes.NEXTVAL, 2) = 0 THEN 'married'
13 ELSE 'widower'
14 END marital_status,
15 --
16 TO_DATE (
17 TRUNC (
18 DBMS_RANDOM.VALUE (TO_CHAR (DATE '2016-01-01', 'J'),
19 TO_CHAR (DATE '2020-12-31', 'J'))),
20 'J') birthda
21 FROM DUAL
22 CONNECT BY LEVEL <= 20;
20 rows created.
Result:
SQL> SELECT * FROM employees;
ID_EMPLOYEE NAME SURNAME MARITAL_STATUS BIRTHDAY
----------- ------------ ------------ --------------- ----------
1 cpewxypfop urkqkpapdk widower 22.12.2018
2 qjslhprqxf jxoaennyqe married 27.08.2017
3 jjwknqkcel zkmnwtoovv single 25.10.2018
4 levwydigey numbxjvjtc married 12.02.2019
5 hswtiotjin cjdfiastvi widower 30.01.2019
6 yxahvjfmre dnlfmkphmv single 11.08.2017
7 nctcntredz raqpofzufx widower 29.05.2018
8 wyivovpnoc ikjakuzanf married 19.09.2016
9 rvtbqfgqnu iuqjqosait single 28.07.2018
10 oislloosfy xtfxpnceik married 30.03.2020
11 issbxtldsn bovdghpjke widower 21.09.2018
12 gzgjdlvwcw rmfqglwohc single 11.12.2019
13 utbznnyyhs ojcswdwuvh widower 21.12.2019
14 etsvhavose fypgntictn married 23.03.2018
15 myjijmagej lvmpbcvcfc single 12.09.2016
16 givwwayxkf hgemcfvnff married 13.02.2016
17 nquarbpzlf zwgjukhgxg widower 07.09.2018
18 lnyyrkohac ttygaxmvle single 25.05.2020
19 gmqboujcbb qszmifozcs widower 20.09.2019
20 eegwdvqvld dsembshumq married 04.09.2020
20 rows selected.
SQL>

Multiple Sequence in SQL Oracle / Varchar2 ID with letters and digits

I am trying to 'generate' a Varchar ID that contains letters and digits too with a sequence, but I think there will be more sequences than one.
What I am looking forward to is something like this 'DJ_Digit_Digit_Letter_Letter_Letter'. An example would be DJ00WVX/DJ01HYZ/DJ99ZZZ. This is also my primary key so it would be good if I could not encounter any primary key errors.
I thought about working in ascii so I will generate numbers between 65 and 90 (A-Z) and Insert them into the column. Same for the numbers in ascii 45 to 57 or something like that. I don't know how I could use more sequences on the same column like 'letter_seq.nextvalue,digit_seq.nextvalue', i know that this example is wrong, but it was easier for me to explain it. Maybe all my thinking is wrong
In conclusion I need to get something that starts with DJ followed by 2 digits and 3 letters, all wrapped up in a primary key. It's ok to get like 20-30 unique entries, I think.
Thank you for your help!
You can create an INVISIBLE IDENTITY column and then create your letter-digit-letter sequence as a function generated from the invisible column:
CREATE TABLE table_name (
id_seq_value INT
INVISIBLE
GENERATED ALWAYS AS IDENTITY( START WITH 0 INCREMENT BY 1 MINVALUE 0 MAXVALUE 175799 )
NOT NULL
CONSTRAINT table_name__id_seq_value__u UNIQUE,
id VARCHAR2(7)
GENERATED ALWAYS AS (
CAST(
'DJ'
|| TO_CHAR( FLOOR( id_seq_value / POWER( 26, 3 ) ), 'FM00' )
|| CHR( 65 + MOD( FLOOR( id_seq_value / POWER(26, 2) ), 26 ) )
|| CHR( 65 + MOD( FLOOR( id_seq_value / POWER(26, 1) ), 26 ) )
|| CHR( 65 + MOD( id_seq_value, 26 ) )
AS VARCHAR2(7)
)
)
CONSTRAINT table_name__id__pk PRIMARY KEY,
name VARCHAR2(50)
);
Then you can do:
INSERT INTO table_name ( name ) VALUES ( 'Item1' );
INSERT INTO table_name ( name ) VALUES ( 'Item2' );
Then:
SELECT * FROM table_name;
Outputs:
ID | NAME
:------ | :----
DJ00AAA | Item1
DJ00AAB | Item2
(If you want to increment the digits and the letters together then change the IDENTITY to INCREMENT BY 17577 (263+1).)
db<>fiddle here
To me, it looks like this:
SQL> create table test (id varchar2(10));
Table created.
SQL> create sequence seq1;
Sequence created.
SQL> insert into test (id)
2 with
3 a as (select chr(64 + level) la from dual
4 connect by level <= 26),
5 b as (select chr(64 + level) lb from dual
6 connect by level <= 26),
7 c as (select chr(64 + level) lc from dual
8 connect by level <= 26)
9 select 'DJ' || lpad(seq1.nextval, 2, '0')
10 || la || lb || lc id
11 from a cross join b cross join c;
17576 rows created.
SQL>
Several sample values:
SQL> with temp as
2 (select id,
3 row_number() Over (order by id) rna,
4 row_Number() over (order by id desc) rnd
5 from test
6 )
7 select id
8 from temp
9 where rna <= 5
10 or rnd <= 5
11 order by id;
ID
----------
DJ01AAA
DJ02AAB
DJ03AAC
DJ04AAD
DJ05AAE
DJ99OUK
DJ99OUL
DJ99OUM
DJ99OUN
DJ99OUO
10 rows selected.
SQL>
However, if
It's ok to get like 20-30 unique entries, I think.
means that you need to generate at most 30 values, well, you'd easily create them manually; why would you develop any software solution for that? If you started typing, you'd be over by now.

how to raise user defined exception in PL/SQLwhen duplicate row is inserted into the table.?

I want to create a user defined exception for duplicate row insertion i.e an excption is raised when a duplicate data(already present in the table) is inserted into the table.My table is dept with columns deptno,dname,loc.So, i want to raise user defined exception for duplicate entry.
create or replace procedure ADD_DEPT(DEPTNO in dept.deptno%type,
DNAME in dept.dname%type,LOC in dept.loc%type) is
begin
insert into dept values(DEPTNO,DNAME,LOC);
end;
Assuming you have a unique constraint on deptno, or a primary key, as you should be, then you can raise a particular exception using DUP_VAL_ON_INDEX and RAISE_APPLICATION_ERROR
create or replace procedure ADD_DEPT(DEPTNO in dept.deptno%type,
DNAME in dept.dname%type,LOC in dept.loc%type)
is
begin
insert into dept values(DEPTNO,DNAME,LOC);
exception
when dup_val_on_index
then
raise_application_error(-20001,'Value duplicated on deptno' );
end;
UPDATE
Let me show you an example.
SQL> create table x ( c1 number not null primary key , c2 number ) ;
insert into x values ( 1 , '1' );
insert into x values ( 2 , '1' );
Table created.
SQL> SQL>
1 row created.
SQL> SQL>
1 row created.
SQL> create or replace procedure add_to_x ( p_c1 in number , p_c2 in number )
2 is
begin
3 4 insert into x values (p_c1 , p_c2);
commit;
5 6 exception when dup_val_on_index
then
7 8 raise_application_error(-20001,'Value duplicated on deptno' );
when others then
9 10 raise;
end; 11
12 /
Procedure created.
SQL> select * from x ;
C1 C2
---------- ----------
1 1
2 1
SQL> exec add_to_x ( 1 , 3 ) ;
BEGIN add_to_x ( 1 , 3 ) ; END;
*
ERROR at line 1:
ORA-20001: Value duplicated on deptno
ORA-06512: at "SYS.ADD_TO_X", line 8
ORA-06512: at line 1
SQL>
I hope you are looking for something like this.
create or replace procedure ADD_DEPT(P_DEPTNO in dept.deptno%type,
P_DNAME in dept.dname%type,P_LOC in dept.loc%type) is
duplicate_value_Exists EXCEPTION;
PRAGMA exception_init( duplicate_value_Exists, -20001 );
v_count number;
begin
select count(1)
into v_count
from dept
WHERE DEPTNO = P_DEPTNO
AND P_DNAME = DNAME
AND LOC = P_LOC;
if v_count >= 1 then
RAISE duplicate_value_Exists;
else
insert into dept values(P_DEPTNO,P_DNAME,P_LOC);
end if;
end;

PL/SQL insert data into a column with values corresponding to values of another column

There is a table with table structure something like this customer_id number(10), listing_id number(12).
Now The data in this table is somewhat above 10 million so i've been given a task of adding a process_id to the table so that the data can be processed in batches in future operations.
so I added a column process_id to the table
alter table temp_lid_cid add process_id number(1) ;
Now i have to add process ids to the customer_ids at random 1 2 3 4 5 6 7, so that they will get processed according to their process_ids when condition where process_id = $1
There are millions of data so i wrote a simple PL
declare
i temp_lid_cid.customer_id%type;
c temp_lid_cid.process_id%type;
begin
c:=0;
for i in (select customer_id from temp_lid_cid)
loop
if (c = 7) then
c := 0;
end if;
c := c+1;
execute immediate q'[insert into temp_lid_cid(process_id) select :var1 as process_id from temp_lid_cid where customer_id = :var2]'using i,c;
end loop;
end;
It throws this error
Error report -
ORA-06550: line 12, column 145:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 12, column 9:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I tried running the insert statement without execute immediate too but it still threw an error.I also tried running the insert statement for a single customer outside the PL and it worked fine.
If you can suggest any other way to do what i'm trying to do without PL that would be great too.
Now The data in this table is somewhat above 10 million so i've been
given a task of adding a process_id to the table so that the data can
be processed in batches
Insert will Insert a new row to your table. You need an Update statement to fullfill your requirement. See below:
DECLARE
i temp_lid_cid.customer_id%TYPE;
c temp_lid_cid.process_id%TYPE;
BEGIN
c := 0;
FOR i IN (SELECT customer_id FROM temp_lid_cid )
LOOP
IF ( c = 7 )
THEN
c := 0;
END IF;
c := c + 1;
UPDATE temp_lid_cid
SET
process_id = c
WHERE customer_id = i.customer_id;
END LOOP;
COMMIT;
END;
Error in your code:
In your Loop, customer_id is fetched using i.customer_id. So in your insert statement replace as below:
using c,i.customer_id;
Suggestion:
Since the number of rows is 10 Million so i would recommend to use BULK Operation to perform Update.
DECLARE
c temp_lid_cid.process_id%TYPE;
type v_cust_id is table of temp_lid_cid.customer_id%TYPE index by pls_integer;
i v_cust_id;
BEGIN
c := 0;
SELECT customer_id
BULK COLLECT INTO i
FROM temp_lid_cid;
FORALL rec IN 1..i.count
UPDATE temp_lid_cid
SET
process_id = c + i(rec) -- Updating Process_Id with Customer_id
WHERE customer_id = i(rec);
COMMIT;
END;
you interchanged your sql type.
declare
i temp_lid_cid.process_id%type;
c temp_lid_cid.customer_id%type;
Why use PL/SQL block and loop for it. It can be done using a single merge statement as following: (I am using the range from 1-4 numbers, you can use 1-7 numbers by replacing 4 with 7 in merge statement)
Oracle table creation:
SQL> CREATE TABLE TEMP_LID_CID (
2 CUSTOMER_ID NUMBER(10),
3 LISTING_ID NUMBER(12),
4 PROCESS_ID NUMBER(1)
5 );
Table created.
Inserting data into the table:
SQL> insert into temp_lid_cid values (1,10,null);
1 row created.
SQL> insert into temp_lid_cid values (1,20,null);
1 row created.
SQL> insert into temp_lid_cid values (1,30,null);
1 row created.
SQL> insert into temp_lid_cid values (1,40,null);
1 row created.
SQL> insert into temp_lid_cid values (1,50,null);
1 row created.
SQL> insert into temp_lid_cid values (2,10,null);
1 row created.
SQL> insert into temp_lid_cid values (2,20,null);
1 row created.
SQL> insert into temp_lid_cid values (2,30,null);
1 row created.
Current view of the data
SQL> select * from TEMP_LID_CID;
CUSTOMER_ID LISTING_ID PROCESS_ID
----------- ---------- ----------
1 10
1 20
1 30
1 40
1 50
2 10
2 20
2 30
8 rows selected.
SQL>
query to achieve the desired result:
SQL> MERGE INTO TEMP_LID_CID T USING (
2 SELECT
3 T1.*,
4 T1.ROWID AS RID,
5 MOD(ROW_NUMBER() OVER(
6 ORDER BY
7 T1.CUSTOMER_ID
8 ), 4) AS RANDOM_PROCESS_ID -- replace 4 with 7
9 FROM
10 TEMP_LID_CID T1
11 )
12 T1 ON ( T.ROWID = T1.RID )
13 WHEN MATCHED THEN UPDATE SET T.PROCESS_ID = DECODE(T1.RANDOM_PROCESS_ID, 0, 4, T1.RANDOM_PROCESS_ID); -- replace 4 with 7
Data after update:
SQL> select * from TEMP_LID_CID;
CUSTOMER_ID LISTING_ID PROCESS_ID
----------- ---------- ----------
1 10 1
1 20 2
1 30 3
1 40 4
1 50 1
2 10 2
2 20 3
2 30 4
8 rows selected.
SQL>
Since process_id can be random, you could also use a simple query like this:
update temp_lid_cid set process_id = mod(rownum,7)+1;

How to insert into temp table when looping through a string - Oracle - PL/SQL

CREATE GLOBAL TEMPORARY TABLE tt_temptable(
RowNums NUMBER(3,0),
procNums NUMBER(18,0)
) ON COMMIT PRESERVE ROWS;
inputString VARCHAR2 ;
inputString := '12,13,14,15'
SELECT REGEXP_SUBSTR (inputString,'[^,]+',1,LEVEL) ProcNums
FROM dual CONNECT BY REGEXP_SUBSTR (inputString,'[^,]+',1,LEVEL) IS NOT NULL;
INSERT INTO tt_temptable(
SELECT identity(3) RowNums,procNums
FROM
);
Want to insert 12 , 13, 14 , 15 and identity of 3 length in the temptable so total 4 rows in temptable
If you use Oracle 12c, then you may define an IDENTITY column through GENERATED ALWAYS AS IDENTITY in your table definition and follow the way below :
SQL> CREATE GLOBAL TEMPORARY TABLE tt_temptable(
2 RowNums NUMBER(3,0) GENERATED ALWAYS AS IDENTITY,
3 procNums NUMBER(18,0)
4 ) ON COMMIT PRESERVE ROWS;
Table created
SQL>
SQL> DECLARE
2 inputString VARCHAR2(50) := '12,13,14,15';
3 BEGIN
4 INSERT INTO tt_temptable(procNums)
5 SELECT REGEXP_SUBSTR (inputString,'[^,]+',1,LEVEL) ProcNums
6 FROM dual
7 CONNECT BY REGEXP_SUBSTR (inputString,'[^,]+',1,LEVEL) IS NOT NULL;
8 END;
9 /
PL/SQL procedure successfully completed
SQL> SELECT * FROM tt_temptable;
ROWNUMS PROCNUMS
------- -------------------
1 12
2 13
3 14
4 15
To reset the IDENTITY column (RowNums), use :
SQL> ALTER TABLE tt_temptable MODIFY( RowNums Generated as Identity (START WITH 1));
whenever the shared locks on the table are released.
insert
into tt_temptable
select NVL((select max(a.rownums)
from tt_temptable a
),100)+rownum
,procNums
from (SELECT REGEXP_SUBSTR ('10,20,30','[^,]+',1,LEVEL) ProcNums,level as lvl
FROM dual
CONNECT BY REGEXP_SUBSTR ('10,20,30','[^,]+',1,LEVEL) IS NOT NULL
)x