MySql stored procedure no data fetched - mysql

SQLFiddle
I need to loop throught my cursor and insert new values in another table.
I have two tables:
CREATE TABLE peoples
(
id int auto_increment primary key,
name varchar(20),
enabled varchar(1)
)
/
INSERT INTO peoples
(name, enabled)
VALUES
('john', 'F'),
('jane', 'T')
/
CREATE TABLE test
(
id int,
logins int
)
/
I need to select all peoples enabled = T and insert a new entry in my second table 'test'. I created a stored procedure:
CREATE PROCEDURE sp_a()
BEGIN
DECLARE p int;
DECLARE done INT DEFAULT FALSE;
DECLARE peoples_cur CURSOR FOR select p.id from peoples p where p.enabled='T';
OPEN peoples_cur;
REPEAT
FETCH peoples_cur INTO p;
IF NOT done THEN
INSERT INTO test
(id, logins)
VALUES
(p, '999');
END IF;
UNTIL done END REPEAT;
CLOSE peoples_cur;
END;
/
But i got the error:
No data - zero rows fetched, selected, or processed: CALL sp_a()
SQLFiddle

Simple way:
DROP PROCEDURE IF EXISTS sp_a;
DELIMITER $$
CREATE PROCEDURE `sp_a`()
BEGIN
INSERT INTO test (logins)
SELECT COUNT(id) AS l FROM peoples WHERE enabled = 'T';
END$$
CALL sp_a();

Related

Mysql loop trigger

I'm trying to do Closure tables with parentId so I have two tables (Subjects and SubjectsTree). When I insert a record in Subjects I need to add records in SubjectsTree for every Subjects.Id = new.ParentId. I'm trying in that way:
delimiter //
CREATE TRIGGER test AFTER INSERT ON Subjects
FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE ids INT;
DECLARE cur CURSOR FOR SELECT Id FROM Subjects inner join SubjectsTree on SubjectsTree.DescendantId = new.ParentId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO ids;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT INTO SubjectsTree VALUES (ids, new.Id);
END LOOP;
CLOSE cur;
insert into SubjectsTree values (new.Id, new.Id);
END; //
But it doesn't work just because it repeats for all records in Subjects! And when I try without loop it doesn't.
Why does this code aren't executed for each record in Subjects?
create trigger test after insert on Subjects
for each row
insert into some_test_table values ('test value');
And how can I solve this problem? Or maybe there is a better way?
Subjects table:
Id int PRI
Name longtext
ParentId int
SubjectsTree table:
AncestorId int PRI
DescendantId int PRI
Have solved this problem much easier.
drop trigger if exists test;
create trigger test after insert on Subjects
for each row
insert into SubjectsTree select AncestorId, new.Id, 1 from SubjectsTree
where DescendantId = new.ParentId union all select new.Id, new.Id, 1;

MySQL stored procedure insert multiple rows from list

How can I write a MySQL stored procedure to insert values from a variable sized list? More specifically I need to insert data into one parent table, get the ID from the insert, and then insert a variable number of child records along with the new ID into another table in a one-to-many relationship. My schema looks something like this:
TableA:
table_a_id -- Auto Increment
counter
some_data...
TableB:
table_b_id -- Auto Increment
table_a_id -- Foreign Key Constraint
some_data_from_list...
My stored procedure so far looks like this:
DELIMITER ;;
CREATE PROCEDURE insert_group_alert(
IN _some_data_a VARCHAR(255),
IN _data_list_b TEXT,
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
END;
START TRANSACTION;
INSERT INTO TableA (
some_data,
counter
)
VALUES (
_some_data_a,
1
)
ON DUPLICATE KEY UPDATE
counter = counter + 1;
SELECT last_insert_id()
INTO #newId;
LIST INSERT ???:
INSERT INTO TableB (
table_a_id, some_data
) VALUES (
#newId,
list_item,
);
END LIST INSERT ???
COMMIT;
END ;;
DELIMITER ;
My thought was to pass in a list of items to insert into table B via a comma delimited string. The values are strings. I am not sure what to do in the LIST INSERT section. Do I need a loop of some sort? Is this stored procedure I have so far the correct way to do this? I don't want to do a batch as I could potentially have hundreds or even thousands of items in the list. Is there a better solution? I am using straight JDBC.
Yes, you need a loop, in which you can use substring_index() to get the values within the list. The solution is based on the answers from this SO topic:
DELIMITER ;;
CREATE PROCEDURE insert_group_alert(
IN _some_data_a VARCHAR(255),
IN _data_list_b TEXT,
)
BEGIN
DECLARE strLen INT DEFAULT 0;
DECLARE SubStrLen INT DEFAULT 0;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
END;
START TRANSACTION;
INSERT INTO TableA (
some_data,
counter
)
VALUES (
_some_data_a,
1
) -- you do not really need this, since you do not provide an id
ON DUPLICATE KEY UPDATE
counter = counter + 1;
SELECT last_insert_id()
INTO #newId;
do_this:
LOOP
SET strLen = CHAR_LENGTH(_data_list_b);
INSERT INTO TableB (table_a_id, some_data) VALUES(#newId,SUBSTRING_INDEX(_data_list_b, ',', 1));
SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(_data_list_b, ',', 1))+2;
SET _data_list_b = MID(_data_list_b, SubStrLen, strLen); --cut the 1st list item out
IF _data_list_b = '' THEN
LEAVE do_this;
END IF;
END LOOP do_this;
COMMIT;
END ;;
DELIMITER ;

split string and insert trigger phpMyAdmin

I want to get the name in test table and split it form "to" word & insert that splitted string in abc table.
the trigger fired,but when insert data into test it generate
"#1172 - Result consisted of more than one row" error in phpMyAdmin.
please help me with this.
DROP TRIGGER IF EXISTS `split_after_insert`;
CREATE DEFINER=`root`#`localhost`
TRIGGER `split_after_insert` AFTER INSERT ON `test`
FOR EACH ROW
BEGIN
DECLARE vName varchar(50);
-- Find name of person performing the INSERT into table
SELECT SUBSTR(name,(POSITION("to" IN name)+4),20) FROM test INTO vName;
-- Insert record into abc table
INSERT INTO abc(a) VALUES (vName);
END
DROP TRIGGER IF EXISTS `j`;
CREATE DEFINER=`root`#`localhost`
TRIGGER `j` AFTER INSERT ON `test`
FOR EACH ROW
BEGIN
DECLARE vName varchar(100);
DECLARE vtemp varchar(100);
select new.name into vtemp;
-- Find name of person performing the INSERT into table
SELECT SUBSTR(vtemp,(POSITION("to" IN vtemp)+3),20) INTO vName;
-- Insert record into abc table
INSERT INTO `abc`(`a`) VALUES (vName );
END

mysql concat and insert into not working

i have a code in stored procedure which adds "PID-" to the id number, so if id number is 1, the result shoulb be PID-1. but it's not working.
Here's the code:
DROP PROCEDURE `inserproducts`//
CREATE DEFINER=`root`#`localhost` PROCEDURE `inserproducts`(pid int,pname varchar(50),pdesc varchar(50),psupp varchar(50),pdate date,pquant int)
begin
insert into products(productid,productname,proddescription,supplier,lastpurchasedate,quantityleft)
values(select concat('PID',pid,pname),pdesc,psupp,pdate,pquant));
select pid=last_insert_id();
end
how can i join insert into and concat together? Please help me with this one.
Use INSERT INTO...SELECT
insert into products(productname,proddescription,supplier,lastpurchasedate,quantityleft)
select concat('PID',pid,pname),pdesc,psupp,pdate,pquant
You can omit the column productid if it is an AUTO_INCREMENT column.
I was wondering why you need to execute select pid=last_insert_id(); when pid is an IN parameter.
UPDATE 1
DROP PROCEDURE `inserproducts`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `inserproducts`
(
pid int,
pname varchar(50),
pdesc varchar(50),
psupp varchar(50),
pdate date,
pquant int
)
begin
insert into products
(productname,
proddescription,
supplier,
lastpurchasedate,
quantityleft)
select concat('PID',pid,pname), pdesc, psupp, pdate, pquant;
select last_insert_id();
end$$
DELIMITER ;
just following up... if you specify values you don't need the select - there's probably a slight performance gain by just using values:
DROP PROCEDURE `inserproducts`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `inserproducts`
(
in pid int,
in pname varchar(50),
in pdesc varchar(50),
in psupp varchar(50),
in pdate date,
in pquant int
)
begin
insert into products
(productname, proddescription, supplier, lastpurchasedate, quantityleft)
values
(concat('PID',pid,pname), pdesc, psupp, pdate, pquant );
select last_insert_id();
end$$
DELIMITER ;
I'd leave select alone unless you actually need data from another table...

what is the error of this stored procedure

hi i m using this stored procedure
DELIMITER $$
DROP PROCEDURE IF EXISTS get_all_user_selected_children_of_preference$$
CREATE PROCEDURE get_all_user_selected_children_of_preference(
IN entity_id INT,
IN user_type INT,
IN parent_id INT
)
BEGIN
DECLARE profilepreferenceid INT;
DECLARE inpreferenceid INT;
DECLARE preference_parent_id INT;
DECLARE prefvalue VARCHAR(50);
DECLARE no_more_prefrences INT;
DECLARE element_type INT;
DECLARE preference_type INT;
DECLARE cur CURSOR for select ProfilePreferenceID,PreferenceParentID,PreferenceID,ProfilePreferenceValueAlias,ElementType,PreferenceType from xxxxx WHERE PreferenceParentID=parent_id AND EntityID=entity_id AND UserType=user_type ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_prefrences=1;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_user_selected_preference_children(
ProfilePreferenceID int(11) NOT NULL AUTO_INCREMENT,
PreferenceIDTmp INT(11),
PreferenceParentIDTmp INT(11),
ProfilePreferenceValueTmp varchar(255),
userProfileIdTmp INT(11),
elementTypeTmp INT (11),
PreferenceTypeTmp INT (11),
PRIMARY KEY (ProfilePreferenceID)
);
SET no_more_prefrences=0;
OPEN cur;
dept_loop:WHILE(no_more_prefrences=0) DO
FETCH cur INTO profilepreferenceid,preference_parent_id,inpreferenceid,prefvalue,element_type,preference_type;
IF no_more_prefrences=1 THEN
LEAVE dept_loop;
END IF;
INSERT INTO temp_user_selected_preference_children(ProfilePreferenceID,PreferenceIDTmp,PreferenceParentIDTmp,ProfilePreferenceValueTmp,userProfileIdTmp,elementTypeTmp,PreferenceTypeTmp)
VALUES (profilepreferenceid,inpreferenceid,preference_parent_id,prefvalue,entity_id,element_type,preference_type);
CALL get_all_user_selected_children_of_preference(entity_id,user_type,inpreferenceid);
END WHILE dept_loop;
CLOSE cur;
END$$
DELIMITER ;
i run it in phpmyamin , it run successfully .
then i am calling it from codeigniter
public function get_user_selected_all_sub_preferencs_of_preference($preference_id,$user_type,$profile_id)
{
$this->db->query("SET max_sp_recursion_depth=1000");
$this->db->query("CALL get_all_user_selected_children_of_preference(".$profile_id.",".$user_type.",".$preference_id.")");
$data= $this->db->query("SELECT * FROM temp_user_selected_preference_children");
$dara_arr=$data->result_array();
$this->db->query("DELETE FROM temp_user_selected_preference_children WHERE userProfileIdTmp=".$profile_id."");
if(is_array($dara_arr)&&count(array_filter($dara_arr))>0){
return $dara_arr;
}
else
{
return FALSE;
}
}
then it gives the error
A Database Error Occurred
Error Number: 1054
Unknown column 'PreferenceTypeTmp' in 'field list'
CALL get_all_user_selected_children_of_preference(65,2,1)
Filename: C:\xampp\htdocs\elephanti2\system\database\DB_driver.php
Line Number: 330
can not find what is this .
in mysql console , i describe table
please help . thanks in advance
As stated in the manual page on CREATE TABLE Syntax:
A TEMPORARY table is visible only to the current connection, and is dropped automatically when the connection is closed. This means that two different connections can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.)
Therefore, the DESCRIBE command that you ran from the MySQL command-line client refers to a different table to that which is in use by CodeIgniter.
Since the stored procedure uses CREATE TEMPORARY TABLE IF NOT EXISTS, it only creates a new table if one of the same name does not already exist on that connection: perhaps CodeIgniter previously created a table of the same name but with different columns?
You might have meant to first drop any existing table and then perform a simple create:
DROP TEMPORARY TABLE IF EXISTS temp_user_selected_preference_children;
CREATE TEMPORARY TABLE temp_user_selected_preference_children (
-- etc.