MySQL create table and trigger - mysql

Can anyone help me understand what this code does?
CREATE TABLE `exams` (
`id` int(11) NOT NULL, `score` int(2) NOT NULL, `class` int(11) NOT NULL, `date` date NOT NULL, PRIMARY KEY (`class`,`date`,`id`));
CREATE TRIGGER `trig3` BEFORE INSERT ON `exams` FOR EACH ROW SET #xxx = #xxx + 1;
SET #xxx = 0;
INSERT INTO `exams` VALUES (10001,24,1,'2013-09-16'), (10005,30,1,'2013-09-16'), (10083,30,1,'2014-03-21'), (10120,26,1,'2014-03-21'), (10035,23,1,'2014-07-22'), (10005,28,2,'2014-01-23'), (10001,27,2,'2014-06-30'), (10001,25,4,'2014-01-23'), (10083,22,4,'2014-01-23'), (10120,30,4,'2014-01-23'), (10005,22,4,'2014-03-21');
SELECT #xxx;
I understand the creation of the table and the insertion of values but i don't get the rest of it.

The code seams to be a workaround way to count or check if the multi insert inserted all records or not.
SELECT #xxx;
| #xxx |
| ---- |
| 11 |
But MySQL doesn't have a native way to find that out.
see demo
A more easy MySQL code to do the same without needing the TRIGGER code and SET.
But it will require a new table structure to function.
CREATE TABLE `esami` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, `id_studente` int(11) NOT NULL
, `voto` int(2) NOT NULL
, `id_corso` int(11) NOT NULL
, `data` date NOT NULL
, UNIQUE KEY (`id_corso`,`data`,`id_studente`)
);
And the query to test if all records where inserted by the multi insert.
SELECT
COUNT(*)
FROM
esami
WHERE
id BETWEEN LAST_INSERT_ID() AND LAST_INSERT_ID() + 11;
see demo

Related

Update another table if conditions are met

as I'm working on a small app for managing metadata and I was wondering if it is possible to insert row in another table if conditions are met.
Let me follow with example: So, let's say we have table ispu_plan
CREATE TABLE `ispu_plan` (
`id` int(11) NOT NULL,
`id_jls` int(11) NOT NULL,
`id_razina_plan` int(11) NOT NULL,
`id_revizija` int(11) NOT NULL,
`naziv_plan` varchar(150) NOT NULL,
`ispu_naziv` varchar(100) NOT NULL,
`id_mjerilo` int(11) NOT NULL,
`datum_donosenja_plana` date DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and as I'm updating table ispu_plan I want to update another table (e.g. ispu_plan_updated) if certain conditions are met in ispu_plan with same rows from table ispu_plan
Using this query:
SELECT * FROM ispu_plan WHERE datum_donosenja_plana BETWEEN '2014-01-01' AND CURDATE()
I want to insert row in table ispu_plan_updated. Is something like this possible and can I insert rows in ispu_plan_updated using views?
Thank you
You can use a trigger to achieve that:
DROP TRIGGER IF EXISTS ispu_plan_trigger;
DELIMITER |
CREATE TRIGGER ispu_plan_trigger AFTER UPDATE ON ispu_plan
FOR EACH ROW BEGIN
-- example condition with update:
IF NEW.datum_donosenja_plana >= '2017-01-01' THEN
UPDATE ispu_plan_updated SET naziv_plan = 'some_value' WHERE id = NEW.id
LIMIT 1;
END IF;
END;
DELIMITER ;

insert multiple rows in a table without inserting duplicates rows

I would like to merge a table that the data comes from 2 differents databases.
I operated as described below:
1 – I have done a dump of the source database table and I get the following insert query:
INSERT INTO `t_vaccination` VALUES (242,NULL,NULL,53,1,'20030528','0','W5770-2',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23'),
(243,NULL,NULL,53,1,'20130525','0','',1,'DTP - ','A 20130521170623','2013-05-21 17:06:23'),
(1830,NULL,NULL,50,1,'20080502','3','',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23'),
(1831,NULL,NULL,50,1,'20130501','4','',1,'DTP - ','A 20130521170623','2013-05-21 17:06:23'),
(1832,NULL,NULL,50,1,'20080502','3','',0,'PAPILLOMAVIRUS - Gardasil','A 20130521170623','2013-05-21 17:06:23')
the structure of the t_vaccination table is:
CREATE TABLE `t_vaccination` (
`nIdVaccination` INT(10) UNSIGNED NOT NULL,
`nIdVaccin` INT(10) UNSIGNED NULL DEFAULT NULL,
`nIdVacProtocole` INT(10) UNSIGNED NULL DEFAULT NULL,
`nIdPatient` INT(10) UNSIGNED NOT NULL,
`nIdUtilisateur` INT(10) UNSIGNED NULL DEFAULT NULL,
`sDateInjection` VARCHAR(8) NOT NULL DEFAULT '',
`nNumInjection` VARCHAR(45) NOT NULL DEFAULT '0',
`sNumLot` VARCHAR(45) NOT NULL DEFAULT '',
`nRappel` TINYINT(4) NOT NULL DEFAULT '0',
`sLibelle` VARCHAR(255) NOT NULL DEFAULT '',
`sAction` VARCHAR(16) NOT NULL DEFAULT 'A 20080101000000',
`sDH_REPLIC` DATETIME NULL DEFAULT '2010-01-01 00:00:00',
PRIMARY KEY (`nIdVaccination`),
INDEX `NDX_t_vaccination_nIdUtilisateur` (`nIdUtilisateur`),
INDEX `NDX_t_vaccination_nIdVaccin` (`nIdVaccin`),
INDEX `NDX_t_vaccination_nIdVacProtocole` (`nIdVacProtocole`),
INDEX `NDX_t_vaccination_nIdPatient` (`nIdPatient`),
CONSTRAINT `FK_vaccination_nIdUtilisateur_utilisateur` FOREIGN KEY (`nIdUtilisateur`) REFERENCES `t_utilisateur` (`nIdUtilisateur`),
CONSTRAINT `FK_vaccination_nIdVaccin_vaccin` FOREIGN KEY (`nIdVaccin`) REFERENCES `t_vaccin` (`nIdVaccin`)
)
2 - I would like to insert all the rows in the t_vaccination table of the final database without inserting the duplicates rows. the new query run by inserting one row:
INSERT INTO t_vaccination (nIdVaccination, nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur, sDateInjection, nNumInjection, sNumLot, nRappel, sLibelle, sAction, sDH_REPLIC)
SELECT 251,41,4,53,1,'20030528','0','W5770-2',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23' FROM t_vaccination WHERE NOT EXISTS (SELECT nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur FROM t_vaccination WHERE nIdVaccin = 41 and nIdVacProtocole = 4 and nIdPatient = 53 and nIdUtilisateur =1 ) LIMIT 1
3 - Is it possible to insert rows by group by using insert where not exists because the attempts that i have done failed. here is an example of an an insert that failed:
INSERT INTO t_vaccination (nIdVaccination, nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur, sDateInjection, nNumInjection, sNumLot, nRappel, sLibelle, sAction, sDH_REPLIC)
SELECT 251,41,4,53,1,'20030528','0','W5770-2',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23' FROM t_vaccination WHERE NOT EXISTS (SELECT nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur FROM t_vaccination WHERE nIdVaccin = 41 and nIdVacProtocole = 4 and nIdPatient = 53 and nIdUtilisateur =1 ) LIMIT 1,
SELECT 243,NULL,NULL,53,1,'20130525','0','',1,'DTP - ','A 20130521170623','2013-05-21 17:06:23' FROM t_vaccination WHERE NOT EXISTS (SELECT nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur FROM t_vaccination WHERE nIdVaccin = NULL and nIdVacProtocole = NULL and nIdPatient = 53 and nIdUtilisateur =1 ) LIMIT 1
I hope for your help.
Regards
Motti
In my opinion, the simplest way to do what you want is to remove Unique keys/indexes and remove dupes or create a temporary table without those keys. Let's assume you create a temp_t_vaccination table and import all your rows in, you'll then just have to do :
INSERT INTO t_vaccination (field1, field2 ...) SELECT DISTINCT field1, fields2 ... FROM temp_vaccination
ref : http://dev.mysql.com/doc/refman/5.0/en/insert-select.html?ff=nopfpls

How to Add integer column to an String column in MySQl 5.0

I Want to add an Integer Column to a String that's because i need to generate a varchar variable with a numeric part that automatically increments. For example, P000001,P000002...
In order to do that what i am doing while creation of table i have taken an int field ID which auto_increments and i am Concatenating P with 00000 and the ID value
The Table i have created is :
CREATE TABLE tblAcceptTest(
ID int AUTO_INCREMENT NOT NULL primary key,
PatientID as CONCAT('P' , CONCAT('000000',CAST(ID as char)))
);
It Shows me the error from as keyword.
Please help
MySQL's documentation (http://dev.mysql.com/doc/refman/5.1/en/create-table.html) says, "the default value must be a constant; it cannot be a function or an expression." Why don't you just get the PatientID value afterward as part of the SELECT:
SELECT CONCAT('P', LPAD(ID, 6, 0)) AS PatientID FROM tblAcceptTest;
It looks like you want six digits after the "P", so try this for your expression:
CONCAT('P', LPAD(ID, 6, '0'))
Mysql has little support for computed columns.
Patient ID from your specification could be a char(7)
CREATE TABLE tblAcceptTest(
ID int AUTO_INCREMENT NOT NULL primary key,
PatientID char(7)
);
Then create some triggers. Note that the following insert trigger will cause issues with high concurrency servers.
DELIMITER |
CREATE TRIGGER tblAcceptTest_insert BEFORE INSERT ON tblAcceptTest
FOR EACH ROW BEGIN
DECLARE next_id INT;
SET next_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='tblAcceptTest');
SET NEW.PatientID = CONCAT('P' , RIGHT(CONCAT('000000',next_id),6)) ;
END;
|
CREATE TRIGGER tblAcceptTest_update BEFORE UPDATE ON tblAcceptTest
FOR EACH ROW BEGIN
SET NEW.PatientID = CONCAT('P' , RIGHT(CONCAT('000000',NEW.ID),6)) ;
END;
|
DELIMITER ;
You use relationships and views to achieve the same result.
CREATE TABLE `patient` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient` varchar(60) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `accepted_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient_id` int(11) NOT NULL,
`accepted` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `patient_id` (`patient_id`),
CONSTRAINT `accepted_test_ibfk_1` FOREIGN KEY (`patient_id`) REFERENCES `patient` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create or replace view accepted_test_veiw as
select CONCAT('P' , RIGHT(CONCAT('000000',patient_id),6)) patient_key
, accepted
, id accepted_test_id
, patient_id
from accepted_test ;
select * from `accepted_test_veiw`

mysql trigger not working on insert

Table: items
Create Table:
CREATE TABLE `items` (
`ite_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`itemName` varchar(40) DEFAULT NULL,
`itemNumber` int(10) unsigned NOT NULL,
PRIMARY KEY (`ite_id`),
UNIQUE KEY `itemName` (`itemName`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
delimiter |
create trigger item_beforeinsert before insert on items
for each row begin
if new.itemNumber < 50 then
set new.ite_id = null;
end if;
end;
|
now the following command doesn't cause a trigger
insert items( itemname, itemnumber) values ( 'xyz', 1 );
any help would be very much appreciated, thanks!
Your ite_ID is not null and you want to set it null with your trigger, beside that it's auto increment, so you wont be able to 'control' all the values to assign to that field, I.E it wont overwrite values
It'd be
insert INTO items( itemname, itemnumber) values ( 'xyz', 1 );
also, since you have set ite_id as NOT NULL, you can't use a set new.ite_id = null;
For auto incremented primary key fields you can pass NULL value while inserting. MySQL automatically assigns auto generated value. It is not an error setting up NULL to it BEFORE insert. And hence trigger didn't fire an error.
Example:
insert into items( ite_id, ... ) values ( null, ... );
The above statement is valid and works, since ite_id field is primary key with auto increment.

Mysql - second auto_increment col with diff behaviour

I have a proposals table like this
- ID (auto_increment)
- proposal_id
- client_id
There a way in sql that the proposal_id increments just for each client_id
example:
ID proposal_id client_id
1 1 1
2 1 2
3 2 1
4 3 1
5 2 2
6 3 2
i know i can get the last poposal_id and +1 and i add the new entry... but i dont want to do a sql instruction just to get this value... instead i want to use in a sql!
Tkz
Roberto
As I understand you wish to have proposal_id as a sequence in a continuos manner per client_id. Either you should normalize the table to split into per-client-table [tricky and not advisable] to do this or write a SELECT
I think this is what you want if using innodb (recommended) although you can simplify this with myisam
delimiter ;
drop table if exists customer;
create table customer(
cust_id int unsigned not null auto_increment primary key,
name varchar(255) unique not null,
next_proposal_id smallint unsigned not null default 0
)engine = innodb;
insert into customer (name) values ('c1'),('c2'),('c3');
drop table if exists proposal;
create table proposal(
cust_id int unsigned not null,
proposal_id smallint unsigned not null,
proposal_date datetime not null,
primary key (cust_id, proposal_id) -- composite clustered primary key
)engine=innodb;
delimiter #
create trigger proposal_before_ins_trig before insert on proposal for each row
begin
declare new_proposal_id smallint unsigned default 0;
select next_proposal_id+1 into new_proposal_id from customer
where cust_id = new.cust_id;
update customer set next_proposal_id = new_proposal_id where cust_id = new.cust_id;
set new.proposal_id = new_proposal_id;
set new.proposal_date = now();
end#
delimiter ;
insert into proposal (cust_id) values (1),(2),(1),(3),(2),(1),(1),(2);
select * from proposal;
select * from customer;
hope it helps :)
i've added the myisam version below for good measure:
drop table if exists customer;
create table customer(
cust_id int unsigned not null auto_increment primary key,
name varchar(255) unique not null
)engine = myisam;
insert into customer (name) values ('c1'),('c2'),('c3');
drop table if exists proposal;
create table proposal(
cust_id int unsigned not null,
proposal_id smallint unsigned not null auto_increment,
proposal_date datetime not null,
primary key (cust_id, proposal_id) -- composite non clustered primary key
)engine=myisam;
insert into proposal (cust_id,proposal_date) values
(1,now()),(2,now()),(1,now()),(3,now()),(2,now()),(1,now()),(1,now()),(2,now());
select * from customer;
select * from proposal order by cust_id;
I think that you could design a complicated enough query to take care of this without any non-sql code, but that's not in the spirit of what you're asking. There is not a way to create the type of field-specific increment that you're asking for as a specification of the table itself.