I am trying to write a query to generates 1000 rows, I have a table called CCHOMEWORK with 2 columns, ID integer (PK) and StudentID varchar which contains the value for all the 1000 rows.
I tried this, but I keep getting errors and does not work
SET #MyCounter = 1
WHILE #MyCounter < 1000
BEGIN
INSERT INTO CCHOMEWORK
(ID)
VALUES
#MyCounter)
set #MyCounter = #MyCounter + 1;
END
This will create 1000 rows:
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 1000
You can include it in your insert with:
INSERT INTO CCHOMEWORK (ID)
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 1000
However, if you want to insert multiple sequential IDs you might be better using a sequence:
CREATE SEQUENCE CCHOMEWORK__ID__SEQ
/
Then:
INSERT INTO CCHOMEWORK (ID)
SELECT CC_HOMEWORK__ID__SEQ.NEXTVAL
FROM DUAL
CONNECT BY LEVEL <= 1000;
Or:
BEGIN
FOR i IN 1 .. 1000 LOOP
INSERT INTO CCHOMEWORK (ID) VALUES ( CC_HOMEWORK__ID__SEQ.NEXTVAL );
END LOOP;
END;
/
Syntax for Oracle database (using PL/SQL):
DECLARE
MyCounter NUMBER := 1;
BEGIN
LOOP
EXIT WHEN MyCounter> 1000;
INSERT INTO CCHOMEWORK (ID)
VALUES(MyCounter);
MyCounter := MyCounter+1;
END LOOP;
COMMIT;
END;
/
Related
I wrote These Two queries For Sample Table to insert into "z_exp14_resualt" From "z_exp14_main ". The First Query Works Correctly (Null) But Second That For rows have due_date on the main table (Not Null), not works correctly! . I Think Problem is The loop. It started before the due date and even goes beyond that . For NOT Nulls Insert must start from today(year and monts from sysdate and day from opening_date) and continue until due_date
Calculate For Null DUE_DATES
declare
i number := 1;
BEGIN
for i in 1..12 loop
insert into z_exp14_resualt
select dep_id,ADD_MONTHS(ADD_MONTHS(opening_date,trunc( months_between (sysdate,opening_date))),i),rate*balance
from z_exp14_main
WHERE due_date IS null;
end loop;
END;
/
And For Not Null Due_dates
DECLARE
diff number;
x number :=1;
BEGIN
for i in (select * FROM z_exp14_main WHERE due_date IS NOT null) loop
diff :=trunc( months_between (sysdate,i.opening_date));
WHILE (ADD_MONTHS(ADD_MONTHS(i.opening_date,diff),x)<i.due_date) LOOP
insert into z_exp14_resualt
select dep_id,ADD_MONTHS(ADD_MONTHS(i.opening_date,diff),x),rate*balance
from z_exp14_main WHERE due_date is not null ;
x :=x+1;
end loop;
end loop;
end;
/
sample Date On Main (z_exp14_main)
--
DEP_ID
DUE_DATE
BALANCE
RATE
OPENING_DATE
--
20056634
null
283428
10
15-SEP-16
--
20056637
null
180222
10
07-NOV-14
--
20056639
null
58741
10
28-AUG-14
--
40000020
27-NOV-21
5000000
22
31-MAR-14
--
40000023
23-APR-21
63000000
22
25-AUG-18
The Problem Is In the "While" condition. I correct it And This Is Final Answer:
DECLARE
diff number;
x number ;
BEGIN
for i in (select * FROM z_exp14_main WHERE due_date IS NOT null) loop
diff :=trunc( months_between (sysdate,i.opening_date));
x:=0;
WHILE (add_months(sysdate,x)<i.due_date) LOOP
insert into z_exp14_resualt values (i.dep_id,ADD_MONTHS(ADD_MONTHS(i.opening_date,diff),x),(i.rate*i.balance) );
x :=x+1;
end loop;
end loop;
end;
/
I am new to PL/SQL and just want to know what I can do here.
I have created a table that loops a counter up to 10 that is displayed in the table data.
How do I achieve it so I can count to 1-10 but exclude a number such a 5 so that it displays 1, 2, 3, 4, 6, 7, 8, 9, 10?
Current code is as follows;
DROP TABLE COUNTER
CREATE TABLE COUNTER (
COUNTER VARCHAR2(60)
);
DECLARE V_COUNTER NUMBER(2) := 1;
BEGIN
LOOP
INSERT INTO COUNTER (COUNTER)
VALUES (V_COUNTER);
V_COUNTER := V_COUNTER + 1
EXIT WHEN V_COUNTER = 11;
END LOOP;
END;
Table data;
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
Something like:
DROP TABLE COUNTER
CREATE TABLE COUNTER (COUNTER VARCHAR2(60));
BEGIN
FOR i IN 1 .. 10 LOOP
IF i <> 5 THEN
INSERT INTO COUNTER (COUNTER) VALUES (i);
END IF;
END LOOP;
END;
/
In general it's better to process such statements in bulk and avoid context switching ( here's more info on this topic.
DECLARE
TYPE t_values IS
TABLE OF NUMBER;
l_values t_values;
BEGIN
SELECT
level counter
BULK COLLECT
INTO l_values
FROM
dual
WHERE
level NOT IN (
6,
7
)
CONNECT BY
level <= 11;
FORALL i IN l_values.first..l_values.last
INSERT INTO counter VALUES ( l_values(i) );
END;
/
if code is simple enough you can always use plain insert stmt.
INSERT INTO counter
SELECT
level
FROM
dual
WHERE
level NOT IN (
6,
7
)
CONNECT BY
level <= 11;
I have this code from trigger and now i need to create procedure because i cant use trigger.
CREATE OR REPLACE TRIGGER LIVE_MATCHES_TO_MATCHES
instead of insert ON LIVE_MATCHES
for each row
declare
p_priority number:= 1;
p_sport number:=0;
begin
insert into matches(sub_list , priority , sport, created)
select :new.comp_name , p_priority, p_sport,sysdate
from dual
where not exists (
select 1 from matches
where sub_list = :new.comp_name);
end;
this is procedure :
CREATE OR REPLACE PROCEDURE LIVE_MATCHES_SOCCER_T IS
p_priority number := 1;
p_sport number:=0;
begin
INSERT INTO matches("sub_list","priority","sport","created")
SELECT LIVE_MATCHES.COMP_NAME,p_priority,p_sport, sysdate
FROM LIVE_MATCHES WHERE LIVE_MATCHES.COMP_NAME <> matches.SUB_LIST;
commit;
end;
but I m getting error that matches.sub_list is invalid identifier.
How will i create procedure that will insert into table only if sub_list is different from comp_name.. I will set up job that will call this procedure every 5 minutes..
You can use MERGE statement
CREATE OR REPLACE
PROCEDURE PR_INSRT_INTO_MATCHES
IS
P_PRIORITY NUMBER := 1;
P_SPORT NUMBER := 0;
BEGIN
MERGE INTO MATCHES M USING
(SELECT DISTINCT COMP_NAME AS COMP_NAME FROM LIVE_MATCHES
) LM ON (LM.COMP_NAME=M.SUB_LIST)
WHEN NOT MATCHED THEN
INSERT
(
M.SUB_LIST,
M.PRIORITY,
M.SPORT,
M.CREATED
)
VALUES
(
LM.COMP_NAME,
P_PRIORITY,
P_SPORT,
SYSDATE
)
COMMIT;
END;
I think you want:
INSERT INTO matches("sub_list","priority","sport","created")
SELECT lm.COMP_NAME, lm.p_priority, lm.p_sport, sysdate
FROM LIVE_MATCHES lm
WHERE NOT EXISTS (SELECT 1
FROM matches m
WHERE lm.COMP_NAME <> m.SUB_LIST
);
Unless your column names are lower-case (which can only be done in Oracle by using quotes when you create them - and which is not a particularly good idea in any case), then your stored procedure won't work, as you're quoting lower-case identifiers in it. Try this instead:
CREATE OR REPLACE PROCEDURE LIVE_MATCHES_SOCCER_T IS
p_priority number := 1;
p_sport number := 0;
begin
INSERT INTO matches
( sub_list, priority, sport, created )
SELECT LIVE_MATCHES.COMP_NAME, p_priority, p_sport, sysdate
FROM live_matches
WHERE NOT EXISTS ( SELECT 1 FROM matches WHERE LIVE_MATCHES.COMP_NAME = matches.SUB_LIST );
commit;
end;
here is my serial table.it has more than 1000 records.its with start number and end number.but between numbers not exist.
i need to add all number [start/between & end numbers] records in another temp table number by number
like below
EXIST TABLE
select concat(CARD_BULK_CODE,start_serial) startserial,concat(CARD_BULK_CODE,end_serial) endserial
from TSR_BULK_CARD_SERIALS
---------------------------
STARTSERIAL ENDSERIAL |
---------------------------
18126944 18126946 |
18141101 18141122 |
15150722 15150729 |
19069303 19069317 |
---------------------------
REQUIRED TABLE
-----------
SERIAL_NO |
-----------
18126944
18126945
18141101
18141102
....
-----------
seem its need pl-sql to implement this.
please help me to sort out this issue
I tried with below query with the help of dual.
but its very slow and not yet got results :-) running more than 1 Hour
select distinct concat(t.CARD_BULK_CODE,t.START_SERIAL)+level-1 SERIAL
from TSR_BULK_CARD_SERIALS t, dual
connect by level-1<=(concat(t.CARD_BULK_CODE,t.END_SERIAL ))-concat(t.CARD_BULK_CODE,t.START_SERIAL)
order by 1
EDIT :
Dear Alen & Dba.i tried with your ones and below error occured.
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (select concat(card_bulk_code, start_serial) startserial,concat(card_bulk_code, end_serial) endserial from tsr_bulk_card_serials)
LOOP
l_st := rec.startserial;
l_en := rec.endserial;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO temp(serial_no) values(rec1);
END LOOP;
END LOOP;
COMMIT;
END;
Error at line 1
ORA-01426: numeric overflow
ORA-06512: at line 9
Script Terminated on line 1.
One way to do it without resorting to plsql
WITH ranges AS
(
SELECT CONCAT(CARD_BULK_CODE, start_serial) startserial,
CONCAT(CARD_BULK_CODE, end_serial) endserial
FROM TSR_BULK_CARD_SERIALS
),
numbers(n) AS (
SELECT 0 n
FROM dual
UNION ALL
SELECT n + 1
FROM numbers
WHERE n <=
(
SELECT MAX(endserial - startserial)
FROM ranges
)
)
SELECT t.startserial + n.n SERIAL_NO
FROM ranges t JOIN numbers n
ON n.n <= t.endserial - t.startserial
ORDER BY SERIAL_NO
Here is SQLFiddle demo
Just write some PL/SQL - iterate through your table and insert rows in the temp table.
declare
l_start number;
l_end number;
begin
for r_rec in (select to_number(concat(card_bulk_code, start_serial)) startserial
, to_number(concat(card_bulk_code, end_serial)) endserial
from tsr_bulk_card_serials )
loop
l_start := r_rec.startserial;
l_end := r_rec.endserial;
for l_i in l_start..l_end loop
insert into your_temp_table;
end loop;
end loop;
end;
Try like this,
WITH t(ST, EN) AS
(
SELECT 18126944, 18126946 FROM dual
UNION
SELECT 18141101, 18141122 FROM dual
UNION
SELECT 15150722, 15150729 FROM dual
UNION
SELECT 19069303 , 19069317 FROM dual
)
SELECT DISTINCT st + LEVEL -1
FROM t
CONNECT BY LEVEL <= (SELECT en - st + 1 FROM DUAL)
ORDER BY 1;
/
Try something like this for PL/SQL,
DECLARE
l_st NUMBER;
l_en NUMBER;
BEGIN
FOR rec IN (SELECT * FROM t)
LOOP
l_st := rec.st;
l_en := rec.en;
FOR rec1 IN l_st..l_en
LOOP
INSERT INTO <your_tab>;
END LOOP;
END LOOP;
COMMIT;
END;
DECLARE
l_st NUMBER (20);
l_en NUMBER (20);
testnum NUMBER (4);
BEGIN
FOR rec IN (SELECT CONCAT (card_bulk_code, start_serial) startserial,CONCAT (card_bulk_code, end_serial) endserial FROM tsr_bulk_card_serials)
LOOP
l_st := TO_NUMBER (rec.startserial);
l_en := TO_NUMBER (rec.endserial);
testnum := l_en - l_st;
DBMS_OUTPUT.put_line (l_st);
DBMS_OUTPUT.put_line (l_en);
IF l_st < l_en
THEN
FOR rec1 IN 0 .. testnum
LOOP
l_st := l_st + 1;
INSERT INTO temp(serial_no) VALUES (l_st);
END LOOP;
END IF;
END LOOP;
COMMIT;
END;
above code helped me to sorted my issue
thanks all :-)
In my query I'm using a for loop, which displays 1000 three times. I have to increment 1000 for each iteration of the loop, i.e. 1001, 1002,.. same number three times i.e. I want to add into my table 1000,1000,1000,1001,1001,1001 and 1002,1002,1002,
declare
CPName varchar(20) :=1000;
a number;
begin
for a in 1 .. 3 loop
insert into clients values (CPName,null,null);
end loop;
end;
How can I do this?
CPName is a VARCHAR; I assume you want this to be a number, in which case you just add it on.
There's no need to define the variable a either, it's implicitly declared by the LOOP. I would call this i as it's a more common name for an index variable.
declare
CPName integer := 1000;
begin
for i in 1 .. 3 loop
insert into clients values (CPName + i, null, null);
end loop;
end;
You can do this all in a single SQL statement though; there's no need to use PL/SQL.
insert into clients
select 1000 + i, null, null
from dual
cross join ( select level as i
from dual
connect by level <= 3 )
Based on your comments you actually want something like this:
insert into clients
with multiply as (
select level - 1 as i
from dual
connect by level <= 3
)
select 1000 + m.i, null, null
from dual
cross join multiply m
cross join multiply
This will only work if you want the same number of records as you want to increase so maybe you'd prefer to do it this way, which will give you a lot more flexibility:
insert into clients
with increments as (
select level - 1 as i
from dual
connect by level <= 5
)
, iterations as (
select level as j
from dual
connect by level <= 3
)
select 1000 + m.i, null, null
from dual
cross join increments m
cross join iterations
Using your LOOP methodology this would involve a second, interior loop:
declare
CPName integer := 1000;
begin
for i in 1 .. 3 loop
for j in 1 .. 3 loop
insert into clients values (CPName + i, null, null);
end loop;
end loop;
end;