MySQL Stored Procedure DELETEs all Rows instead of just one - mysql

I'm trying out stored procedures for the first time, and I can't figure out what I'm doing wrong.
Here's the table definition:
CREATE TABLE `answers` (
`anid` int(11) unsigned NOT NULL auto_increment,
`uid` int(11) NOT NULL,
`dtid` int(11) NOT NULL,
`answer` text NOT NULL,
PRIMARY KEY (`anid`),
KEY `uid` (`uid`),
KEY `dtid` (`dtid`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
anid is the primary key, uid is user id, dtid is datum id, and answer is the answer provided.
Whenever I get a new answer for a given datum (question) and user id, I want to first delete any old answer to that same question by that same user, and then insert the new one.
Here's the procedure declaration:
DELIMITER //
CREATE PROCEDURE new_answer(uid INT(11),dtid INT(11),answer TEXT)
BEGIN
DELETE FROM `answers` WHERE `uid` = uid AND `dtid` = dtid;
INSERT INTO `answers` SET `uid` = uid, `dtid` = dtid, `answer` = answer;
END//
However, whenever I CALL new_answer ALL existing rows are deleted, and that one new answer is now the only row in the table.
Hope it's something simple, thanks for your help.

Rename your parameters:
DELIMITER //
CREATE PROCEDURE new_answer(p_uid INT(11),p_dtid INT(11),p_answer TEXT)
BEGIN
DELETE FROM `answers` WHERE `uid` = p_uid AND `dtid` = p_dtid;
INSERT INTO `answers` SET `uid` = p_uid, `dtid` = p_dtid, `answer` = p_answer;
END//

You should probably try naming procedure arguments different than table columns.
Anyway, it looks like all you need is a single INSERT ... ON DUPLICATE KEY UPDATE query.

I'm not familiar with stored procedures, but what about renaming your function parameters to x and y instead of the very same as the column names?

Related

MySQL trigger - Adding from a separate table

I have two tables:
CREATE TABLE `class` (
`id` int(11) NOT NULL,
`class_no` int(11) NOT NULL,
`class_title` varchar(11) NOT NULL,
`no_of_students` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `enrolment` (
`id` int(11) NOT NULL,
`ssn` varchar(11) NOT NULL,
`class_no` int(11) NOT NULL,
`grade` varchar(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
What I am trying to do is when someone enters into 'Enrolment', if the class number entered matches an entry in 'Class', e.g. class number 2 - then i want what is typed into grade on 'Enrolment' (i.e 5) to add to whatever is already in number of students (Say if it's 10). In this case, the number of students would then say 15. This is the current trigger i have, however is not adding:
DELIMITER $$
CREATE TRIGGER `after_insert_add_one` AFTER INSERT ON `enrolment` FOR EACH ROW UPDATE class
SET class.no_of_students = class.no_of_students + enrolment.grade WHERE class_no = NEW.class_no
$$
DELIMITER ;
If anyone knows i'd be grateful for the help.
You must use the NEW key instead of the name of table enrolment, try this
CREATE TRIGGER `after_insert_enrolment` AFTER INSERT ON `enrolment`
FOR EACH ROW BEGIN
UPDATE class c
SET
c.no_of_students = c.no_of_students + NEW.grade
WHERE c.class_no = NEW.class_no;
END
You’re not making changes with SET class.no_of_students = class.no_of_students + enrolment.grade if you’re not using enrolment.class_no to compare using where clause. Update it with NEW in place of enrolment if you’re using it:
DELIMITER $
CREATE TRIGGER `after_insert_add_one` AFTER INSERT ON `enrolment` FOR EACH ROW UPDATE class
SET class.no_of_students = class.no_of_students + NEW.grade WHERE class_no = NEW.class_no
$
DELIMITER ;

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 ;

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.

SELECT returning no rows using declared variable inside MySQL trigger

I am trying to perform an INSERT...SELECT to create rows in a 'tasks' table once a row is created in a 'workflow' table. (The process_index used in the workflow creation looks up those tasks required in the 'process_tasks' table then creates them in the tasks table).
The problem, however, is that after performing an insert with the process_index of 'process_one' on the workflow table, the SELECT in the trigger finds no rows. I considered that the #process_id was not being set properly, but with the alternative insert i've commented out in the trigger, it demonstrates that the #process_index is being set correctly. Can anyone advise?
Here is some simplified code to demonstrate the problem:
DROP TABLE IF EXISTS workflow;
CREATE TABLE workflow (
id INT(10) PRIMARY KEY AUTO_INCREMENT,
process_index VARCHAR(12)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS tasks;
CREATE TABLE tasks (
id INT(10) PRIMARY KEY AUTO_INCREMENT,
process_index_used VARCHAR(12),
target_field VARCHAR(12)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS process_tasks;
CREATE TABLE process_tasks (
id INT(10) PRIMARY KEY AUTO_INCREMENT,
process_index VARCHAR(12),
source_field VARCHAR(12)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO process_tasks SET process_index = 'process_one', source_field = 'alpha';
INSERT INTO process_tasks SET process_index = 'process_one', source_field = 'beta';
DROP TRIGGER IF EXISTS workflow_tasks;
DELIMITER //
CREATE TRIGGER workflow_tasks AFTER INSERT ON workflow
FOR EACH ROW BEGIN
DECLARE process_index VARCHAR(12);
SET #process_index = NEW.process_index;
-- INSERT INTO tasks (process_index_used) VALUES (#process_index);
INSERT INTO tasks (target_field) SELECT source_field FROM process_tasks WHERE process_index = #process_index;
END//
DELIMITER ;

Dependency objects MySQL

Advise the GUI tool for viewing dependent object database MySQL.
for example:
USE db;
CREATE TABLE t1(
id INT(11) NOT NULL,
`column` INT(11) DEFAULT NULL,
UNIQUE INDEX id (id)
);
CREATE TABLE t2(
id INT(11) NOT NULL,
`column` INT(11) DEFAULT NULL,
INDEX FK_t2_t1_id (`column`),
CONSTRAINT FK_t2_t1_id FOREIGN KEY (`column`)
REFERENCES t1 (id) ON DELETE RESTRICT ON UPDATE RESTRICT
);
CREATE TABLE t3(
id INT(11) NOT NULL,
`column` INT(11) DEFAULT NULL,
INDEX FK_t3_t1_id (`column`),
CONSTRAINT FK_t3_t1_id FOREIGN KEY (`column`)
REFERENCES t1 (id) ON DELETE RESTRICT ON UPDATE RESTRICT
);
DELIMITER $$
CREATE DEFINER = 'root'#'localhost'
PROCEDURE procedure1()
BEGIN
SELECT
*
FROM
db.t1;
END
$$
DELIMITER ;
I want to see which objects refer to the table t1.
In this example it are t2, t3 and procedure1
This is most likely what you are looking for. The information can be found in information_schema.
SELECT pk.constraint_schema AS PKDatabaseName
, pk.table_name AS PKObjectName
, fk_cols.column_name AS PKColumnName
, fk_cols.referenced_table_schema AS FKDatabaseName
, fk_cols.referenced_table_name AS FKObjectName
, fk_cols.referenced_column_name AS FKColumnName
, pk.constraint_name AS ConstraintName
, fk_cols.ordinal_position AS ColumnIdx
FROM information_schema.table_constraints pk
INNER JOIN information_schema.key_column_usage fk_cols
ON pk.constraint_schema = fk_cols.table_schema
AND pk.table_name = fk_cols.table_name
AND pk.constraint_name = fk_cols.constraint_name
WHERE pk.constraint_type = 'FOREIGN KEY'
Your question isn't all that clear, but it sounds like you're looking for some sort of GUI tool to do data modeling with MySQL. If that's correct, try looking at MySQL Workbench.