For each supplier(name) show the names of the items it supplies.
Files.sql
I happen to have the following data in my database
Database creation and deletion
DROP DATABASE IF EXISTS almacen;
CREATE DATABASE IF NOT EXISTS almacen;
Create and Add data to the table articulos
USE almacen;
CREATE TABLE articulos(
cod_art VARCHAR(6) PRIMARY KEY,
descripcion VARCHAR(45),
precio FLOAT,
stock INT,
caducidad BOOLEAN,
cod_prov VARCHAR(4),
observaciones VARCHAR(45)
);
INSERT INTO articulos VALUES('DR-001','Lejia',0.80,18,FALSE,'A002','Muy Toxica'),
('DR-002','Suavizante',2.40,10,FALSE,'A001','No volcar'),
('DR-003','Quitamancha',5.00,18,FALSE,'B001','Muy Toxico'),
('PA-001','Pan',1.00,35,TRUE,'B001','No tocar con las manos'),
('PA-002','Palmerita',2.10,8,TRUE,'A001','Aplicar max 5 paquetes'),
('PA-003','Napolitana',1.00,44,TRUE,'A002','Chocolate crema'),
('VE-001','Lechuga',1.50,27,TRUE,'B002','No meter en la nevera'),
('VE-002','Zanahoria',3.00,330,TRUE,'A001','No meter en la nevera');
Create and Add data to the clientes table
CREATE TABLE clientes(
cod_cliente INT AUTO_INCREMENT PRIMARY KEY,
dni VARCHAR(9),
nombreCli VARCHAR(25),
ap1 VARCHAR(35),
ap2 VARCHAR(35),
descuento INT
);
INSERT INTO clientes VALUES(null,'45098765G','Juan','Perez','Soler',5),
(null,'33456739H','Antonio','Garcia','Toro',8),
(null,'23478962S','Ramon','Gonzalez','Tamudo',0),
(null,'45765432F','Jesus','Duarte','Fortes',4),
(null,'29876098G','Gabriel','Lopez','Vazquez',2);
Create and Add data to the detallesFacturas
CREATE TABLE detallesFacturas(
nFactura INT,
cod_art VARCHAR(6),
cantidad INT,
desc_especial INT,
PRIMARY KEY (nFactura,cod_art)
);
INSERT INTO detallesFacturas VALUES(6,'DR-003',5,2),
(6,'PA-002',2,6),
(7,'DR-003',4,0),
(7,'DR-002',2,2),
(8,'VE-002',3,5),
(8,'PA-001',7,5),
(1,'DR-001',2,2),
(1,'PA-002',5,0),
(1,'DR-002',10,4),
(1,'VE-001',3,0),
(2,'DR-002',2,4),
(2,'VE-002',3,5),
(2,'PA-001',2,2),
(3,'PA-002',4,4),
(3,'VE-002',1,3),
(3,'DR-001',3,2),
(4,'PA-001',2,0),
(4,'PA-002',3,5),
(4,'VE-002',2,2),
(5,'VE-001',4,6),
(5,'PA-001',3,3);
Create and Add data to the facturas
CREATE TABLE facturas(
nFactura INT AUTO_INCREMENT PRIMARY KEY,
nCliente INT,
fecha DATE,
forma_pago VARCHAR(20)
);
INSERT INTO facturas VALUES(null,3,'2007-10-10','Contado'),
(null,2,'2007-10-11','Contado'),
(null,5,'2007-10-11','Cheque'),
(null,1,'2007-10-12','Transferencia'),
(null,5,'2007-10-14','Contado'),
(null,1,'2007-10-16','Cheque'),
(null,2,'2007-10-16','Transferencia'),
(null,4,'2007-10-17','Contado');
Create and Add data to the proveedores
CREATE TABLE proveedores(
cod_prov VARCHAR(4) PRIMARY KEY,
nombre_prov VARCHAR(30),
telefono VARCHAR(9),
ciudad VARCHAR(20),
descuento_1 INT,
descuento_2 INT
);
INSERT INTO proveedores VALUES('A001','Distribuciones Sur','956525354','Ceuta',5,10),
('A002','Todomasa SL','952875309','Malaga',3,6),
('A003','La mancha pastelera','953709912','Jaen',15,20),
('B001','Romelsa','912345762','Madrid',10,20),
('B002','Gegatur SL','933988344','Barcelona',7,13);
Cursor.sql
USE almacen;
DELIMITER $$
DROP PROCEDURE IF EXISTS art $$
CREATE PROCEDURE art()
BEGIN
DECLARE fin boolean;
DECLARE c1_codProv VARCHAR(4);
DECLARE c1_nomProv VARCHAR(30);
DECLARE c2_Articulos VARCHAR(20);
DECLARE cur_proveedor CURSOR FOR SELECT cod_prov,nombre_prov FROM proveedores;
DECLARE cur_articulos CURSOR FOR SELECT descripcion FROM articulos WHERE cod_prov=c1_codProv;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fin=true;
SET fin=0;
OPEN cur_proveedor;
FETCH cur_proveedor INTO c1_codProv,c1_nomProv;
WHILE fin=false DO
SELECT c1_nomProv;
FETCH cur_proveedor INTO c1_codProv,c1_nomProv;
OPEN cur_articulos;
FETCH cur_articulos INTO c2_Articulos;
WHILE fin=false DO
SELECT c2_Articulos;
FETCH cur_articulos INTO c2_Articulos;
END WHILE;
SET fin = false;
CLOSE cur_Articulos;
FETCH cur_proveedor INTO c1_codProv,c1_nomProv;
END WHILE;
CLOSE cur_proveedor;
END $$
DELIMITER ;
call art();
And my cursor fails me because it does not return the expected result. For example DISTRIBUCIONES SUR should give me SUAVIZANTE, PALMERITA and ZANAHORIA.
RUN EXAMPLE
I found my bug. It turns out that I had a fetch left over and that's why it cut me off and didn't give it to me correctly because it overwrote what I had before.
The fetch that was left over is the one that is commented on
USE almacen;
DELIMITER $$
DROP PROCEDURE IF EXISTS art $$
CREATE PROCEDURE art()
BEGIN
DECLARE fin boolean DEFAULT FALSE;
DECLARE c1_codProv VARCHAR(4);
DECLARE c1_nomProv VARCHAR(30);
DECLARE c2_Articulos VARCHAR(20);
DECLARE cur_proveedor CURSOR FOR SELECT cod_prov,nombre_prov FROM proveedores;
DECLARE cur_articulos CURSOR FOR SELECT descripcion FROM articulos WHERE cod_prov=c1_codProv;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fin=true;
OPEN cur_proveedor;
FETCH cur_proveedor INTO c1_codProv,c1_nomProv;
WHILE fin=FALSE DO
SELECT c1_nomProv;
# FETCH cur_proveedor INTO c1_codProv,c1_nomProv;
OPEN cur_articulos;
FETCH cur_articulos INTO c2_Articulos;
WHILE fin=FALSE DO
SELECT c2_Articulos;
FETCH cur_articulos INTO c2_Articulos;
END WHILE;
SET fin = FALSE;
CLOSE cur_Articulos;
FETCH cur_proveedor INTO c1_codProv,c1_nomProv;
END WHILE;
SET fin = FALSE;
CLOSE cur_proveedor;
END $$
DELIMITER ;
call art();
RUN EXAMPLE :
similar to StackOverflowPosting I would like to calculate the Levenshtein Distance for a m x n matrix consisting of TITLE1 and TITLE2.
My Levenshtein Functions works fine and is from here: LD
But my Question is how can I loop through the m x n in a UDF?
The Result should be a table with m x n rows with LD, TITLE1 and TITLE2.
I have done this - BUT I ALWAYS GET AN ERROR
1338 Cursor Declaration after Handler Declaration
My UDF looks like this:
BEGIN
DECLARE bDone INT;
DECLARE bDone1 INT;
DECLARE var2 varCHAR(255); -- or approriate type
DECLARE Var1 INT;
DECLARE c1Var1 VARCHAR(250);
DECLARE curs CURSOR FOR SELECT recid as BIOTIrecid, replace(replace(BIOGRAPHYTITLE," [in SCOPUS]",""),"[SIMILAR]","") as bioti FROM BIO ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
DECLARE curs1 CURSOR FOR SELECT trim(concat(scopus.Titel," ",scopus.Untertitel)) as scopusti FROM scopus ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
DROP TABLE IF EXISTS LDResults;
CREATE TABLE `LDResults` (
`BIOGRAPHYTITLE` varchar(255) DEFAULT NULL,
`recid` int(11) NOT NULL AUTO_INCREMENT,
`BIOTIrecid` int(11) default NULL,
`LD` varchar(255) DEFAULT NULL,
`ScopusTI` varchar(255) DEFAULT NULL,
PRIMARY KEY (`recid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
OPEN curs1;
SET bDone1 = 0;
#---------------- run all rows for scopusti
REPEAT
FETCH curs1 into c1var1;
#-----------------------------------------
OPEN curs;
SET bDone = 0;
#----- run all COLUMNs for biographytitle
REPEAT
FETCH curs INTO var1, var2;
INSERT INTO LDResults (`BIOGRAPHYTITLE`, `BIOTIrecid`, `LD`, `ScopusTI`) VALUES (var2, var1, LEVENSHTEIN(var2,c1var1), c1var1);
UNTIL bDone END REPEAT;
#--------------------------------------------
CLOSE curs;
UNTIL bDone1 END REPEAT;
CLOSE curs1;
SELECT * FROM LDResults;
END
Is my way to solve this problem sophisticated or could this be done on a more faster and better solution ?
Thanks for all advices.
EDIT:
I could make it with a counter here: Any comments?
BEGIN
-- DECLARE bDone INT;
-- DECLARE bDone1 INT;
DECLARE i INT;
DECLARE var2 varCHAR(255); -- or approriate type
DECLARE Var1 INT;
DECLARE cVar1 VARCHAR(250);
DECLARE curs1 CURSOR FOR SELECT trim(concat(t.Titel," ",t.Untertitel)) as scopusti FROM tscopus t ;
DECLARE curs CURSOR FOR SELECT recid as BIOTIrecid, replace(replace(BIOGRAPHYTITLE," [in SCOPUS]",""),"[SIMILAR]","") as bioti FROM tBIO ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
#DECLARE curs1 CURSOR FOR SELECT trim(concat(t.Titel," ",t.Untertitel)) as scopusti FROM tscopus t ;
#DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
DROP TABLE IF EXISTS LDResults;
CREATE TABLE `LDResults` (
`BIOGRAPHYTITLE` varchar(255) DEFAULT NULL,
`recid` int(11) NOT NULL AUTO_INCREMENT,
`BIOTIrecid` int(11) default NULL,
`LD` varchar(255) DEFAULT NULL,
`ScopusTI` varchar(255) DEFAULT NULL,
PRIMARY KEY (`recid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
OPEN curs1;
SET i = 0;
SET bDone1 = 0;
-- ---------------- run all rows for scopusti
REPEAT
FETCH curs1 into cvar1;
set i=(i+1);
-- -----------------------------------------
OPEN curs;
SET bDone = 0;
-- ----- run all COLUMNs for biographytitle
REPEAT
FETCH curs INTO var1, var2;
INSERT INTO LDResults (`BIOGRAPHYTITLE`, `BIOTIrecid`, `LD`, `ScopusTI`) VALUES (var2, var1, LEVENSHTEIN(var2,cvar1), cvar1);
UNTIL bDone END REPEAT;
-- --------------------------------------------
CLOSE curs;
UNTIL (i >= 2) END REPEAT;
CLOSE curs1;
SELECT * FROM LDResults;
END
I mean you can do it by next way useng CROSS JOIN without loops in your code. CROSS JOIN by definition return product of two tables rows result.
So you can use this result and after some data manipulation insert the result into new table like:
DROP TABLE IF EXISTS LDResults;
CREATE TABLE `LDResults` (
`BIOGRAPHYTITLE` varchar(255) DEFAULT NULL,
`recid` int(11) NOT NULL AUTO_INCREMENT,
`BIOTIrecid` int(11) default NULL,
`LD` varchar(255) DEFAULT NULL,
`ScopusTI` varchar(255) DEFAULT NULL,
PRIMARY KEY (`recid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO LDResults (`BIOGRAPHYTITLE`, `BIOTIrecid`, `LD`, `ScopusTI`)
SELECT bioti, BIOTIrecid, LEVENSHTEIN(bioti,scopusti), scopusti
FROM (
SELECT
replace(replace(BIO.BIOGRAPHYTITLE," [in SCOPUS]",""),"[SIMILAR]","") as bioti,
BIO.recid as BIOTIrecid,
trim(concat(scopus.Titel," ",scopus.Untertitel)) as scopusti
FROM scopus
CROSS JOIN BIO
) tbl;
I created two columns in student table for my database. I now need to create a cursor for the student table. I need to make use of the input parameters for start and end student Id’s to filter the results in the cursor query.
I also need to open the cursor created and check if the student has an email assigned or not. If the email is not assigned I need to update the email column to have an email assigned to the student.
Finally to why I want help:
I cannot figure out how I would write the case statements for this cursor. I have tried to think of a good way to do this and not succeeded. Please help!!
DELIMITER $
DROP PROCEDURE IF EXISTS CURSOR_DEMO$
CREATE PROCEDURE CURSOR_DEMO(start_student_id INT
,end_student_id INT
)
BEGIN
DECLARE l_table_name VARCHAR(50);
DECLARE iam_done INT DEFAULT 0;
DECLARE l_sql_stmt VARCHAR(5000);
SET #l_sql_stmt='ALTER TABLE STUDENT ADD EMAIL VARCHAR';
SELECT #l_sql_stmt;
prepare stmt from #l_sql_stmt;
execute stmt;
SET #l_sql_stmt='ALTER TABLE STUDENT ADD PHONE int(10)';
SELECT #l_sql_stmt;
prepare stmt from #l_sql_stmt;
execute stmt;
DECLARE TBL_CUR CURSOR FOR
SELECT EMAIL FROM STUDENT.TABLES WHERE TABLE_SCHEMA='MYSQLDB';
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET IAM_DONE=1;
OPEN TBL_CUR;
tbl_loop:LOOP
FETCH tbl_cur INTO l_table_name;
IF IAM_DONE = 1 THEN
LEAVE tbl_loop;
END IF;
CASE WHEN l_table_name = 'STUDENT' THEN
ELSE BEGIN END;
END CASE;
END LOOP tbl_loop;
CLOSE TBL_CUR;
END;
END$
DELIMITER ;
Is this the kind of thing you need?
/*
drop table student;
delimiter $$
CREATE TABLE `student` (
`id` int(11) NOT NULL ,
`name` char(1) NOT NULL,
`email` varchar(1),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8$$
drop table email;
delimiter $$
CREATE TABLE `email` (
`id` int(11) NOT NULL ,
`type` varchar(8) NOT NULL,
`person_id` int,
`email` varchar(1),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8$$
;
*/
DELIMITER $
DROP PROCEDURE IF EXISTS CURSOR_DEMO$
CREATE PROCEDURE CURSOR_DEMO(start_student_id INT
,end_student_id INT)
BEGIN
declare email_person_id int;
declare email_address varchar(50);
DECLARE done INT DEFAULT 0;
DECLARE CUR CURSOR FOR
SELECT person_id,email FROM sandbox.email where type = 'student';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN CUR;
cur_loop:LOOP
IF done = 1 THEN
LEAVE cur_loop;
END IF;
FETCH CUR INTO email_person_id,email_address;
update student
set email = email_address
where id = email_person_id
and email is null
;
END LOOP cur_loop;
CLOSE CUR;
commit;
END$
DELIMITER ;
truncate table student;
insert into student
values
(1,'A','1'),
(2,'B','1'),
(3,'C',null),
(4,'D',null),
(5,'E',null),
(6,'G',null),
(7,'F',null)
;
truncate table email;
insert into email
values
(1,'student',1,'a'),
(2,'student',2,'b'),
(3,'faculty',7,'z'),
(4,'student',3,'c')
;
select * from student;
call cursor_demo(1,10);
select * from student;