MySql if else statement, if not valid in this position - mysql

I have a vet table and a medical table with a 1 to many relationship, and the ID's are auto incremented.
CREATE TABLE vet(
vetID INT NOT NULL AUTO_INCREMENT,
vetPractice varchar(35),
Address varchar(150),
contactNumber varchar (15),
PRIMARY KEY (VetID)
);
CREATE TABLE medical(
medicalID INT NOT NULL AUTO_INCREMENT,
medication VARCHAR (200),
PRIMARY KEY (medicalID),
FOREIGN KEY (vetID) REFERENCES vet(vetID)
);
Users can enter details of a vet, i want a query to determine;
if the the vet details entered already exist, then update the foreign key in vetID(medical) with the entered vetID.
else if the vet does not exist create a new vet and update the foreign key in vetID(medical) with the newly created vetID.
I have the following query
IF EXISTS(SELECT * FROM vet WHERE vetPractice = "inputValue")
THEN
UPDATE medical set value vetID = (Select max(vetID) from vet)
ELSE
INSERT INTO vet values (null, "newVetPractice", "NewAddress", "newContactNumber", "NewEmergencyNumber" );
Then
update medical set value vetID = (Select max(vetID) from vet);
END IF;
However, i am not familiar with if else's in mySQL is this the correct format, i have seen somethings about stored procedures.
Any help would be appreciate.

I'm not really clear about your logic; but it seems like you wanted it in a stored procedure format.
CREATE PROCEDURE 'sp_Med' (IN 'in_vetPractice' VARCHAR(35))
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
BEGIN
DECLARE ckExists int;
SET ckExists = 0;
SELECT count(*) INTO ckExists from vet WHERE vetPractice = in_vetPractice;
IF (ckExists > 0) THEN
UPDATE medical SET vetID = (Select max(vetID) FROM vet WHERE vetPractice = in_vetPractice)
ELSE
INSERT INTO vet VALUES (NULL, "newVetPractice", "NewAddress", "newContactNumber", "NewEmergencyNumber");
UPDATE medical SET vetID = LAST_INSERT_ID();
END IF;
END;
Execute it like
CALL sp_Med('newPractice')

I think you have to update your query, and this is the general syntax you have to use rather tha n yours:-
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
This query will insert records if they are not present, and on presence it will update them.
So use this rather than your approach

Related

SQL max number of records

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.

Don't update if null is given in a procedure

I know an around-about way of accomplishing this but I would like to know the clean and best way to solve my problem. I am using an INSERT INTO with an ON DUPLICATE KEY UPDATE. Sometimes a value is not given but I still have to pass it into the parameter of the procedure otherwise it would fail. So I have been passing in a null value but this will update the field with nulls and I will lose data. So, I would like to "ignore" a field if it a null value gets passed into it. In other words just not update it or get the current value instead and pass that in.
I could use multiple IF statements to just check if a value is null or not but this procedure is about 20 values long and that would seem ridiculous and gratuitous. If there is a better way, I know that it can be done differently.
I'm only going to include part of my procedure for simplicity sake.
PROCEDURE `p_my_record_create`(
IN in_group varchar(255),
IN in_package varchar(255),
IN in_type enum('A', 'M'),
IN in_uid varchar(255),
IN in_member_id int(11),
IN in_first_name varchar(255)
)
BEGIN
INSERT INTO myDatabase.my_record
(`group`, `package`, `type`, `uid`, `member_id`, `first_name`)
VALUES
(in_group, in_package, in_type, in_uid, in_member_id, in_first_name)
ON DUPLICATE KEY UPDATE
`group` = in_group,
`package` = in_package,
`type` = in_type, #if this is passed in as null then I would like for it to be "ignored" or if any of them are.
`uid` = in_uid,
`client_member_id` = in_client_member_id,
`first_name` = in_first_name;
SELECT
record_id
FROM
myDatabase.my_record
WHERE
record_id = LAST_INSERT_ID();
END
If there is a simple way to accomplish this in MySQL, please enlighten me that would really help. Thanks.
PROCEDURE `p_my_record_create`(
IN in_group varchar(255),
IN in_package varchar(255),
IN in_type enum('A', 'M'),
IN in_uid varchar(255),
IN in_member_id int(11),
IN in_first_name varchar(255)
)
BEGIN
INSERT INTO myDatabase.my_record
(`group`, `package`, `type`, `uid`, `member_id`, `first_name`)
VALUES
(in_group, in_package, in_type, in_uid, in_member_id, in_first_name)
ON DUPLICATE KEY UPDATE
`group` = in_group,
`package` = COALESCE(in_package, `package`),
`type` = COALESCE(in_type, `type`),
`uid` = in_uid,
`client_member_id` = in_client_member_id,
`first_name` = COALESCE(in_first_name, `first_name`);
SELECT
record_id
FROM
myDatabase.my_record
WHERE
record_id = LAST_INSERT_ID();
END

MySQL trigger to target an attribute of a column

I am working with an overlap super/subtype relationship dealing with person(s) in my DB. What I would like to do is have the overlapping subtypes insert new rows when the supertype gains a new row. I have attached my LRD to clarify the relationship. LRD
I would like to create a trigger that inserts new person rows into the correct subtype based on the attributes employee/user in the person table.
The code I have attempted so far gives me an error upon inserting rows into person noting "employee column does not exist". I would assume this is because this code is trying to use the if statement for the subtypes where it is in fact absent.
I would appreciate any feedback.
Table Details
CREATE TABLE PERSON
(person_id int(10) not null AUTO_INCREMENT,
first_name varchar(15) not null,
last_name varchar(15) not null,
employee char(1),
participant char(1),
CONSTRAINT person_pk PRIMARY KEY (person_id))
ENGINE=InnoDB;
CREATE TABLE EMPLOYEE
(eperson_id int(10) not null AUTO_INCREMENT,
enterprise_email varchar(30),
manager_id int(10),
CONSTRAINT employee_pk PRIMARY KEY (eperson_id),
CONSTRAINT employee_fk1 FOREIGN KEY(eperson_id) REFERENCES PERSON(person_id) ON update cascade,
CONSTRAINT employee_fk2 FOREIGN KEY(manager_id) REFERENCES EMPLOYEE(eperson_id) ON update cascade)
ENGINE=InnoDB;
CREATE TABLE PARTICIPANT
(pperson_id int(10) not null AUTO_INCREMENT,
city varchar(30),
state varchar(2),
zip int(5),
sign_up_date date,
termination_date date,
CONSTRAINT participant_pk PRIMARY KEY (pperson_id),
CONSTRAINT participant_fk FOREIGN KEY(pperson_id) REFERENCES PERSON(person_id) ON update cascade)
ENGINE=InnoDB;
Trigger Code
DELIMITER //
CREATE TRIGGER subtype_creator
AFTER INSERT ON PERSON
FOR EACH ROW
BEGIN
IF (employee = ā€˜eā€™ ) THEN
INSERT INTO EMPLOYEE
SET eperson_id = NEW.person_id,
last_name = NEW.last_name,
enterprise_email = NULL,
manager_id = NULL;
IF (participant = ā€˜pā€™ )THEN
INSERT INTO PARTICIPANT
SET pperson_id = NEW.person_id,
city=NULL,
state = NULL,
zip = NULL,
sign_up_date =NULL,
termination_date = NULL;
END IF;
END IF;
END//
DELIMITER ;
This may work for you.
First off, I think to have the AUTO_INCREMENT attribute on columns EMPLOYEE.eperson_id and PARTICIPANT.pperson_id is not needed.
Since both of those columns are FOREIGN KEYS and are referencing back to the person_id column of table PERSON, they need to have, and will be getting, their values from that column through the TRIGGER anyway so no need to autoincrement them in the tables.
So I would change that.
This TRIGGER should work with populating both tables EMPLOYEE and PARTICIPANT after INSERT on table PERSON:
DELIMITER //
CREATE TRIGGER subtype_creator
AFTER INSERT ON PERSON
FOR EACH ROW
BEGIN
INSERT INTO EMPLOYEE(eperson_id, enterprise_email, manager_id)
VALUES(NEW.person_id, NULL, NULL);
INSERT INTO PARTICIPANT(pperson_id, city, state, zip, sign_up_date, termination_date)
VALUES(NEW.person_id, NULL, NULL, NULL, NULL, NULL);
END//
DELIMITER ;
Hope this helps you.
I ended up figuring out two methods to solve my issue. I ended up altering my 'employee' and 'participant' into boolean/tinyint data types.
CREATE TABLE PERSON
(person_id int(10) not null AUTO_INCREMENT,
first_name varchar(15) not null,
last_name varchar(15) not null,
employee tinyint(1),
participant tinyint(1),
CONSTRAINT person_pk PRIMARY KEY (person_id))
ENGINE=InnoDB;
After that alteration I decided to try and break up the one trigger into two. This was successful.
Type 1
DELIMITER //
CREATE TRIGGER employee_creator
AFTER INSERT ON PERSON
FOR EACH ROW
BEGIN
IF (NEW.employee = 1 ) THEN
INSERT INTO EMPLOYEE
SET eperson_id = NEW.person_id,
last_name = NEW.last_name,
enterprise_email = NULL,
manager_id = NULL;
END IF;
END//
DELIMITER ;
DELIMITER //
CREATE TRIGGER participant_creator
AFTER INSERT ON PERSON
FOR EACH ROW
BEGIN
IF (NEW.participant =0 )THEN
INSERT INTO PARTICIPANT
SET pperson_id = NEW.person_id,
city=NULL,
state = NULL,
zip = NULL,
sign_up_date =NULL,
termination_date = NULL;
END IF;
END//
DELIMITER ;
After inplementing that first option I realized the ELSEIF would allow me to not split the two and create a single trigger.
Type 2
DELIMITER //
CREATE TRIGGER employee_creator
AFTER INSERT ON PERSON
FOR EACH ROW
BEGIN
IF (NEW.employee = 1 ) THEN
INSERT INTO EMPLOYEE
SET eperson_id = NEW.person_id,
last_name = NEW.last_name,
enterprise_email = NULL,
manager_id = NULL;
ELSEIF (NEW.participant =0 )THEN
INSERT INTO PARTICIPANT
SET pperson_id = NEW.person_id,
city=NULL,
state = NULL,
zip = NULL,
sign_up_date =NULL,
termination_date = NULL;
END IF;
END//
DELIMITER ;

mysql trigger to update one field of the newly added row

I have 'users' table with the following fields:-
user_id (int, auto increment PK)
encrypted_userid (varchar 50)
user_name (varchar 50)
user_location (varchar 50)
What I want to do is create a trigger so that when values are inserted into the users table into user_name and user_location, i want to populate the encrypted_userid field with an AES_ENCRYPTED value from user_id - e.g. AES_ENCRYPT(user_id,'MYAESKEY') but only for the newly INSERTed row
Is this possible in MySQL with some kind of trigger?
Thanks in advance.
So is there a solution to my problem that will not fail etc? using a trigger - all other solutions i tried from reading other sources just didn't work.
Well all solutions revolve around LAST_INSERT_ID() because it's the only multi-user safe way to obtain auto generated ID.
First possible way, if you're very fond of triggers, is to have a separate table for auto generated sequences. Your schema will look like this
CREATE TABLE users_seq (user_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT);
CREATE TABLE users
(
user_id INT NOT NULL PRIMARY KEY DEFAULT 1,
encrypted_userid varchar(50),
user_name varchar(50),
user_location varchar(50),
FOREIGN KEY user_id_fk (user_id) REFERENCES users_seq (user_id)
);
And the trigger
DELIMITER //
CREATE TRIGGER useridinserttrigger
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO users_seq() VALUES();
SET NEW.user_id = LAST_INSERT_ID(),
NEW.encrypted_userid = AES_ENCRYPT(LAST_INSERT_ID(), 'MYAESKEY');
END//
DELIMITER ;
Second way is to leverage your existing schema but use a stored procedure
DELIMITER //
CREATE PROCEDURE insert_user(IN _name VARCHAR(50), IN _location VARCHAR(50))
BEGIN
DECLARE _id INT;
START TRANSACTION;
INSERT INTO users (user_name, user_location) VALUES(_name, _location);
SET _id = LAST_INSERT_ID();
UPDATE users
SET encrypted_userid = AES_ENCRYPT(_id, 'MYAESKEY')
WHERE user_id = _id;
COMMIT;
END//
DELIMITER ;
Sample usage:
CALL insert_user('johndoe', null);
I solved my problem using MySQL - Trigger for updating same table after insert (JCLG's entry)
CREATE TRIGGER `useridinserttrigger` BEFORE INSERT ON `users`
FOR EACH ROW BEGIN
DECLARE tmpid,tmpid2 INT(11);
SELECT user_id INTO tmpid FROM users ORDER BY user_id DESC LIMIT 1;
SET tmpid2=tmpid+1;
SET new.encrypted_userid=AES_ENCRYPT(tmpid2,'MYAESKEY');
END;

MySQL insert unique record by index of columns

I have a table:
table user(
id_user,
userName,
email,
primary key(id_user)
);
I added unique index on it:
alter table user add unique index(userName, email);
Now I have two indexs on the table:
Index:
Keyname Unique Field
PRIMARY Yes id_user
userName Yes userName, email
The task is to find the MySQL statement for fastest way to insert new unique record.
Statement should return Id_user of the new or existent record.
I'm considering these 2 options, and don't know which is better or is there some third better way to do this?:
1.
INSERT INTO `user` (`userName`, `email`)
VALUES (u1,'u1#email.me' )
ON DUPLICATE KEY Ignore
Q: Where in this statement should be specified that the required KEY for unique inserts is Keyname = uesrName?
2.
IF EXISTS(SELECT `userName`, `email` FROM user WHERE `userName` = u1 AND `email` = u1#email.me)
BEGIN
END
ELSE
BEGIN
INSERT INTO user(`userName`, `email`)
VALUES (u1, u1#email.me);
END IF;
Q: In this statement - how the index with Keyname = userName should be taken in consideration?
Thanks!
The only way to get data out of a table in MySQL is to select.
DELIMITER $$
CREATE FUNCTION ForceUser(pUsername varchar(255), pEmail varchar(255))
RETURNS integer
BEGIN
DECLARE MyId INTEGER;
/*First do a select to see if record exists:*/
/*because (username,email) is a unique key this will return null or a unique id.*/
SELECT id INTO MyId FROM user
WHERE username = pUsername
AND email = pEmail;
IF MyId IS NULL THEN
/*If not then insert the record*/
INSERT INTO user (username, email) VALUES (pUserName,pEmail);
SELECT LAST_INSERT_ID() INTO MyId;
END IF;
RETURN MyID;
END $$
DELIMITER ;
Q: Where in this statement should be specified that the required KEY for unique inserts is Keyname = uesrName?
A: MySQL already knows this, because that information is part of the table definition.
See: http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html