I am trying to insert large amount of data (500M rows) into MySQL. I put the whole line into a first table and use an insert after trigger. Since this inserts data to 7 different tables (for normalization purposes) I was wondering whether it would be possible to do the 7 inserts at the same time. Presently I am using MySQL 5.1 which does not allow me to create more triggers on the same table. Can you suggest me something how to increase the insert speed:
CREATE TRIGGER temptable_tr AFTER INSERT ON temp
FOR EACH ROW
BEGIN
DECLARE TR_00 INT;
DECLARE TR_1G INT;
DECLARE TR_2G INT;
DECLARE TR_3G INT;
DECLARE TR_1S INT;
DECLARE TR_2S INT;
DECLARE TR_3S INT;
/* This part repeats 7 times, instead of 00, we can put 1G, 2G, 3G, 1S, 2S, 3S
Since these 7 parts insert into seven independent tables, would it possible to run them parallely?*/
BEGIN
DECLARE T_MD5_00 CHAR(32);
DECLARE SBN_00 INT;
DECLARE S_MD5_00 CHAR(32);
DECLARE SBS_MD5_00 VARCHAR(500);
SET T_MD5_00 = SELECT MD5(NEW.tr_00) FROM DUAL;
SET TR_00 = (SELECT tr_00_id FROM trans_00 WHERE trans_00_MD5 = T_MD5_00);
SET SGN_00 = REPLACE( substring(NEW.tr_00,1,((select LOCATE('>', NEW.tr_00)-1))) ,'[*:1]','[*]') ;
SET S_MD5_00 = SELECT MD5(SGN_00) FROM DUAL;
SET SBN_00 = (SELECT subs_00_id FROM substr_00 WHERE subs_00_MD5 = S_MD5_00);
IF (TR_00 IS NULL OR SBN_00 IS NULL) THEN
IF (TR_00 IS NULL) THEN
INSERT INTO trans_00(transform_00) values(NEW.tr_00);
INSERT INTO trans_00(trans_00_MD5) values(T_MD5_00);
SET TR_00 = LAST_INSERT_ID();
END IF;
IF (SBN_00 IS NULL) THEN
INSERT INTO substr_00(substruct00,subs_00_MD5) values(SGN_00,S_MD5_00);
SET SBN_00 = LAST_INSERT_ID();
END IF;
INSERT INTO tr_subs_00(tr_00_id,subs_00_id) VALUES(TR_00,SBN_00);
END IF;
END;
.....
/* At the end collect the TR_?? ids and insert them into an other table:*/
INSERT INTO pairs(tr_00_id,tr_1G_id,tr_2G_id,tr_3G_id,tr_1S_id,tr_2S_id,tr_3S_id) VALUES(TR_00,TR_1G,TR_2G,TR_3G,TR_1S,TR_2S,TR_3S
END;
Oracle has "INSERT ALL". Doesn't MySQL have it too?
https://www.techonthenet.com/oracle/questions/insert_rows.php
Related
I am trying to create a repetition in 'cursor' that uses 'join', but it doesn't work.
Already tested without 'join' and works normally.
My code:
DECLARE hvDataAtual DATE;
DECLARE manDataAtual DATETIME;
DECLARE motCodAtual INT;
DECLARE done INT DEFAULT FALSE;
DECLARE Crs_vei_man
CURSOR FOR (
SELECT hvedatageracao, hvedatageracao, hvemotorista
FROM tableone INNER JOIN tabletwo ON hveveiculo = manveiculo
WHERE SUBSTRING(mandata, 1, 10) = SUBSTRING(hvedatageracao, 1, 10) LIMIT 10);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN Crs_vei_man;
myloop: LOOP
FETCH Crs_vei_man
INTO hvDataAtual,
manDataAtual,
motCodAtual;
-- Insert 1 row (null, null, null) ?
INSERT INTO testes VALUES(hvDataAtual, manDataAtual, motCodAtual);
IF done THEN
LEAVE myloop;
END IF;
IF motCodAtual > 0 THEN
INSERT INTO testes VALUES('hvDataAtual', 'manDataAtual', 'motCodAtual');
END IF;
END LOOP;
CLOSE Crs_vei_man;
This code is in a stored procedure.
What is happening?
I need to write a stored procedure using mysql.
In the repeat loop showing below, if I use something as:
SET VDATEI=(SELECT A.DATEI FROM STAFF_CONVENIOS A WHERE
A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
the stored procedure works well and I get a result set.
But, I need select into multiple variables. Something as:
SELECT
A.DATEI, A.DIAI, A.HORAI
INTO
VDATEI, VDIAI, VHORAI
FROM
STAFF_CONVENIOS A
WHERE
A.CONV_ID = CONVE AND A.STAFF_ID = MED
LIMIT 1;
In this case my stored procedure is broken I get no result set.
How to use select into to multiple variables into stored procedure with temporary tables?
My stored procedure is similar to:
CREATE PROCEDURE P_GETHORARIOS(
IN `MED` BIGINT,
IN `DATAREF` DATE,
IN `ESPEC` BIGINT,
IN `CONVE` BIGINT
)
BEGIN
DECLARE BDONE,BTEMP, BOCUP INT;
DECLARE DIA;
DECLARE VDIA,OK TINYINT;
DECLARE VDURACAO TINYINT;
DECLARE VDATEI DATE;
DECLARE VDIAI TINYINT;
DECLARE VHORAI TIME;
DECLARE VHORA, VHORAI,VHORAF TIME;
DECLARE CURS CURSOR FOR SELECT DIA,COALESCE(A.DURACAO,30) AS DURACAO, A.HINI FROM STAFF_ESCALA A
WHERE A.DIA=DIA;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET BDONE = 1;
DROP TEMPORARY TABLE IF EXISTS TBLRESULTS;
CREATE TEMPORARY TABLE IF NOT EXISTS TBLRESULTS (
DATA_AG DATE,
DIA TINYINT,
HORA TIME );
SET DIA=DAYOFWEEK(DATAREF);
OPEN CURS;
SET BDONE = 0;
REPEAT
SET OK=TRUE;
FETCH CURS INTO VDIA,VDURACAO,VHORAI;
-- SET VDATEI=(SELECT A.DATEI FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
SELECT A.DATEI, A.DIAI,A.HORAI INTO VDATEI, VDIAI,VHORAI FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1;
SET BTEMP=IF(VDATEI IS NULL,TRUE,FALSE);
SET OK=OK AND BTEMP ;
IF (OK) THEN
INSERT INTO TBLRESULTS VALUES (DATAREF,VDIA,VHORA);
ELSE INSERT INTO TBLRESULTS VALUES (VDATEI,VDIAI,VHORAI);
END IF;
UNTIL BDONE END REPEAT;
CLOSE CURS;
SELECT A.* FROM TBLRESULTS;
END
I have posted a sample of my problem. Here is the real stored procedure:
CREATE DEFINER=`SYSDBA`#`%` PROCEDURE `P_GETHORARIOS`(
IN `MED` BIGINT,
IN `DATAREF` DATE,
IN `ESPEC` BIGINT,
IN `CONVE` BIGINT
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE BDONE INT;
DECLARE BTEMP TINYINT;
DECLARE BOCUP TINYINT;
DECLARE DIA BIGINT;
DECLARE VDIA TINYINT;
DECLARE VDURACAO TINYINT;
DECLARE VHORA, VHORAI,VHORAF TIME;
DECLARE VMED_ID BIGINT;
DECLARE VESPEC_ID BIGINT;
DECLARE VCONV_ID BIGINT;
DECLARE OK TINYINT;
DECLARE VNOMEESPEC,VNOMEMED VARCHAR(100);
DECLARE CURS CURSOR FOR SELECT DIA,COALESCE(A.DURACAO,30) AS DURACAO, A.HINI, A.HFIM, A.STAFF_ID,B.NOME AS NOMESTAFF, A.ESPEC_ID,C.NOME AS NOMEESPEC
FROM STAFF_ESCALA A
LEFT JOIN STAFF B ON B.ID=A.STAFF_ID
LEFT JOIN ESPECIALIDADES C ON C.ID=A.ESPEC_ID
WHERE A.DIA=DIA;
-- DECLARE CURS CURSOR FOR SELECT HINI, HFIM FROM STAFF_ESCALA;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET BDONE = 1;
DROP TEMPORARY TABLE IF EXISTS TBLRESULTS;
CREATE TEMPORARY TABLE IF NOT EXISTS TBLRESULTS (
DATA_AG DATE,
DIA TINYINT,
HORA TIME,
MED_ID BIGINT,
NOME_MED VARCHAR(100),
ESPEC_ID BIGINT,
NOME_ESPEC VARCHAR(100)
);
SET DIA=DAYOFWEEK(DATAREF);
OPEN CURS;
SET BDONE = 0;
REPEAT
SET OK=TRUE;
FETCH CURS INTO VDIA,VDURACAO,VHORAI,VHORAF,VMED_ID,VNOMEMED,VESPEC_ID,VNOMEESPEC;
IF (MED IS NOT NULL) THEN
SET OK=IF(MED=VMED_ID,TRUE,FALSE) ;
END IF;
IF (ESPEC IS NOT NULL) THEN
SET OK=OK AND IF(ESPEC=VESPEC_ID,TRUE,FALSE) ;
END IF;
IF (CONVE IS NOT NULL) THEN
-- SET #EOK=(SELECT 1 FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
SELECT 1 INTO #EOK FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1;
SET BTEMP=IF(#EOK IS NULL,TRUE,FALSE);
SET OK= OK AND BTEMP ;
END IF;
IF (OK) THEN
SET VHORA=VHORAI;
IF (VDURACAO IS NULL) THEN
SET VDURACAO=30;
END IF;
WHILE (VHORA <= VHORAF) DO
SET BOCUP=(SELECT 1 FROM AGENDA_STAFF A WHERE A.DATA_MARCADA=DATAREF AND A.HORA_MARCADA=VHORA);
IF (BOCUP IS NULL) THEN
INSERT INTO TBLRESULTS VALUES (DATAREF,VDIA,VHORA,VMED_ID,VNOMEMED,VESPEC_ID,VNOMEESPEC);
END IF;
SET VHORA=ADDTIME(VHORA, VDURACAO * 100);
END WHILE;
SET VHORA=ADDTIME(VHORA, VDURACAO * (-100));
IF (VHORA < VHORAF) THEN
SET VHORA=VHORAF;
SET BOCUP=(SELECT 1 FROM AGENDA_STAFF A WHERE A.DATA_MARCADA=DATAREF AND A.HORA_MARCADA=VHORA);
IF (BOCUP IS NULL) THEN
INSERT INTO TBLRESULTS VALUES (DATAREF,VDIA,VHORA,VMED_ID,VNOMEMED,VESPEC_ID,VNOMEESPEC);
END IF;
END IF;
END IF;
UNTIL BDONE END REPEAT;
CLOSE CURS;
SELECT A.* FROM TBLRESULTS A LEFT JOIN AGENDA_STAFF B ON B.STAFF_ID=A.MED_ID AND B.HORA_MARCADA=A.HORA AND B.DATA_MARCADA=A.DATA_AG;
END
//
The problem is with the lines:
-- SET #EOK=(SELECT 1 FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1);
SELECT 1 INTO #EOK FROM STAFF_CONVENIOS A WHERE A.CONV_ID=CONVE AND A.STAFF_ID=MED LIMIT 1;
If I use "SET #EOK..." all works well.
If I use SELECT 1 INTO #EOK.. the problem appears.
More info with data
Expected result from call p_gethorarios(7,'2017-11-20',47,21)
"data_ag";"dia";"hora";"med_id";"nome_med";"espec_id";"nome_espec"
"2017-11-20";"2";"08:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"10:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"08:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"09:30:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
"2017-11-20";"2";"10:00:00";"7";"Paulo Renato Scofano";"47";"Pediatria/Neonatologia"
STAFF-ESCALA TABLE
ID;STAFF_ID;DIA;HINI;HFIM;ESPEC_ID;DURACAO;CREATION_TIME;MODIFICATION_TIME;LAST_USER_MODIF
25;7;2;08:00:00;10:00:00;50;;18/11/2017 21:44:02;;1
26;7;6;08:00:00;10:00:00;50;;18/11/2017 21:55:27;;1
27;7;4;08:00:00;10:00:00;50;;18/11/2017 21:55:27;;1
28;7;5;08:00:00;10:00:00;50;;18/11/2017 21:56:36;;1
35;7;3;08:00:00;10:00:00;47;;19/11/2017 19:10:29;;1
36;7;5;08:00:00;10:00:00;47;;19/11/2017 19:10:29;;1
38;7;2;08:00:00;10:00:00;47;;19/11/2017 19:10:29;;1
You may have to use user/session variables (the #xyz kind). The documentation does not explicitly state such, but it only shows examples with them.
https://dev.mysql.com/doc/refman/5.7/en/select-into.html
If it is an issue with the NOT FOUND handler getting triggered from something other than the cursor, you could try structuring your code something like this (very pseudocode):
FETCH
WHILE( NOT DONE )
BEGIN
DO STUFF
SET DONE = FALSE
FETCH
END
I inserted record into a table with the help of Cursor and loop after closing cursor i wrote update statement to update some record which inserted by cursor so reords not updating. but i ran query outside then records updating
my try is
drop procedure if exists kpsf_inopdormantac;
create procedure kpsf_inopdormantac(inp_branchcode varchar(6), inp_date date)
begin declare c_branchcode varchar(6);
declare c_accounttype varchar(4);
declare c_accountsubtype varchar(6);
declare c_accountno varchar(12);
declare c_lasttxndate date;
declare c_inopdate date;
declare c_temp varchar(25);
declare c1 cursor for SELECT
branchcode, accounttype, accountsubtype, accountno, lasttxndate, inoperativedate FROM accountmaster WHERE branchcode = inp_branchcode AND accounttype in ('10','11') AND accountstatus!='C' AND lasttxndate < ( SELECT date_add(inp_date,interval -24 month));
truncate table inopdormantac;
commit;
open c1;
loop1:loop fetch c1 into c_branchcode, c_accounttype, c_accountsubtype, c_accountno, c_lasttxndate, c_inopdate;
INSERT into inopdormantac (branchcode, accounttype, accountsubtype, accountno, acstatus, lasttxndate, inopdate)
VALUES
(c_branchcode, c_accounttype, c_accountsubtype, c_accountno, 'InOperative', c_lasttxndate, c_inopdate);
end loop loop1;
close c1;
set c_temp='InActive';
update inopdormantac SET acstatus = c_temp WHERE lasttxndate < ( SELECT
date_add('2015-10-06',interval -120 month));
end;
plz help me
Potentially you might be running DB instance in safe-updates mode. Please see another question which have been already answered:
MySQL error code: 1175 during UPDATE in MySQL Workbench
This question already has answers here:
How To have Dynamic SQL in MySQL Stored Procedure
(3 answers)
Closed 8 years ago.
is it possible to set a variable to an insert statement in a stored procedure?
Something like:
set variable1 = insert into table(field1, field2, field3) values(val1, val2, variable2);
If so, how should it be written?
I keep throwing errors and documentation in the wild is inconclusive.
I was going for brevity but the entire procedure is thus:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_accession`(in barcode int, in accepted varchar(11), in wt float(11,2), in wtunit varchar(3),in draw date, in chist varchar(256), in ghist varchar(256), in meds varchar(256), in diffdiag varchar(256),in diseasesus varchar(256),in volume int, in facility int, in patient int, in employ int, in compromised int, in receiving int, in test int)
BEGIN
declare accessionId int;
declare accessionTest int;
declare tkInsert varchar(256);
declare hptInsert varchar(256);
declare calInsert varchar(256);
declare pthInsert varchar(256);
declare vitdtkInsert varchar(256);
declare cnpInsert varchar(256);
if wtunit = 'lb' then set wt = convertLbKg(wt);
end if;
INSERT INTO accession(barcode_accession,accepted_accession,weight_accession,req_weight_units,draw_date_accession,cancer_history_accession,general_history_accession,medication_accession,differential_diagnosis_accession,disease_suspect_accession,volume_accession,facility_doctor_index_id_facility_doctor_index,patient_id_patient,employee_id_employee,accession_compromised_id_accession_compromised,receiving_id,accession_typeof_id_accession_typeof)
VALUES (barcode,accepted,wt,wtunit,draw,chist,ghist,meds,diffdiag,diseasesus,volume,facility,patient,employ,compromised,receiving,1);
set accessionId = last_insert_id();
set tkInsert = insert into pending(accession_facility_index,reagent_type,`status`)values(accessionId,1,'Pending');
set hptInsert = insert into pending(accession_facility_index,reagent_type,`status`)values(accessionId,2,'Pending');
set calInsert = insert into pending(accession_facility_index,reagent_type,`status`)values(accessionId,3,'Pending');
set pthInsert = insert into pending(accession_facility_index,reagent_type,`status`)values(accessionId,4,'Pending');
if test = 1 then tkInsert,calInsert;
elseif test =2 the hptInsert,pthInsert;
else pthInsert;
end if;
END
It is not very clear what you want but if your goal is to store insert's outcome (affected rows) you could use ROW_COUNT().
ROW_COUNT() returns the number of rows changed, deleted, or inserted
by the last statement if it was an UPDATE, DELETE, or INSERT.
For other statements, the value may not be meaningful.
For example:
variable1 = (select ROW_COUNT());
I think you're looking for prepared statements.
PREPARE tkInsert FROM CONCAT("insert into pending(accession_facility_index,reagent_type,`status`)values(?, 1,'Pending')";
Then you execute it with:
EXECUTE tkInsert USING accessionId;
Mysql cursor issue?
I have written a stored procedure which will travel's record from one table and insert those into 2-3 different tables
using insert statements.
Problem is that i am checking if record is not exists in table1 then I am inserting record from temptable to table1 ,table2 sequentially
,but the condition is having some problem i don't know it its always going into else part.
Code sample is as follows:
CREATE PROCEDURE `insertData`(In clientNo INT,In usedID INT)
BEGIN
declare mame varchar(100);
declare address varchar(100);
declare city varchar(50);
declare IdentityNO1 varchar(20)
declare cur1 cursor for select * from temptable;
declare continue handler for not found set done=1;
SET #clientNo = clientNO;
SET #userID = userID;
set done = 0;
open cur1;
igmLoop: loop
fetch cur1 into Name,Address,City,IdentityNO1,clientNo;
if done = 1 then leave igmLoop; end if;
//If no record exists in some records table1,table2.
IF ( (SELECT COUNT(*) FROM table1
WHERE IndentityNo=IdentityNo1
AND clientNo=#clientNo) < = 0)
INSERT INTO table1 (Name,IdentityNO) VALUES (name,IdentityNO1);
INSERT INTO table2 (Address,City) VALUES(address,city);
ELSE
INSERT INTO tblexceptional(Name,Address,City,IdentityNo)
VALUES(name,address,city,IdentityNo1);
end loop igmLoop;
close cur1;
END
There is no THEN nor END IF keywords, the procedure cannot compile.
Check this link for proper syntax of IF statement: http://dev.mysql.com/doc/refman/5.7/en/if.html
Use EXIST operator instead of (SELECT count(*)... ) <=0,
read this link to know the reason: http://sqlblog.com/blogs/andrew_kelly/archive/2007/12/15/exists-vs-count-the-battle-never-ends.aspx
IF EXISTS(
SELECT null FROM table1
WHERE IndentityNo=IdentityNo1
AND clientNo=#clientNo
)
THEN
INSERT INTO table1 (Name,IdentityNO) VALUES (name,IdentityNO1);
INSERT INTO table2 (Address,City) VALUES(address,city);
ELSE
INSERT INTO tblexceptional(Name,Address,City,IdentityNo)
VALUES(name,address,city,IdentityNo1);
END IF;
I recommend using some prefixes for procedure arguments and variable names to avoid ambiguity, for example use p_ for parameters and v_ for variables. It's hard to guess, looking at this code, which name is a column name, a variable or a procedure parameter. This can lead to mistakes and errors.
Avoid using SELECT * - this code will fail if someone will change the table structure. Explicitely list required columns in the cursor declaration:
declare cur1 cursor for
select name,Address,City,IdentityNO,clientNo
from temptable;
The corrected procedure might look like this:
CREATE PROCEDURE `insertData`(In p_clientNo INT,In p_usedID INT)
BEGIN
declare v_name varchar(100);
declare v_address varchar(100);
declare v_city varchar(50);
declare v_IdentityNO varchar(20)
declare v_clientNo int
declare cur1 cursor for
select name,Address,City,IdentityNO,clientNo
from temptable;
declare continue handler for not found set done=1;
set done = 0;
open cur1;
igmLoop: loop
fetch cur1 into v_name,v_Address,v_City,v_IdentityNO,v_clientNo;
if done = 1 then leave igmLoop; end if;
//If no record exists in some records table1,table2.
IF EXISTS( SELECT 1 FROM table1
WHERE IndentityNo = v_IdentityNo
AND clientNo = v_clientNo)
INSERT INTO table1 (Name,IdentityNO) VALUES (v_name,v_IdentityNO);
INSERT INTO table2 (Address,City) VALUES(v_address,v_city);
ELSE
INSERT INTO tblexceptional(Name,Address,City,IdentityNo)
VALUES(v_name,v_address,v_city,v_IdentityNo);
END IF;
end loop igmLoop;
close cur1;
END