Mysql column count doesn't Match value count (but it does!) - mysql

I am running the following procedure in mysql:
create procedure addSavingAccount(id int(10), account_number varchar(10))
begin
insert into saving values(id,'savings', account_number, 0);
end //
However, when I try to call it, it gives me this error:
mysql> call addSavingAccount(103, 'B505');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
I checked on anything that could be linked to it, including triggers. But everything seems like it should be working. Here is my list of triggers:
create trigger balance_change_saving after update on saving for each row
begin
if old.balance != new.balance
then
insert into balance_update_history values(null, 'saving', new.account_number, old.balance, new.balance,
(SELECT NOW()), (select USER()));
end if;
end//
create trigger balance_insert_saving after insert on saving for each row
begin
insert into balance_update_history values(null, 'saving', new.account_number, 0, new.balance, (select now()),
(select user()));
end //
create trigger balance_delete_saving after delete on saving for each row
begin
insert into balance_update_history values(null, null, null, old.balance, null,
(SELECT NOW()), (select USER()));
end //
And here is where I define the table:
create table if not exists saving(account_number varchar(10) , customer_id int(10), balance decimal(8,2), primary key(account_number));
I'd just really like to to figure this out.

There are three columns based on your table create statement, not four. (what is the last 0 in that insert?)
Also, in the procedure, it appears that your insert values are out-of-order relative to the table creation order? So you can either rearrange the insert values to match the table, OR specify the columns with the insert.

Related

inserting values from another table via a TRIGGER in MYSQL

I need to create a trigger when a new record is added to the "plan" table, a record is automatically created in the "results" table.
Table "Plan" has columns:
IdService
IdEmployee
Groupe
Date
Type (varchar)
Table "Results" has columns:
IdService
IdEmployee
IdClient
Date
Result (varchar)
But the idClient must be taken from table "Clients", corresponding to the group number added to the plan. Thus, the trigger should create not one, but several rows in the result table (since there can be several clients in one group)
I am attaching my code, but there is obviously an error in it
CREATE DEFINER = CURRENT_USER TRIGGER `mydb`.`Plan_AFTER_INSERT` AFTER INSERT ON `Plan` FOR EACH ROW
BEGIN
insert into results (Result, idClient, Date, idService, idEmployee)
values ('в процессе',idClient = (Select idClient from Clients
where Clients.Groupe = Plan.New.Groupe),
NEW.Date, NEW.idService, NEW.idEmployee);
END
It is quite OK only your subquery has ti return only one row, so it is better to limit it
DELIMITER //
CREATE DEFINER = CURRENT_USER TRIGGER `mydb`.`Plan_AFTER_INSERT` AFTER INSERT ON `Plan` FOR EACH ROW
BEGIN
insert into results (Result, idClient, Date, idService, idEmployee)
values ('в процессе',(Select idClient from Clients
where Clients.Groupe = New.Groupe ORDER BY idClient LIMIT 1),
NEW.Date, NEW.idService, NEW.idEmployee);
END//
DELIMITER ;

Script/workflow insert not exist and auto increment

I create a script/workflow exportation/importation from 2 system.
I have Table1 {id, name, description}
I want to create a script (not a procedure). I could (I didnt succed) adding procedure into my workflow. (create and delete at the end)
id is auto increment
I cant change the table
I can be sure that between the time I start execution of my script and the end, there will not be an insertion of one of my items into the database.
The script insert {name,description} but I want to NOT insert if the element (name or name and description) is there.
BASE QUERY :
INSERT INTO TABLE1 (name,description) VALUES ('itemX','this is item X')
BASE Script :
Use database1;
BEGIN;
SELECT * FROM TABLE1 ;
SELECT * FROM TABLE3 ;
INSERT INTO TABLE1 (name,description) VALUES ('itemX','this is item X');
set #idTable1 = LAST_INSERT_ID();
INSERT INTO TABLE3 (idTable1,idTable2) VALUES (#idTable1,1);
INSERT INTO TABLE3 (idTable1,idTable2) VALUES (#idTable1,2);
SELECT * FROM TABLE1 ;
SELECT * FROM TABLE3 ;
ROLLBACK;
I want to protect the multiple insertion on TABLE1. But without changing the table.
Maybe I did it wrong
I tried IF but not working outside procedure.
I tried IGNORE (valid only if id is the same, but never the same, its
auto increment)
I tried WHEN
I tried ON DUPLICATE KEY
Because of #idTable1, I will need change the " set #idTable1 = LAST_INSERT_ID();" if I doesnt have if else. But if my item is the only one with the same "name", I can get this instead of last_insert_id.
I opted for creating procedure before my "BEGIN" and removed them at the end of the script.
Just create the table with name as primary key, then be sure that you take care of the key capitalization (uppercase or lowercase) to avoid duplicates.
CREATE TABLE TABLE1(
id INT AUTO_INCREMENT,
name CHAR(30),
description CHAR(100),
PRIMARY KEY (name)
)
create unique constraint on name field if possible.
Otherwise, create trigger before insert in order to ignore duplicate insertion.
Trigger for checking duplicate on two fields a and b:
delimiter //
drop trigger if exists aborting_trigger //
create trigger aborting_trigger before insert on t
for each row
begin
set #found := false;
select true into #found from t where a=new.a and b=new.b;
if #found then
signal sqlstate '45000' set message_text = 'duplicate insert';
end if;
end //
delimiter ;
The trigger here provides feature similar to unique constraint. After creation you should use INSERT IGNORE or INSERT ...ON DUPLICATE KEY UPDATE

Mysql Trigger to insert the last date

I have to make only one insertion / day on a Mysql table .
DELIMITER $$
CREATE TRIGGER trig
BEFORE INSERT ON Table
FOR EACH ROW BEGIN
/** compare the date with the latest inserted **/
IF () THEN
// if it's ok => insert
ELSE
// nothing
END IF;
END$$
DELIMITER ;
I want to compare the last inserted date and current date and then initiate my trigger to do the work.
Thanks
You can achieve this without trigger (which is a good thing right?) by creating a UNIQUE constraint on the date column and then using INSERT IGNORE syntax.
Suppose you have a table with the following schema
CREATE TABLE table1
(
date DATE,
value INT
);
Let's create a UNIQUE constraint
CREATE UNIQUE INDEX idx_date_unique ON table1 (date);
Now you can use IGNORE clause
INSERT IGNORE INTO table1 VALUES (CURDATE(), 1);
INSERT IGNORE INTO table1 VALUES (CURDATE(), 2);
INSERT IGNORE INTO table1 VALUES (CURDATE(), 3);
As a result you'll have only first row in the table for each day.
Here is SQLFiddle demo

Mysql query INSERT two tables

I have two tables:table1 and rating
table1(id,name,category)
rating (cid,rating,total_rating,total_rates,photoID)
and now when i insert data into table1 i want to set all data in table rating at zero for that specific photoID from table1, but i dont know how..can someone help me?
You can use LAST_INSERT_ID() to retrieve the ID you just inserted. For example, assuming PhotoID is the relation between table1 and rating:
insert table1 (name,category) values ('waterfall 2', 'nature');
insert rating (rating,total_rating,total_rates,photoID) values
(0, 0, 0, last_insert_id());
I'd rather create a STORED PROCEDURE to make a single call from application. Assuming that you want to INSERT a record on table rating for every insert on table1 and that ID on table1 is set as AUTO_INCREMENT.
DELIMITER $$
CREATE PROCEDURE procedureName
(
IN _name VARCHAR(25),
IN _category VARCHAR(25)
)
BEGIN
INSERT INTO table1 (name, category)
VALUES (_name, _category);
SET #last_ID := LAST_INSERT_ID();
INSERT INTO rating (cid, rating, total_rating, total_rates, photoID)
VALUES (#last_ID, 0,0,0,0);
END $$
DELIMITER ;
and call the procedure,
CALL procedureName('nameHere','categoryHere')
You can use MySql triggers http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html:
CREATE TRIGGER ins_rating AFTER INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO rating (cid,rating,total_rating,total_rates,photoID)
VALUES( NEW.ID ,0,0,0,null)
END;
If you want to insert data into TABLE1 and delete it from TABLE2, you can write below listed query:
mysql_query("DELETE * FROM table2");

Get current updated column name to use in a trigger

Is there a way to actually get the column name that was updated in order to use it in a trigger?
Basically I'm trying to have an audit trail whenever a user inserts or updates a table (in this case it has to do with a Contact table)
CREATE TRIGGER `after_update_contact`
AFTER UPDATE ON `contact` FOR EACH ROW
BEGIN
INSERT INTO user_audit (id_user, even_date, table_name, record_id, field_name, old_value, new_value)
VALUES (NEW.updatedby, NEW.lastUpdate, 'contact', NEW.id_contact, [...])
END
How can I get the name of the column that's been updated and from that get the OLD and NEW values of that column. If multiple columns have been updated in a row or even multiple rows would it be possible to have an audit for each update?
Just use OLD.colname <> NEW.colname for each column to check and find those that are different. Triggers are a bit limited in their use in MySQL, too bad.
Try this code...
create table sales (
orderno INT,
sale INT,
empsalary int,
ts TIMESTAMP
);
create table history (
updated varchar(20),
oldvalue INT,
newvalue INT
);
INSERT INTO sales
(orderno, sale, empsalary)
VALUES
(1,700,7000),
(2,800,8000),
(3,900,9000);
DROP TRIGGER test.instrigger;
DELIMITER ///
CREATE TRIGGER test.instrigger
AFTER UPDATE ON sales
FOR EACH ROW
BEGIN
IF NEW.sale <> OLD.sale THEN
INSERT INTO history
(updated, oldvalue, newvalue)
VALUES
('sale', OLD.sale,NEW.sale);
END IF;
IF NEW.empsalary <> OLD.empsalary THEN
INSERT INTO history
(updated, oldvalue, newvalue)
VALUES
('empsalary', OLD.empsalary,NEW.empsalary);
END IF;
END;
///
DELIMITER ;