Selecting from Stored Procedures and Storing SP Results into a Table - sql

I'm trying to build a couple of tables based upon the results of a few Stored procedures inside an Informix Database, that I cannot edit, and the parameter of the second SP requires values from another (will be called a few times). I have figured out what to do, but am having trouble executing it, predominantly because I cannot save my DB into a Temp table so I can then modify it.
If someone could give me some pointers, that would be great.
Some examples of things I've tried
call <stored procedure(...)> INTO TEMP db
and
create temp table name(...)
INSERT INTO namefrom storedprocedure()
and
create temp table name(...)
Select INTO name from storedprocedure()
Kind Regards,
Fox

Here's an example of a user-defined function (aka stored procedure) returning multiple values that are inserted into a temporary table. It uses the stores_demo database.
create function func1()
returning char(15), char(15);
define v_fname, v_lname char(15);
foreach select fname, lname into v_fname, v_lname from customer
return v_fname, v_lname with resume;
end foreach
end function;
create temp table tt1(fname char(15), lname char(15));
insert into tt1 execute function func1();

You can use:
SELECT * FROM TABLE(stored_procedure()) INTO TEMP p32;
This inserts the rows returned by the stored procedure into the temporary table p32.
There may be other ways to do it, but this seemed to work and is fairly straight-forward to understand.
(Tested: Informix 12.10.FC6 on a Mac running macOS 10.14.6 Mojave.)
Test schema
CREATE TABLE elements
(
atomic_number INTEGER NOT NULL PRIMARY KEY
CHECK (atomic_number > 0 AND atomic_number < 120),
symbol CHAR(3) NOT NULL UNIQUE,
name CHAR(20) NOT NULL UNIQUE,
atomic_weight DECIMAL(8, 4) NOT NULL,
pt_period SMALLINT NOT NULL
CHECK (pt_period BETWEEN 1 AND 7),
pt_group CHAR(2) NOT NULL
-- 'L' for Lanthanoids, 'A' for Actinoids
CHECK (pt_group IN ('1', '2', 'L', 'A', '3', '4', '5', '6',
'7', '8', '9', '10', '11', '12', '13',
'14', '15', '16', '17', '18')),
stable CHAR(1) DEFAULT 'Y' NOT NULL
CHECK (stable IN ('Y', 'N'))
);
INSERT INTO elements VALUES( 1, 'H', 'Hydrogen', 1.0079, 1, '1', 'Y');
INSERT INTO elements VALUES( 2, 'He', 'Helium', 4.0026, 1, '18', 'Y');
INSERT INTO elements VALUES( 3, 'Li', 'Lithium', 6.9410, 2, '1', 'Y');
INSERT INTO elements VALUES( 4, 'Be', 'Beryllium', 9.0122, 2, '2', 'Y');
INSERT INTO elements VALUES( 5, 'B', 'Boron', 10.8110, 2, '13', 'Y');
INSERT INTO elements VALUES( 6, 'C', 'Carbon', 12.0110, 2, '14', 'Y');
INSERT INTO elements VALUES( 7, 'N', 'Nitrogen', 14.0070, 2, '15', 'Y');
INSERT INTO elements VALUES( 8, 'O', 'Oxygen', 15.9990, 2, '16', 'Y');
INSERT INTO elements VALUES( 9, 'F', 'Fluorine', 18.9980, 2, '17', 'Y');
INSERT INTO elements VALUES( 10, 'Ne', 'Neon', 20.1800, 2, '18', 'Y');
INSERT INTO elements VALUES( 11, 'Na', 'Sodium', 22.9900, 3, '1', 'Y');
INSERT INTO elements VALUES( 12, 'Mg', 'Magnesium', 24.3050, 3, '2', 'Y');
INSERT INTO elements VALUES( 13, 'Al', 'Aluminium', 26.9820, 3, '13', 'Y');
INSERT INTO elements VALUES( 14, 'Si', 'Silicon', 28.0860, 3, '14', 'Y');
INSERT INTO elements VALUES( 15, 'P', 'Phosphorus', 30.9740, 3, '15', 'Y');
INSERT INTO elements VALUES( 16, 'S', 'Sulphur', 32.0650, 3, '16', 'Y');
INSERT INTO elements VALUES( 17, 'Cl', 'Chlorine', 35.4530, 3, '17', 'Y');
INSERT INTO elements VALUES( 18, 'Ar', 'Argon', 39.9480, 3, '18', 'Y');
The full table has 118 elements listed, of course.
Sample procedure
DROP PROCEDURE IF EXISTS lightweights;
CREATE PROCEDURE lightweights()
RETURNING INTEGER AS atomic_number, VARCHAR(3) AS symbol, VARCHAR(20) AS name;
DEFINE num INTEGER;
DEFINE sym VARCHAR(3);
DEFINE nam VARCHAR(20);
FOREACH SELECT e.atomic_number, e.symbol, e.name
INTO num, sym, nam
FROM elements AS e
WHERE atomic_number < 10
RETURN num, sym, nam WITH RESUME;
END FOREACH;
END PROCEDURE;
Example execution of the procedure to create a temp table
$ sqlcmd -d stores
SQL[3368]: select * from table(lightweights());
1|H |Hydrogen
2|He |Helium
3|Li |Lithium
4|Be |Beryllium
5|B |Boron
6|C |Carbon
7|N |Nitrogen
8|O |Oxygen
9|F |Fluorine
SQL[3368]: select * from table(lightweights()) into temp p32;;
SQL[3369]: select * from p32;
1|H |Hydrogen
2|He |Helium
3|Li |Lithium
4|Be |Beryllium
5|B |Boron
6|C |Carbon
7|N |Nitrogen
8|O |Oxygen
9|F |Fluorine
SQL[3370]: q;
$
Note that in sufficiently recent versions of Informix, you can replace TEMP with STANDARD or RAW to create a permanent table instead of a temporary table (and deleting TEMP is equivalent to replacing it with STANDARD). See SELECT statement > INTO table clauses.

Related

To find passengers travelling more than thrice on the same route in PL/SQL

Here I am creating three tables, one for storing the Train Info. Another for holding onto the Passenger info and the other one to hold the ticket Info.
create table T_Train_Info(
route_no integer primary key,
source varchar2(50),
destination varchar2(50)
)
create table T_Pay_Info(
pax_id integer primary key,
pax_name varchar2(50),
dob date,
gender varchar2(5)
)
create table T_Tkt_Info(
pax_id integer,
route_no integer,
journey_date date,
seat_no varchar2(5),
primary key(pax_id, route_no, journey_date)
)
In the Train_Info table, I am inserting two unique routes with the same source and destination as there can be different routes for the same source and destination. And filling the other tables in the same manner. In the ticket table, I am repeating values because I aim to find the passenger travelling thrice on the same route.
insert into T_Train_Info values(1, 'Chennai', 'Pune');
insert into T_Train_Info values(2, 'Chennai', 'Pune');
insert into T_Train_Info values(3, 'Bangalore', 'Kolkata');
insert into T_Tkt_Info values(100, 1, to_date('11/03/2022', 'DD/MM/YYYY'), 22);
insert into T_Tkt_Info values(100, 1, to_date('14/08/2022', 'DD/MM/YYYY'), 23);
insert into T_Tkt_Info values(100, 1, to_date('29/08/2022', 'DD/MM/YYYY'), 24);
insert into T_Tkt_Info values(102, 3, to_date('22/08/2022', 'DD/MM/YYYY'), 24);
insert into T_Tkt_Info values(100, 1, to_date('27/08/2022', 'DD/MM/YYYY'), 24);
insert into T_Tkt_Info values(100, 2, to_date('28/08/2022', 'DD/MM/YYYY'), 24);
insert into T_Pay_Info values(100, 'A', to_date('11/03/2022', 'DD/MM/YYYY'), 'F');
insert into T_Pay_Info values(101, 'B', to_date('23/09/2023', 'DD/MM/YYYY'), 'M');
insert into T_Pay_Info values(102, 'A', to_date('11/03/2022', 'DD/MM/YYYY'), 'F');
insert into T_Pay_Info values(103, 'D', to_date('23/09/2023', 'DD/MM/YYYY'), 'M');
insert into T_Pay_Info values(104, 'A', to_date('11/03/2022', 'DD/MM/YYYY'), 'F');
insert into T_Pay_Info values(105, 'A', to_date('23/09/2023', 'DD/MM/YYYY'), 'M');
Here's my procedure which keeps returning the error saying 'exact fetch returns more than requested number of rows' at the select statement. What am I doing wrong here?
create or replace procedure pr_pass_route_details(x in T_Train_Info.Source%type, y in T_Train_Info.Destination%type) is
pr_name T_Pay_Info.Pax_Name%type;
begin
for i in (select pax_id from t_tkt_info group by pax_id,route_no having count(*) >=3) loop
select pax_name into pr_name from t_pay_info where pax_id = i.pax_id and T_Train_Info.Source=x and T_Train_Info.Destination=y;
dbms_output.put_line(pr_name);
end loop;
end pr_pass_route_details;
i’m not sure why you’ve written a SP to do this as you can achieve this with a simple query:
SELECT
pax_id,
route_no,
COUNT(journey_date)
FROM T_Tkt_Info
GROUP BY
pax_id,
route_no
HAVING COUNT(journey_date) = 3

SQL Server : creating a top 3 view - having difficulties

This is my first time asking a SQL related question. I am having a difficult time getting this query to work.
Basically, I have a database that has 3 tables Course, Faculty and Adjunct. This query is supposed to create a view named Top3Enrollment that returns FirstName, LastName, TotalStudents, and MaxEnrollment of the 3 faculty members with the largest total enrollment for their courses, along with the highest enrollment among the classes they teach.
When attempting to write the query I get an error with selecting the column FirstName
My query:
CREATE VIEW Top3Enrollment
AS
SELECT TOP 3 PERCENT
FirstName, LastName, SUM(Enrollment), MAX(Enrollment)
FROM
Faculty
JOIN
Course ON Faculty.Faculty_ID = Course.Faculty_ID
ORDER BY
MAX(Enrollment);
The error I get is:
Msg 8120, Level 16, State 1, Procedure Top3Enrollment, Line 3 [Batch Start Line 0]
Column 'Faculty.FirstName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
My database structures:
CREATE TABLE Faculty
(
Faculty_ID VARCHAR(2),
LastName VARCHAR(20),
FirstName VARCHAR(20),
Department VARCHAR(10),
Campus VARCHAR(10)
);
INSERT INTO Faculty
VALUES ('1', 'Brown', 'Joe', 'Business', 'Kent'),
('2', 'Smith', 'John', 'Economics', 'Kent'),
('3', 'Jones', 'Sally', 'English', 'South'),
('4', 'Black', 'Bill', 'Economics', 'Deerwood'),
('5', 'Green', 'Gene', 'Business', 'South');
CREATE TABLE Course
(
Course_ID CHAR(2),
Ref_Number CHAR(5),
Faculty_ID VARCHAR(2),
Term Char(1),
BegDate SMALLDATETIME,
Enrollment INTEGER,
TotRev FLOAT
);
INSERT INTO Course
VALUES ('1', '12345', 'a', 'A', '2016-01-08 00:00:00', 24, 12345.32 ),
('2', '54321', '3', 'B', '2016-02-04 00:00:00', 18, 21435.51 ),
('3', '13524', '1', 'B', '2016-02-04 00:00:00', 7, 1256.67 ),
('4', '24653', '1', 'C', '2016-03-04 00:00:00', 29, 54421.11 ),
('5', '98765', '5', 'A', '2016-01-08 00:00:00', 35, 246753.23),
('6', '14862', '2', 'B', '2016-02-04 00:00:00', 14, 9876.87),
('7', '96032', '1', 'C', '2016-03-04 00:00:00', 8, 863159.31),
('8', '81256', '5', 'A', '2016-01-08 00:00:00', 5, 98762.14),
('9', '64321', '2', 'C', '2016-03-04 00:00:00', 23, 2965.98),
('10','90908', 'a', 'A', '2016-01-08 00:00:00', 45, 91724.02),
('11','90908', '3', 'A', '2016-01-08 00:00:00', 23, 73725.77),
('12','90908', '3', 'A', '2016-01-08 00:00:00', 16, 84224.29),
('13','90908', 'b', 'A', '2016-01-08 00:00:00', 13, 42719.82);
CREATE TABLE Adjuncts
(
Faculty_ID Char(2),
LastName VARCHAR(20),
FirstName VARCHAR(20),
Department VARCHAR(10),
Campus VARCHAR(10)
);
INSERT INTO Adjuncts
VALUES ('a', 'Rogers', 'Aaron', 'Business', 'Kent'),
('b', 'Manning', 'Peyton', 'Economics', 'North'),
('c', 'Drew', 'Maurice', 'English', 'Cecil'),
('d', 'Griffin', 'Robert', 'Music', 'Deerwood'),
('e', 'Goodell', 'Roger', 'Economics', 'South'),
('f', 'Vilma', 'Jonathan', 'Business', 'Kent');
Note:
I Understand I cannot have Order By but I wouldn't know what else to use
Added the database code
When you use aggregate functions like sum and max together with other columns you need to group your aggregations by those other columns.
Add GROUP BY like this
SELECT TOP 3 PERCENT FirstName, LastName, SUM(Enrollment), MAX(Enrollment)
FROM Faculty
JOIN Course ON Faculty.Faculty_ID = Course.Faculty_ID
GROUP BY FirstName, LastName
ORDER BY MAX(Enrollment);

ORA-01422: exact fetch returns more than requested number of rows Trigger error

What I am trying to do
BEFORE INSERT trigger involving the
PATIENT table that was designed to prohibit the assignment of two patients to the same room
where the difference in their ages is greater than 10 years. In addition, the trigger was also
supposed to prohibit two patients with allowable ages from being assigned to the same bed.
CREATE TABLE CODE
set linesize 130;
set pagesize 100;
drop table patient cascade constraints;
create table patient (pat_id char(7),
pat_name varchar(41) constraint nn_patnm not null,
pat_gender char(1),
pat_age number(2) constraint nn_patage not null,
pat_admit_dt date constraint nn_patadmdt not null,
pat_wing char(1),
pat_room# number,
pat_bed char(1),
constraint pk_pat primary key (pat_id),
constraint chk_gender check (pat_gender in ('M', 'F')),
constraint chk_age check (pat_age between 1 and 90),
constraint chk_bed check(pat_bed in ('A', 'B')));
insert into patient values ('DB77642', 'Davis, Bill', 'M', 38, '14-DEC-2017', 'A', 16, 'A');
insert into patient values ('GD72222', 'Grimes, David', 'M', 23, '14-DEC-2017', 'B', 17, 'A');
insert into patient values ('LH97384', 'Lisauckis, Hal', 'M', 28, '14-DEC-2017', 'B', 17, 'B');
insert into patient values ('RN31679', 'Robbins, Nancy', 'F', 23, '14-DEC-2017', 'A', 20, 'A');
insert into patient values ('HR32343', 'Howell, Sue', 'F', 20, '14-DEC-2017', 'A', 21, 'B');
desc patient
select * from patient;
commit;
LIST I AM USING TO TEST THE TRIGGER
column pat_name format a18
column pat_gender format a10
column pat_admit_dt format a13
column pat_wing format a8
column pat_bed format a8
set feedback on
insert into patient values ('AZ24523', 'Zhou, Alicia', 'F', 24, '14-DEC-2016', 'A', 20, 'B');
select * from patient;
insert into patient values ('JA33234', 'Abbott, John', 'M', 50, '14-DEC-2016', 'A', 16, 'B');
select * from patient;
insert into patient values ('AN32676', 'Newman, Andrew', 'M', 10, '14-DEC-2016', 'A', 16, 'B');
select * from patient;
insert into patient values ('ZZ24523', 'Zhang, Zhaoping', 'F', 38, '14-DEC-2016', 'A', 16, 'A');
select * from patient;
insert into patient values ('PS76234', 'Savant, Priyanka', 'F', 21, '14-DEC-2016', 'A', 21, 'B');
select * from patient;
insert into patient values ('SS43823', 'Sundar, Sarayu', 'F', 24, '14-DEC-2016', 'A', 21, 'A');
select * from patient;
insert into patient values ('PM43453', 'Perrin, Michael', 'M', 43, '14-DEC-2016', 'B', 22, 'A');
select * from patient;
TRIGGER
create or replace trigger patient_ins_row
before insert on patient
for each row
declare
room_age number;
difference number;
pat_name1 varchar2(41);
pat_bed1 char(1);
pat_room1 number;
ERROR_MESSAGE EXCEPTION;
BEGIN
select pat_name, pat_age, pat_room#, pat_bed into pat_name1, room_age, pat_room1, pat_bed1
from patient where pat_room# = :new.pat_room#;
if (:new.pat_bed = pat_bed1)
then DBMS_OUTPUT.PUT_LINE ('Cannot Assign ' || :new.pat_name || ' to bed already occupied ' || :new.pat_room# || 'years');
else
difference := :new.pat_age - room_age;
end if;
if (difference > 10)
then RAISE ERROR_MESSAGE;
elsif (difference < 10) then
DBMS_OUTPUT.PUT_LINE ('New Patient: ' || :new.pat_name || ' is too young: age difference is ' || difference || 'years');
else
dbms_output.put_line ('Successful insertion of ' || :new.pat_name || 'in room' || pat_room1);
END IF;
EXCEPTION
WHEN ERROR_MESSAGE THEN
RAISE_APPLICATION_ERROR (-20001, 'New Patient: ' || :new.pat_name || ' is too old: age difference is ' || difference || 'years');
END;
I keep getting the error in my title for many of the inserts. Don't know what I am doing wrong.
The problem ORA-01422 raises due to this statement :
select pat_name, pat_age, pat_room#, pat_bed
into pat_name1, room_age, pat_room1, pat_bed1
from patient where pat_room# = :new.pat_room#;
Since, your consecutive statement try to select into pat_room1 from repeatedly used :new.pat_room# with values like 16 and 21.
As an example, in the testing set when you apply
insert into patient values ('JA33234', 'Abbott, John', 'M', 50, '14-DEC-2016', 'A', 16, 'B');
the above select would give more than one row for value 16 of :new.pat_room#, and too_many_rows error will raise.

How to select from table where the table name is a local variable(informix)

I want to select from table where the table name is a local variable and the column name is another local variable but i get the following error :
The specified table ll_tb_nameis not in the database
CREATE PROCEDURE rmg_request_file ( al_task_code integer)
RETURNING integer as byte;
DEFINE ll_task_code integer;
DEFINE ll_pdf_column varchar(50);
DEFINE ll_tb_name varchar(60);
DEFINE ll_request_file REFERENCES BYTE;
SELECT pdf_column,table_name INTO ll_pdf_column ,ll_tb_name FROM rnmtask WHERE task_code = al_task_code;
FOREACH
SELECT ll_pdf_column into ll_request_file FROM ll_tb_name
return ll_request_file with resume ;
end foreach;
end procedure
Assuming you have a recent enough version of Informix (11.70), you should be able to use Dynamic SQL in SPL like this:
BEGIN;
CREATE TABLE rnmtask
(
pdf_column VARCHAR(32) NOT NULL,
table_name VARCHAR(32) NOT NULL,
task_code INTEGER NOT NULL PRIMARY KEY
);
INSERT INTO rnmtask VALUES("symbol", "elements", 1);
INSERT INTO rnmtask VALUES("name", "elements", 2);
INSERT INTO rnmtask VALUES("atomic_number", "elements", 3);
CREATE PROCEDURE rmg_request_file(al_task_code INTEGER)
RETURNING VARCHAR(255) AS colval;
DEFINE ll_pdf_column VARCHAR(50);
DEFINE ll_tb_name VARCHAR(60);
DEFINE stmt VARCHAR(255);
DEFINE result VARCHAR(255);
SELECT pdf_column, table_name
INTO ll_pdf_column, ll_tb_name
FROM rnmtask
WHERE task_code = al_task_code;
LET stmt = "SELECT " || ll_pdf_column || " FROM " || ll_tb_name;
PREPARE p FROM stmt;
DECLARE C CURSOR FOR p;
OPEN C;
WHILE sqlcode = 0
FETCH C INTO result;
IF sqlcode != 0 THEN
EXIT WHILE;
END IF;
RETURN result WITH RESUME;
END WHILE;
CLOSE C;
FREE C;
FREE p;
END PROCEDURE;
EXECUTE PROCEDURE rmg_request_file(1);
EXECUTE PROCEDURE rmg_request_file(2);
EXECUTE PROCEDURE rmg_request_file(3);
ROLLBACK;
This assumes you have a convenient Table of Elements in your database:
CREATE TABLE elements
(
atomic_number INTEGER NOT NULL PRIMARY KEY CONSTRAINT c1_elements
CHECK (atomic_number > 0 AND atomic_number < 120),
symbol CHAR(3) NOT NULL UNIQUE CONSTRAINT c2_elements,
name CHAR(20) NOT NULL UNIQUE CONSTRAINT c3_elements,
atomic_weight DECIMAL(8, 4) NOT NULL,
period SMALLINT NOT NULL
CHECK (period BETWEEN 1 AND 7),
group CHAR(2) NOT NULL
-- 'L' for Lanthanoids, 'A' for Actinoids
CHECK (group IN ('1', '2', 'L', 'A', '3', '4', '5', '6',
'7', '8', '9', '10', '11', '12', '13',
'14', '15', '16', '17', '18')),
stable CHAR(1) DEFAULT 'Y' NOT NULL
CHECK (stable IN ('Y', 'N'))
);
INSERT INTO elements VALUES( 1, 'H', 'Hydrogen', 1.0079, 1, '1', 'Y');
INSERT INTO elements VALUES( 2, 'He', 'Helium', 4.0026, 1, '18', 'Y');
INSERT INTO elements VALUES( 3, 'Li', 'Lithium', 6.9410, 2, '1', 'Y');
INSERT INTO elements VALUES( 4, 'Be', 'Beryllium', 9.0122, 2, '2', 'Y');
INSERT INTO elements VALUES( 5, 'B', 'Boron', 10.8110, 2, '13', 'Y');
INSERT INTO elements VALUES( 6, 'C', 'Carbon', 12.0110, 2, '14', 'Y');
INSERT INTO elements VALUES( 7, 'N', 'Nitrogen', 14.0070, 2, '15', 'Y');
INSERT INTO elements VALUES( 8, 'O', 'Oxygen', 15.9990, 2, '16', 'Y');
INSERT INTO elements VALUES( 9, 'F', 'Fluorine', 18.9980, 2, '17', 'Y');
INSERT INTO elements VALUES( 10, 'Ne', 'Neon', 20.1800, 2, '18', 'Y');
INSERT INTO elements VALUES( 11, 'Na', 'Sodium', 22.9900, 3, '1', 'Y');
INSERT INTO elements VALUES( 12, 'Mg', 'Magnesium', 24.3050, 3, '2', 'Y');
INSERT INTO elements VALUES( 13, 'Al', 'Aluminium', 26.9820, 3, '13', 'Y');
INSERT INTO elements VALUES( 14, 'Si', 'Silicon', 28.0860, 3, '14', 'Y');
INSERT INTO elements VALUES( 15, 'P', 'Phosphorus', 30.9740, 3, '15', 'Y');
INSERT INTO elements VALUES( 16, 'S', 'Sulphur', 32.0650, 3, '16', 'Y');
INSERT INTO elements VALUES( 17, 'Cl', 'Chlorine', 35.4530, 3, '17', 'Y');
INSERT INTO elements VALUES( 18, 'Ar', 'Argon', 39.9480, 3, '18', 'Y');
I think you should prefix every occurrence of ll_tb_name and ll_pdf_column with the # symbol, even in your SELECT INTO
Use NDS (native dynamic SQL):
EXECUTE IMMEDIATE "SELECT ll_pdf_column into ll_request_file FROM :#ll_tb_name"
USING #ll_tb_name;

How to make a join with the stored procedure result?

I want to make a join between a query and the result of stored procedure (for some reason).
my query is:
SELECT COUNT(a.values_key) AS docscount,b.main_code,b.year
FROM SP_name_should_be_here a
INNER JOIN dmr23req b
ON a.values_key = b.req_year || ',' || b.req_ser
AND a.newstateserial = 17
AND a.taskcode = 35
GROUP BY b.main_code,b.year
My stored procedure dmr_get_full_in takes two param
The answer is that you should use an 'iterator function' in the FROM clause:
FROM TABLE(FUNCTION stored_procedure(arg1, arg2)) AS alias(col1, col2, ....)
The 'alias' is not always necessary, but look hard at the column names in the output of executing the procedure directly:
EXECUTE stored_procedure(arg1, arg2)
If that contains unique column names, you'll be OK; if not, you won't and you'll need the AS alias(col1, col2, ...) notation.
Here's an analogue (more or less) to your query.
Trivial function that could be written differently, but works:
CREATE FUNCTION SimpleElements(lo INTEGER, hi INTEGER) RETURNING INTEGER AS Atomic_Number;
DEFINE an INTEGER;
FOREACH SELECT Atomic_Number
INTO an
FROM Elements
WHERE Atomic_Number BETWEEN lo AND hi
ORDER BY Atomic_Number
RETURN an WITH RESUME;
END FOREACH;
END FUNCTION;
Query using TABLE(FUNCTION stored_procedure(arg1, arg2)):
The MOD function is used as simple way of generating some groups to count, but it illustrates the notation which is the main point of the exercise.
SELECT COUNT(*) AS group_count, MOD(b.atomic_number, 3) AS mod_num
FROM TABLE(FUNCTION SimpleElements(1, 10)) AS a(Atomic_Number)
JOIN Elements AS b
ON a.atomic_number = b.atomic_number
GROUP BY mod_num
ORDER BY mod_num;
Output:
3 0
4 1
3 2
Table of Elements
CREATE TABLE elements
(
atomic_number INTEGER NOT NULL UNIQUE CONSTRAINT c1_elements
CHECK (atomic_number > 0 AND atomic_number < 120),
symbol CHAR(3) NOT NULL UNIQUE CONSTRAINT c2_elements,
name CHAR(20) NOT NULL UNIQUE CONSTRAINT c3_elements,
atomic_weight DECIMAL(8,4) NOT NULL,
stable CHAR(1) DEFAULT 'Y' NOT NULL
CHECK (stable IN ('Y', 'N'))
);
INSERT INTO elements VALUES( 1, 'H', 'Hydrogen', 1.0079, 'Y');
INSERT INTO elements VALUES( 2, 'He', 'Helium', 4.0026, 'Y');
INSERT INTO elements VALUES( 3, 'Li', 'Lithium', 6.9410, 'Y');
INSERT INTO elements VALUES( 4, 'Be', 'Beryllium', 9.0122, 'Y');
INSERT INTO elements VALUES( 5, 'B', 'Boron', 10.8110, 'Y');
INSERT INTO elements VALUES( 6, 'C', 'Carbon', 12.0110, 'Y');
INSERT INTO elements VALUES( 7, 'N', 'Nitrogen', 14.0070, 'Y');
INSERT INTO elements VALUES( 8, 'O', 'Oxygen', 15.9990, 'Y');
INSERT INTO elements VALUES( 9, 'F', 'Fluorine', 18.9980, 'Y');
INSERT INTO elements VALUES( 10, 'Ne', 'Neon', 20.1800, 'Y');
INSERT INTO elements VALUES( 11, 'Na', 'Sodium', 22.9900, 'Y');
INSERT INTO elements VALUES( 12, 'Mg', 'Magnesium', 24.3050, 'Y');
INSERT INTO elements VALUES( 13, 'Al', 'Aluminium', 26.9820, 'Y');
INSERT INTO elements VALUES( 14, 'Si', 'Silicon', 28.0860, 'Y');
INSERT INTO elements VALUES( 15, 'P', 'Phosphorus', 30.9740, 'Y');
INSERT INTO elements VALUES( 16, 'S', 'Sulphur', 32.0650, 'Y');
INSERT INTO elements VALUES( 17, 'Cl', 'Chlorine', 35.4530, 'Y');
INSERT INTO elements VALUES( 18, 'Ar', 'Argon', 39.9480, 'Y');
…