I have a procedure that includes a number of query
DELIMITER $$
CREATE PROCEDURE test()
BEGIN
SELECT * FROM a;
INSERT INTO b ...; //use result a query
UPDATE c ...; //use result a query
INSERT INTO d ...; //use result a query
SELECT * FROM d WHERE ...; //use result a query
INSERT INTO e ...; //use result d query
UPDATE a ...; //use result d query
END
$$
How can I get value from previous queries?
And
How can I detect if it was null?
If you are inserting one row at a time and you want the the most recent auto-incremented id, you can get the id using;
select last_insert_id()
This is documented here.
If they are inserting multiple rows, then this can be a little bit trickier.
If you want to "return" a value from a select, use variables . . . either := or into.
I would suggest you use "temp table". It is temporary tables that you can create to store your data and perform query on it as per that session.
So, it could be something like this..
DELIMITER $$ CREATE PROCEDURE test()
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS tempTable_A AS (SELECT * FROM a)
INSERT INTO b ...; //use result tempTable_A query
UPDATE c ...; //use result tempTable_A query
INSERT INTO d ...; //use result tempTable_A query
CREATE TEMPORARY TABLE IF NOT EXISTS tempTable_D AS (SELECT * FROM d) //use result tempTable_A query
INSERT INTO e ...; //use result tempTable_D query
UPDATE a ...; //use result tempTable_D query
END $$
Example could be found here:
Create a temporary table in a SELECT statement without a separate CREATE TABLE
Documentation link:
https://dev.mysql.com/doc/refman/5.7/en/create-table.html
Related
I want to execute, in a stored procedure, a certain set of statements if, in table my_table there is exactly one row with value value in column column_name. I have tried the following, but I get a syntax error:
IF ((SELECT COUNT(*) FROM my_table WHERE column_name = value) = 1) THEN
BEGIN
END;
END IF;
For context: In my procedure I create a temporary table at some point, where I store a list of values. Then later on in the procedure, I want to check if a given value is present in that temporary table.
I think you might be better to structure it more like this
BEGIN
DECLARE myCOUNT INTEGER;
SELECT COUNT(*)
INTO myCount
FROM my_table
WHERE column_name=value;
IF (myCount = 1) THEN
-- do stuff
END IF;
END;
I'm not sure what you are trying to do, but I'll guess an "upsert" -- update a record if it exists, otherwise insert a new record.
In any case, if you are trying to ensure that name is unique in my_table, then this is not the right approach at all. Instead, declare a unique index/constraint so the database ensures the data integrity:
create unique index unq_my_table_name on my_table(name);
You can then use insert . . . on duplicate key update to modify the records in the database.
In the next sample procedure, can I output the row from the queried table as a procedure resultset, and at the same time store a single field or some fields in a variable (similarly as when I use SELECT INTO)? The only way I can imagine is repeating the query.
CREATE PROCEDURE `Panel_TerminalesForm`(IN idTerminal INT)
BEGIN
declare somefield INT:
-- this select statement returns the found row as a resultset
SELECT terminales.*
FROM terminales
WHERE id_terminal = idTerminal;
-- but I also want to have here a table field inside the variable somefield
-- do some manipulation with somefield...
END;
If i understand you correctly, you need to create a temporary table, then you can manipulate the temporary the way you want.
MySQL:
CREATE PROCEDURE `Panel_TerminalesForm`(IN idTerminal INT)
BEGIN
declare somefield INT
CREATE TEMPORARY TABLE SampleTempTable
SELECT * INTO SampleTempTable FROM terminales WHERE id_terminal = idTerminal;
-- output the resultset
SELECT * FROM SampleTempTable
-- read the variables you want
SELECT field INTO somefield FROM SampleTempTable
-- Drop the temp table
DROP TEMPORARY TABLE SampleTempTable
END;
http://www.mysqltutorial.org/mysql-temporary-table/
SQL Server:
CREATE PROCEDURE `Panel_TerminalesForm`(IN idTerminal INT)
BEGIN
declare somefield INT
SELECT terminales.*
INTO #tempSample FROM terminales
WHERE id_terminal = idTerminal;
SELECT * FROM #tempSample
-- Drop the temp table
DROP TABLE #tempSample
END;
Note: Drop the temp table after using it to avoid errors.
So far I have tried many different ways of accessing the data on three tables using a stored procedure. First I tried a simple select statement :
create procedure reportCodes () begin
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers, Owner, location
WHERE Numbers.used = true AND Numbers.id=numOwner.Numbers_id AND
Numbers.id=location.Numbers_id;
end$$
(names changed to protect the guilty)
Running the stored procedure in phpmyadmin results in the first instance of the record (1 out of two ‘true’ in the test database). Running just:
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers, Owner, location
WHERE Numbers.used = true AND Numbers.id=numOwner.Numbers_id AND
Numbers.id=location.Numbers_id;
in the phpmyadmin SQL tab returns both records. Then I tried a temp table:
create procedure reportCodes () begin
CREATE TEMPORARY TABLE used_numbers AS (
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers, Owner, location
WHERE Numbers.used = true AND Numbers.id=numOwner.Numbers_id AND
Numbers.id=location.Numbers_id);
SELECT * FROM used_numbers; end$$
Returns 1 of 2 records as the procedure but both records in console. Finally I tried changing my table to a join:
CREATE PROCEDURE reportCodes()
begin
create temporary table used_numbers AS (
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers JOIN numOwner
ON Numbers.id=numOwner.Numbers_id
JOIN location ON
numOwner.Numbers_id=location.Numbers_id
WHERE Numbers.used = true
);
SELECT * FROM used_numbers; end$$
Same results as above. I’m at a loss as to why running just the SQL would show both test records but running the procedure with the exact same code only yields one.
Thanks
in your query, numOwners isn't a valid table being selected against, so something's wrong. Have you tried running your SQL in the Query window in phpMyAdmin to ensure that the EXACT same query is returning 2 rows?
I presume the "Owner" table is supposed to be "numOwner", so I've re-written the stored procedure call below. Also, I'm not sure what types of values you're storing in Numbers.used to evaluate to "TRUE". I will presume you're using a TINYINT(1), so I've altered that, as well. I hope this helps.
DELIMITER $$
USE `db`$$
DROP PROCEDURE IF EXISTS `reportCodes`$$
CREATE PROCEDURE `reportCodes`()
BEGIN
SELECT
n.serial_numb,
o.lName,
o.fName,
o.email,
l.long,
l.lat,
n.dateValidated
FROM Numbers n
INNER JOIN numOwner o ON n.id=o.Numbers_id
INNER JOIN location l ON n.id=l.Numbers_id;
WHERE n.used = 1
END$$
DELIMITER ;
i just created a stored procedure that take a parameter(example id) and copies columns related to that id from one table to another table.
How can i create stored procedure that takes sub query results as parameter,database is mysql..
This is my example..i want to pass query that select id from table to procedure..
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`sasi`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sasi`(IN idno int(4))
BEGIN
INSERT INTO user5(id,email,address,fullname,gender,phonenumber)
SELECT id,email,address,fullname,gender,phonenumber FROM user1 where id != idno;
END$$
DELIMITER ;
call sasi(4);
To pass the results of a query into your stored procedure, wrap the query in brackets.
For example:
call sasi((select max(id) from sometable where somecondition));
You must make sure the query only returns one row and one column.
Edited:
If you want to call the procedure multiple times, once for each row, change your procedure to be a FUNCTION:
CREATE FUNCTION sasi(idno int(4))
RETURNS int(4)
BEGIN
INSERT INTO user5(id,email,address,fullname,gender,phonenumber)
SELECT id,email,address,fullname,gender,phonenumber FROM user1 where id != idno;
RETURN idno;
END
Then call it like this:
select sasi(id)
from table
where ...
sasi(id) will get called for every row matching the where clause.
Can I say that one of many ways to optimize mysql is to reduce the number of queries?
If that so, can I do this:
- Select "data" => $A from table X
- Update $A from table Y
- Delete $A from table X
in one query?
You can't reduce the number of queries - they all do different things - but you could reduce the number of round trips to the database and the number of parses by wrapping it all as a PLSQL function.
However you can't select the data after you've deleted it.....but consider:
CREATE PROCEDURE s_u_d(a)
BEGIN
UPDATE tab_x SET tab_x.avalue=1 WHERE tab_x.another=a;
DELETE FROM tab_y WHERE tab_y.avalue=a;
SELECT *
FROM tab_x
WHERE tab_x.another=a;
END;
NB - you can also run multiple selects in the same procedure and handle multiple, different shaped result sets, e.g. see this page
NO,
only can combine
DELETE and SELECT
UPDATE and SELECT
This is not a proper way for mysql optimization simply
because each query come with different query cost.
And in myisam, it involve table level locking for write
Example for UPDATE and SELECT
/* this will update TABLE_A if ID in TABLE_B exist in TABLE_A */
UPDATE TABLE_A, TABLE_B
SET TABLE_A.SOME_COLUMN=TABLE_B.SOME_COLUMN
WHERE TABLE_A.ID=TABLE_B.ID
/* or */
UPDATE TABLE_A
SET SOME_COLUMN = (SELECT SOME_COLUMN_B FROM TABLE_B WHERE ... LIMIT 1)
Example for DELETE and SELECT
DELETE FROM TABLE_A WHERE TABLE_A IN(SELECT ID FROM TABLE_B)
Create a stored procedure:
DELIMITER //
create procedure empproc(in name varchar(255),in fathername varchar(255),in password varchar(255))
begin
Select * from xemp where uname = name and fname = fathername;
insert into xemp values(name,fathername,password);
end //
delimiter ;
Java Code.....
import java.sql.*;
public class StoredProcedure {
public static void main(String a[])throws Exception {
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/01jim2010","root","");
CallableStatement calstat=conn.prepareCall("{call empproc(?,?,?)}");
calstat.setString(1,"Jimit");
calstat.setString(2,"Temp");
calstat.setString(3,"Temp");
ResultSet rs = calstat.executeQuery();
conn.close();
calstat.close();
System.out.println("Your data has been inserted into table.");
}
}