A bit of PLSQL - just for fun.

Always, looking for bits of PLSQL to use with my apprentice so that he might pick it up.

If you want to test your select knowledge.

http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial

Not necessarily database related. So just for fun we did these.
  • Simple maths question
I was asked a simple maths question by my daughter and wondered if I could use simple PL/SQL to work it out. It was the square root of a number plus 15 added to the square root of that number


i.e. sqrt(a+15) + sqrt(a) = 15 (knew it would be a low number so tried up to 100).

SQL>
1 DECLARE
2 c integer;
3 a integer := 0;
4 x number;
5 BEGIN
6 WHILE a < 100 LOOP
7 SELECT ((sqrt (a+15)) + (sqrt(a))) into x from dual;
8 dbms_output.put_line('loop ' || a ||' value '|| x);
9 IF (x = 15) then dbms_output.put_line('Success........');
10 END IF;
11 a := a+ 1;
12 END LOOP;
13* END;

SQL> /

set server output on

…..

loop 47 value 14.72966247441285514462090589789685682414

loop 48 value 14.865457163469280945614632626941270744

loop 49 value 15


Success........

PL/SQL procedure successfully completed.


So the square root of (49+15) added to the square root of 49 equals 15


  • Lotto generator
As the lotto syndicate was doing terrible (does it do anything else) wrote a script to generate
100 numbers and we would pick six numbers from the output in the range we wanted.

There are thousands of examples out there to do this but at least now we can use our "Lucky Dips" haha

Using TRUNC or ROUND to alter the precision as required. For example, to produce random integer values between 1 and 59 truncate the output and add 1 to the upper boundary.

TRUNC(DBMS_RANDOM.value(1,60))

1 DECLARE
2 c integer;
3 a integer := 0;
4 TYPE ref_cursor IS REF CURSOR;
5 cur REF_CURSOR;
6 BEGIN
7 WHILE a < 100 LOOP
8 OPEN CUR for 'SELECT MOD(trunc(DBMS_RANDOM.Value(1, 60)) from dual';
9 FETCH CUR into c;
10 dbms_output.put_line('value of lotto: ' || c);
11 IF (c = 0) then dbms_output.put_line('value of lotto is Zero');
12 END IF;
13 a := a+ 1;
14 END LOOP;
15 CLOSE CUR;
16* END;

SQL> /

  •  Sine wave generator
SQL> l
1 declare
2 d integer := 0;
3 e number(7,4);
4 f integer;
5 begin
6 dbms_output.put_line('Sine value');
7 loop
8 d := d + 1;
9 e := ((sin (d *(3.1412857/720))));
10 dbms_output.put_line(e);
11 exit when d >= 180;
12 end loop;
13* end;


Unfortunately, I had to put the output in Excel to see the Sine wave. I tried to use "tput" and asterisks in a shell script but it did not quite work as expected.



If anybody has any strange things that can be done in PLSQL please let me know.


Using the code from above you can easily use it as a template to do other stuff. If you wanted to show  character codes for example.

SQL> l

1 declare
2 a integer :=0;
3 x character;
4 begin
5 while a < 128 loop
6 select chr(a) into x from dual;
7 dbms_output.put_line('character ' || a ||' value '|| x);
8 a := a+1;
9 end loop;
10* end;


Variation to count rows from a table every hour for a week

  1  declare
  2                 x integer :=1;
  3                y integer;
  4                 z date;
  5                 begin
  6                while x < 168 loop
  7                 select count(*) into y from EC_MAIN.API_REQUEST_LOG where INSERTED_DTM < round(SYSDATE-(x/24),'hh');
  8                 select round(SYSDATE-(x/24),'hh') into z from dual;
  9                dbms_output.put_line( z ||     '       ' ||  y);
 10             x := x+1;
 11             end loop;
 12*         end;
 13  /


06-MAY-2019 10:00:00       4243025
06-MAY-2019 09:00:00       4229012
06-MAY-2019 08:00:00       4214438
...etc

e.g. so for 09-10am 4243025 - 4229012 = 14013 rows

Run a count for the whole days (should match the row sum for the 24 hours)  :

 1* select trunc(inserted_dtm), count(*) from ec_main.api_request_log group by trunc(inserted_dtm) order by 1
  2  /
...
06-MAY-2019 00:00:00     258371
...

Ran a double check to show hours :

 1  declare
  2      x integer :=1;
  3      y date;
  4      begin
  5      while x < 168 loop
  6      select round (SYSDATE-(x/24),'hh') into y from dual;
  7      dbms_output.put_line( x || '-- ' ||  y);
  8      x := x+1;
  9      end loop;
 10*   end;

SQL> /

1-- 02-MAY-2019 09:00:00
2-- 02-MAY-2019 08:00:00
3-- 02-MAY-2019 07:00:00
4-- 02-MAY-2019 06:00:00
5-- 02-MAY-2019 05:00:00
6-- 02-MAY-2019 04:00:00
7-- 02-MAY-2019 03:00:00
8-- 02-MAY-2019 02:00:00
9-- 02-MAY-2019 01:00:00
.....
....
164-- 25-APR-2019 14:00:00
165-- 25-APR-2019 13:00:00
166-- 25-APR-2019 12:00:00
167-- 25-APR-2019 11:00:00

PL/SQL procedure successfully completed.