I have created a stored procedure to delete data from multiple tables. my work flow as follows
I'm using mysql 5.0 and running on linux
table dependencies as follows
table C depending on table B
table B depending on table A
I want to delete a record in table A and delete all the related records in tables B and C
1 - delete all the data from detail tables (C) (with stored procedure sp_delete_from_C)
2 - delete related data immediate child table (B) (with stored procedure sp_delete_from_B)
3 - delete master table (A) (with stored procedure sp_delete_from_A)
I have wrote the following procedure
CREATE PROCEDURE sp_A_rollback(IN aId INT UNSIGNED)
READS SQL DATA
BEGIN
DECLARE b_id INT DEFAULT 0;
DECLARE cur_1 CURSOR FOR SELECT id FROM b where a_id=aId;
OPEN cur_1;
read_loop: LOOP
FETCH cur_1 INTO a_id;
CALL sp_delete_from_C(b_id);
END LOOP;
CLOSE cur_1;
CALL sp_delete_from_B(aId);
CALL sp_delete_from_A(aId);
END //
My question is,
If i run these procedures individually it works
but if u run sp_A_rollback it execute only 'sp_delete_from_C'
I dont have any idea why its not calling the other 2 sps. I'm a newbee to mysql stored procedures. please can someone help me
thanks in advance
sameera
I have no idea why you're using cursors - all you need is something like the following:
drop procedure if exists cascade_delete_tableA;
delimiter #
create procedure cascade_delete_tableA
(
in p_id int unsigned
)
begin
delete from tableC where a_id = p_id;
delete from tableB where a_id = p_id;
delete from tableA where id = p_id;
end#
delimiter ;
call the stored procedure from your application code wrapped up in a transaction.
EDIT
You'll need to use a join to delete rows from your tableC. Here's a more comprehensive example for you to study http://pastie.org/1435521. Also, your cursor loop isnt fetching into the correct variable which is why it's not working in it's current form. I would still recommend you examine the following...
-- TABLES
drop table if exists customers;
create table customers
(
cust_id smallint unsigned not null auto_increment primary key,
name varchar(255) not null
)
engine=innodb;
drop table if exists orders;
create table orders
(
order_id int unsigned not null auto_increment primary key,
cust_id smallint unsigned not null
)
engine=innodb;
drop table if exists order_items;
create table order_items
(
order_id int unsigned not null,
prod_id smallint unsigned not null,
primary key (order_id, prod_id)
)
engine=innodb;
-- STORED PROCS
drop procedure if exists cascade_delete_customer;
delimiter #
create procedure cascade_delete_customer
(
in p_cust_id smallint unsigned
)
begin
declare rows int unsigned default 0;
-- delete order items
delete oi from order_items oi
inner join orders o on o.order_id = oi.order_id and o.cust_id = p_cust_id;
set rows = row_count();
-- delete orders
delete from orders where cust_id = p_cust_id;
set rows = rows + row_count();
-- delete customer
delete from customers where cust_id = p_cust_id;
select rows + row_count() as rows;
end#
delimiter ;
-- TEST DATA
insert into customers (name) values ('c1'),('c2'),('c3'),('c4');
insert into orders (cust_id) values (1),(2),(3),(1),(1),(3),(2),(4);
insert into order_items (order_id, prod_id) values
(1,1),(1,2),(1,3),
(2,5),
(3,2),(3,5),(3,8),
(4,1),(4,4),
(5,2),(5,7),
(6,4),(6,8),(6,9),
(7,5),
(8,3),(8,4),(8,5),(8,6);
-- TESTING
/*
select * from customers where cust_id = 1;
select * from orders where cust_id = 1;
select * from order_items oi
inner join orders o on oi.order_id = o.order_id and o.cust_id = 1;
call cascade_delete_customer(1);
*/
Related
So I have the following table:
CREATE TABLE Hospital_MedicalRecord(
recNo CHAR(5),
patient CHAR(9),
doctor CHAR(9),
enteredOn DATE NOT NULL,
diagnosis VARCHAR(50) NOT NULL,
treatment VARCHAR(50),
PRIMARY KEY (recNo, patient),
FOREIGN KEY (patient) REFERENCES Hospital_Patient(NINumber),
FOREIGN KEY (doctor) REFERENCES Hospital_Doctor(NINumber)
);
I want to make it so there are never more that 65,535 medical records for a single patient. Am I supposed to make a new statement or should I implement it in the table above. I can post the patient table if needed.
You would typically use a before insert trigger for this, that raises an error if the number of records for a patient reached the limit and a new insert is attempted:
delimiter //
create trigger Trg_Hospital_MedicalRecord
before insert on Hospital_MedicalRecord
for each row
begin
if (
select count(*) from Hospital_MedicalRecord where patient = new.patient
) = 65535 then
set msg = concat('Patient ', new.patient, ' cannot have more than 65535 records');
signal state '45000' set message_text = msg;
end if;
end
//
delimiter ;
I would assume that you should not allow a patient to be updated on an existing record. But if this may happen, then you also need a before update trigger (with the very same code).
Consider the following...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table(id SERIAL PRIMARY KEY, user_id INT NOT NULL);
INSERT INTO my_table (user_id)
SELECT 1
FROM (SELECT 1) x
LEFT
JOIN (SELECT user_id FROM my_table GROUP BY user_id HAVING COUNT(*) >=3) y
ON y.user_id = 1
WHERE y.user_id IS NULL
LIMIT 1;
This limits INSERTS to 3 per user_id.
Challenge:
Create a method to set "auto_increment" values for tables in a non-sequential way.
The goal is to override the "auto_increment" mechanism and allow the function "LAST_INSERT_ID()" to continue working as expected (returning an INT), so that no changes are needed in software side.
My Solution
The method I found is based on an auxiliary table (unique_id), that stores values available to be assigned. Values are then selected randomly, and removed from the tables as used. When the table gets empty, a new set of ID's is created.
This example is working as expected, but with one problem.
Tables for the demo:
CREATE TABLE `unique_id` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=100;
CREATE TABLE `test_unique_id` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
Defined a stored procedure and a function:
DELIMITER $$
DROP PROCEDURE IF EXISTS `UNIQUE_ID_REFILL`$$
CREATE PROCEDURE UNIQUE_ID_REFILL()
BEGIN
DECLARE a INT Default 0 ;
simple_loop: LOOP
SET a=a+1;
INSERT INTO unique_id (id) values(null);
IF a=100 THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
END $$
DROP FUNCTION IF EXISTS `UNIQUE_ID_GET`$$
CREATE FUNCTION UNIQUE_ID_GET()
RETURNS INT(11)
MODIFIES SQL DATA
BEGIN
DECLARE new_id INT(11);
DECLARE unique_id_count INT(11);
SET new_id = 0;
SELECT COUNT(*) INTO unique_id_count FROM unique_id;
IF unique_id_count=0 THEN
CALL UNIQUE_ID_REFILL();
END IF;
SELECT id INTO new_id FROM unique_id ORDER BY RAND() LIMIT 1;
DELETE FROM unique_id WHERE id = new_id;
RETURN new_id;
END $$
Created a Trigger on the destination table (test_unique_id):
CREATE TRIGGER test_unique_id__unique_id BEFORE INSERT ON test_unique_id
FOR EACH ROW
SET NEW.id = UNIQUE_ID_GET();
The solution is getting the random ID's as expected:
INSERT INTO test_unique_id(name) VALUES ('A'),('B'),('C');
Creates the rows:
id name
154 'A'
129 'B'
173 'C'
The Problem
The main problem is that LAST_INSERT_ID() stops working... and the software side is broken:
SELECT LAST_INSERT_ID();
0
Any ideas on how to solve this problem? or any other different approach to the challenge?
Thank you very much.
I'm having some trouble with my stored procedure.
I'm trying to write a "create script" with a "stored procedure" that takes an input "n" in the interval of 0-100000.
After user input i want all the information to go into a new Table called "T".
SELECT * FROM T;
I want it to print:
+----+------------+----------+---------------+---+----+-----+
| Id | First Namne| Last Name| Street Address| No| Zip| City|
+----+------------+----------+---------------+---+----+-----+
The street number should be in the range of 1-300.
Zip should be 5 numbers and can't start with 0.
Every row must be unique even if i remove the ID column.
I've made 3 files:
1. Contains 500 unique First Names
2. Contains 500 unique Last Names
3. Contains 335 unique Adresses
My take was to make the new table "t" to take in a random first name and a random last name. It would take in 1 adress 300 times and make the adress no go up 300 times then continue to the next adress, that way all my rows would be unique.enter code here
This is how far i came before my brain crashed:
/*
* Sets database to users
*/
USE users;
/*
* Removes tables if exists
*/
DROP TABLE IF EXISTS t;
DROP TABLE IF EXISTS first_names;
DROP TABLE IF EXISTS last_names;
DROP TABLE IF EXISTS street_names;
/*
* Creating new tables
*/
-- Create table t
CREATE TABLE t(
player_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(20) NOT NULL,
last_name VARCHAR (20) NOT NULL,
street_name VARCHAR (30) NOT NULL,
street_number SMALLINT(3) NOT NULL,
zip MEDIUMINT(5) NOT NULL,
city VARCHAR(20) NOT NULL
);
-- Create table first_names
CREATE TABLE first_names (
first_name_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(20) NOT NULL
);
Source C:\Database\Inlamning\first_names.txt
-- Create table last_names
CREATE TABLE last_names (
last_name_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(20) NOT NULL
);
Source C:\Database\Inlamning\last_names.txt
-- Create table street_names
CREATE TABLE street_names (
street_name_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
street_name VARCHAR(30) NOT NULL
);
Source C:\Database\Inlamning\street_names.txt
/*
* Create PRECEDURE "generate_adress"
*/
DROP PROCEDURE IF EXISTS generate_adress;
DELIMITER $$
CREATE PROCEDURE generate_adress(x INT, fn VARCHAR(20), ln VARCHAR(20), sn VARCHAR (30), snno SMALLINT(3), zi MEDIUMINT(5), ci VARCHAR(20))
BEGIN
SELECT (SELECT CONCAT("generate_adress", NOW())) as "Start";
IF (x > 100000) THEN
SELECT ("Max allowed adresser are 100000, value set to 100000") AS "Number of address:";
SET x = 100000;
END IF;
INSERT INTO "t" (first_name, last_name, street_name, street_number, zip, city)
END$$
DELIMITER ;
CALL generate_adress(1000);
SELECT * FROM t;
Help would be much appreciated!
I suggest the following high level pseudo-code, you can then code it as in line sql or SP with cursors, and/or use temp tables or save code by using subqueries, etc.:
1- cross join first and last names, this will give you the 250000 rows of all possible unique names
2- cross join street names with a table containing numbers from 1 to 300, this will give you the 100500 rows of unique addresses
3- Select n rows from the first cross join ordered by RAND() (temp table T1)
4- Select n rows from the second cross join ordered by RAND() (temp table T2)
5- Join T1 and T2 on row number and that will be your result of n unique rows
The ZIP codes can be worked out as 100000 * RAND()
EDIT
pseudocode a bit more elaborated:
set #rownum=0
create table t1 as
(
select #rownum:=#rownum+1 as rownum, x.*
from (select firstname, lastname from firstnames, lastnames) as x limit 10
) x1
set #rownum=0
create table t2 as
(
select #rownum:=#rownum+1 as rownum, x.*
from (select number, streetname from streetnames, numbers) as x limit 10
) x1
select * from t1 join t2 on t1.rownum=t2.rownum
I ended up with this solution! Thank you for the help I recieved!
/*************************************************
*
* Andreas Ekman Newton Java 2
*
* CREATE -- Source C:\Database\Test\CREATE.txt
* File: -- Source C:\Database\Inlamning\first_names.txt - 358 Unique ID
* File: -- Source C:\Database\Inlamning\last_names.txt - 359 Unique ID
* File: -- Source C:\Database\Inlamning\street_names.txt - 335 Unique ID
* File: -- Source C:\Database\Inlamning\street_numbers.txt - 300 Uniqe ID
* File: -- Source C:\Database\Inlamning\zips.txt - 7 Uniqe ID
* File: -- Source C:\Database\Inlamning\cities.txt - 7 Uniqe ID
*
**************************************************/
/*
* Setting database to "Gamers"
*/
USE Gamers;
/*
* Creating new tables
*/
-- Create table t
DROP TABLE IF EXISTS t;
CREATE TABLE t(
player_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(20) NOT NULL,
last_name VARCHAR (20) NOT NULL,
street_name VARCHAR (30) NOT NULL,
street_number SMALLINT(3) NOT NULL,
zip MEDIUMINT(5) NOT NULL,
city VARCHAR(20) NOT NULL
);
-- Create table first_names
DROP TABLE IF EXISTS first_names;
CREATE TABLE first_names (
first_name_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(20) NOT NULL
);
Source C:\Database\Inlamning\first_names.txt
-- Create table last_names
DROP TABLE IF EXISTS last_names;
CREATE TABLE last_names (
last_name_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(20) NOT NULL
);
Source C:\Database\Inlamning\last_names.txt
-- Create table street_names
DROP TABLE IF EXISTS street_names;
CREATE TABLE street_names (
street_name_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
street_name VARCHAR(30) NOT NULL
);
Source C:\Database\Inlamning\street_names.txt
-- Create table street_numbers
DROP TABLE IF EXISTS street_numbers;
CREATE TABLE street_numbers (
street_number_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
street_number SMALLINT(30) NOT NULL
);
Source C:\Database\Inlamning\street_numbers.txt
-- Create table zip
DROP TABLE IF EXISTS zips;
CREATE TABLE zips (
zip_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
zip MEDIUMINT(5) NOT NULL
);
Source C:\Database\Inlamning\zips.txt
-- Create table citites
DROP TABLE IF EXISTS cities;
CREATE TABLE cities (
city_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
city VARCHAR(20) NOT NULL
);
Source C:\Database\Inlamning\cities.txt
/*
* Create PRECEDURE "generate_adress"
*/
DROP PROCEDURE IF EXISTS generate_adress;
DELIMITER $$
-- CREATE PROCEDURE generate_adress(x INT)
CREATE PROCEDURE generate_adress(x INT)
BEGIN
-- Declaring variables
DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 1;
DECLARE k INT DEFAULT 1;
DECLARE fname VARCHAR(20) DEFAULT 'error';
DECLARE lname VARCHAR(20) DEFAULT 'error';
DECLARE stname VARCHAR(30) DEFAULT 'error';
DECLARE stno SMALLINT(3) DEFAULT '0';
DECLARE zi MEDIUMINT(5) DEFAULT '0';
DECLARE ci VARCHAR(20) DEFAULT 'error';
-- Visualizing the start of generator
SELECT (SELECT CONCAT("generate_adress", NOW())) as "Start generator!";
-- Check call ID, max allowed input is 100000
IF (x > 100000) THEN
SELECT ("Max allowed addresses are 100000, value set to 100000") AS "Number of adresses";
SET x = 100000;
END IF;
-- Loop for creating inserts to table "t"
WHILE (i <=x) DO
-- Setting random value for numbers in the 100's range
SET #random = FLOOR((RAND()*300 +1));
-- Setting random value for numbers in the up to 7's range
SET #randomci = FLOOR((RAND()*7 +1));
-- Getting random name from first_names table
SET fname = (SELECT first_name FROM first_names WHERE first_name_id = #random); -- SELECT (fname) as 'first_name';
-- Getting random last name from last_names table
SET lname = (SELECT last_name FROM last_names WHERE last_name_id = #random);
-- Getting street name by ID = k
SET stname = (SELECT street_name FROM street_names WHERE street_name_id = k);
-- Getting street name by ID = j
SET stno = (SELECT street_number FROM street_numbers WHERE street_number_id = j);
-- Getting a random area code from zips table
SET zi = (SELECT zip FROM zips WHERE zip_id = #randomci);
-- Getting a random city from cities table
SET ci = (SELECT city FROM cities WHERE city_id = #randomci);
-- Insert data to table called "t"
INSERT INTO t (first_name, last_name, street_name, street_number, zip, city) VALUES(fname, lname, stname, stno, zi, ci);
-- Setting the "call generate_adress" counter to tick
SET i = i+1;
-- Setting street_name and street_number tick
SET j = j+1;
-- Variable counter
IF (j > 300) THEN
SET j = 1;
SET k = k+1;
END IF;
-- End of while loop
END WHILE;
-- Visualizing the start of generator
SELECT (SELECT CONCAT("generate_adress", NOW())) as "Stop generator!";
-- End of create procedure
END$$
-- Setting default Delimiter to ;
DELIMITER ;
-- Call command, innout "x" for creating number of x's adresses
CALL generate_adress(1000);
-- View all created addresses
SELECT * FROM t;
I need to know that how to fetch a record from table which consist of certain records varies with different id named[sponser_id]
from the above img i give you a simple scenario..say for ex: the rounded person is said to be the person A.
when Person A loggin into his/her acc. It should show how many members(count) are coming under his/her control.
Mysql table has columns like
sponser_id refers to the parent user_id.
sponser_id varies with parent_user who referred them.
Here my question is, How to retrieve the count of members under this particular person..
I have only user_id & sponser_id columns alone in my table.
Here is an MLM tree I once implemented here, I think I deleted the answer cuz it was not appreciated :)
I always do these with Stored Procedures. A member can have a parent, like your setup.
The output showed downline sales and a commission at 5%
Schema
-- drop table member;
create table member
( memberId int not null auto_increment primary key,
handle varchar(255) not null,
parentId int null,
key (parentId)
);
-- drop table sales
create table sales
( -- sales of Products abbreviated
id int auto_increment primary key,
memberId int not null,
amount decimal(10,2) not null,
saleDate datetime not null,
CONSTRAINT `fk_member`
FOREIGN KEY (memberId)
REFERENCES member(memberId)
);
insert member(handle,parentId) values ('Johnny Two-Thumbs',null); -- 1
insert member(handle,parentId) values ('Jake the Enforcer',null); -- 2
insert member(handle,parentId) values ('Innocent Kim',2); -- 3
insert member(handle,parentId) values ('Karen',2); -- 4
insert member(handle,parentId) values ('Henry',2); -- 5
insert member(handle,parentId) values ('Shy Sales-less Sam',5); -- 6
insert member(handle,parentId) values ('Pete',5); -- 7
insert member(handle,parentId) values ('Iowa Mom',7); -- 8
insert member(handle,parentId) values ('Albuquerque Agoraphobiac',7); -- 9
insert sales (memberId,amount,saleDate) values (2,1,'2015-01-01');
insert sales (memberId,amount,saleDate) values (5,10,'2015-01-20');
insert sales (memberId,amount,saleDate) values (5,15.50,'2015-01-22');
insert sales (memberId,amount,saleDate) values (7,101.12,'2015-02-01');
insert sales (memberId,amount,saleDate) values (7,201.12,'2015-03-01');
insert sales (memberId,amount,saleDate) values (7,109,'2015-04-01');
insert sales (memberId,amount,saleDate) values (7,45,'2015-05-01');
insert sales (memberId,amount,saleDate) values (8,111,'2015-04-20');
insert sales (memberId,amount,saleDate) values (8,99.99,'2015-05-22');
insert sales (memberId,amount,saleDate) values (9,0.04,'2015-06-20');
insert sales (memberId,amount,saleDate) values (9,1.23,'2015-06-24');
Stored Procedure
drop procedure if exists showAllDownlineSales;
DELIMITER $$
create procedure showAllDownlineSales
(
theId int
)
BEGIN
-- theId parameter means i am anywhere in hierarchy of membership
-- and i want all downline sales
-- return 1 row: sales amt for downlines, and that amt * 5%, and total children (including children-of-children)
declare bDoneYet boolean default false;
declare working_on int;
declare theCount int;
declare downlineSales decimal(10,2);
declare commish decimal(10,2);
CREATE temporary TABLE xxFindSalesxx
(
memberId int not null,
processed int not null, -- 0 for not processed, 1 for processed
salesTotal decimal(10,2) not null
);
set bDoneYet=false;
insert into xxFindSalesxx (memberId,processed,salesTotal) select theId,0,0;
while (!bDoneYet) do
select count(*) into theCount from xxFindSalesxx where processed=0;
if (theCount=0) then
-- found em all
set bDoneYet=true;
else
-- one not processed yet, insert its children for processing
SELECT memberId INTO working_on FROM xxFindSalesxx where processed=0 limit 1;
insert into xxFindSalesxx (memberId,processed,salesTotal)
select memberId,0,0 from member
where parentId=working_on;
-- update xxFindSalesxx
-- join sales
-- on sales.memberId=xxFindSalesxx.memberId
-- set salesTotal=sum(sales.amount)
-- where xxFindSalesxx.memberId=working_on;
update xxFindSalesxx
set salesTotal=(select ifnull(sum(sales.amount),0) from sales where memberId=working_on)
where xxFindSalesxx.memberId=working_on;
-- mark the one we "processed for children" as processed
update xxFindSalesxx set processed=1 where memberId=working_on;
end if;
end while;
delete from xxFindSalesxx where memberId=theId;
select sum(salesTotal),count(*) into downlineSales,theCount from xxFindSalesxx;
drop table xxFindSalesxx;
select downlineSales,round(downlineSales*0.05,2) as commission,theCount; -- there is your answer, 1 row
END
$$
DELIMITER ;
Test it
call showAllDownlineSales(2); -- 693.00 34.69 7
call showAllDownlineSales(1); -- null null 0
call showAllDownlineSales(5); -- 668.50 33.43 4
I have temporary memory tables A and B. each contain 1 column of integer values
I need to find all values which are in A but not in B.
The problem is that its very slow due to the fact (I think) that memory tables use hash and not ordered keys.
How can I perform it efficiently? Currently I'm using
SELECT val FROM tableA WHERE val NOT IN (SELECT val FROM tableB)
The definition of each table :
CREATE TABLE tableA (val INT, PRIMARY KEY USING HASH (val)) ENGINE = MEMORY;
select
a.val
from
tableA a
left outer join tableB b on a.val = b.val
where
b.val is null;
some additional testing on 250K rows reveals that there's not much between them:
call load_test_data();
call test_memory_tables_hash(); -- 0:00:00.597
call test_memory_tables_hash(); -- 0:00:00.362
call load_test_data();
call test_memory_tables_btree(); -- 0:00:00.460
call test_memory_tables_btree(); -- 0:00:00.429
full testing script:
drop table if exists tableA;
create table tableA
(
val int unsigned not null primary key
)
engine=innodb;
drop table if exists tableB;
create table tableB
(
val int unsigned not null primary key
)
engine=innodb;
drop procedure if exists load_test_data;
delimiter #
create procedure load_test_data()
proc_main:begin
declare i int unsigned default 0;
declare rnd int unsigned default 0;
declare max int unsigned default 250000;
truncate table tableA;
truncate table tableB;
set autocommit = 0;
while i < max do
if i % 2 = 0 then insert into tableA values (i); end if;
if i % 3 = 0 then insert into tableB values (i); end if;
set i = i+1;
end while;
commit;
end proc_main #
delimiter ;
drop procedure if exists test_memory_tables_hash;
delimiter #
create procedure test_memory_tables_hash()
proc_main:begin
create temporary table mem_tableA
(
val int unsigned not null, index using hash(val)
)
engine=memory select val from tableA;
create temporary table mem_tableB
(
val int unsigned not null, index using hash(val)
)
engine=memory;
insert into mem_tableA select val from tableA;
insert into mem_tableB select val from tableB;
select
a.val
from
mem_tableA a
left outer join mem_tableB b on a.val = b.val
where
b.val is null
order by
a.val desc
limit 64;
drop temporary table if exists mem_tableA;
drop temporary table if exists mem_tableB;
end proc_main #
delimiter ;
delimiter ;
drop procedure if exists test_memory_tables_btree;
delimiter #
create procedure test_memory_tables_btree()
proc_main:begin
create temporary table mem_tableA
(
val int unsigned not null, index using btree(val)
)
engine=memory select val from tableA;
create temporary table mem_tableB
(
val int unsigned not null, index using btree(val)
)
engine=memory;
insert into mem_tableA select val from tableA;
insert into mem_tableB select val from tableB;
select
a.val
from
mem_tableA a
left outer join mem_tableB b on a.val = b.val
where
b.val is null
order by
a.val desc
limit 64;
drop temporary table if exists mem_tableA;
drop temporary table if exists mem_tableB;
end proc_main #
delimiter ;
call load_test_data();
call test_memory_tables_hash();
-- 0:00:00.597
call test_memory_tables_hash();
-- 0:00:00.362
call load_test_data();
call test_memory_tables_btree();
-- 0:00:00.460
call test_memory_tables_btree();
-- 0:00:00.429