DROP TABLE IF EXISTS Sales;
CREATE TABLE Sales (
id INT AUTO_INCREMENT,
product VARCHAR(100) NOT NULL,
quantity INT NOT NULL DEFAULT 0,
fiscalYear SMALLINT NOT NULL,
fiscalMonth TINYINT NOT NULL,
CHECK(fiscalMonth >= 1 AND fiscalMonth <= 12),
CHECK(fiscalYear BETWEEN 2000 and 2050),
CHECK (quantity >=0),
UNIQUE(product, fiscalYear, fiscalMonth),
PRIMARY KEY(id)
);
DROP TABLE IF EXISTS log;
CREATE TABLE log (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
text VARCHAR(100)
);
Triggers
CREATE DEFINER=`root`#`localhost` TRIGGER `sales_AFTER_UPDATE` AFTER UPDATE ON `sales`
FOR EACH ROW
BEGIN
INSERT INTO log VALUES(NOW(),CONCAT('Update Student Record ', OLD.quantity));
END
UPDATE test for.sales SET quantity = 36
WHERE (id = 1);
ERROR 1136: 1136: Column count doesn't match value count at row 1
Iam new in mySQL Please help
You should specify columns in INSERT statement in your trigger explicitly, as you do not set all values in a row (auto incremented column excluded).
So it would be
INSERT INTO log(timestamp, text) VALUES (NOW(),CONCAT('Update Student Record ', OLD.quantity));
You have some errors.
First based on your trigger you need another column on log table which is as following
quantity INT NOT NULL DEFAULT 0
Second , do not use Keywords and Reserved Words like text and timestamp, it is a bad practice. If you do please put it inside backticks
Third your insert statement should be
INSERT INTO log(`timestamp`,`text`,quantity) VALUES(NOW(),'Update Student Record', OLD.quantity);
there is no need for CONCAT.
Fourth,
`sales`
table is not the same as Sales table, because you have used backticks.
Full working trigger below:
DELIMITER //
CREATE TRIGGER `sales_AFTER_UPDATE` AFTER UPDATE ON Sales
FOR EACH ROW
BEGIN
INSERT INTO log(`timestamp`,`text`,quantity) VALUES(NOW(),'Update Student Record', OLD.quantity);
END//
DELIMITER ;
Check working demo:
https://www.db-fiddle.com/f/iqwShcHK3AGJvU4MDbxDku/0
Related
Is there a way to set at the time of creating a table a custom ID with some character as prefix and the rest are numbers which is auto incremented so that the first time a record is inserted the ID will be "UID0000001" and the second time a record is inserted the ID will be "UID0000002" and so on automatically in MySQL.
You could do it in the database via a trigger. What you would need to do is to use an auto_increment-column and get the value of it in the BEFORE-trigger:
delimiter $$
drop table thetable
$$
create table thetable (
id int auto_increment,
id_text varchar(20),
another varchar(20),
primary key(id),
unique index(id_text)
)
$$
CREATE TRIGGER thetable_ibefore
BEFORE INSERT ON thetable
FOR EACH ROW
BEGIN
DECLARE v_id int;
select auto_increment into v_id
from information_schema.tables
where table_schema = database() and table_name = 'thetable';
SET NEW.id_text = concat('UID',substr(concat('000000', v_id), -7));
END;
$$
insert into thetable (another) values ('ABC')
$$
select * from thetable
$$
Assuming the prefix would always be UID, then you should just maintain an auto increment id column and then build the UIDxxxxx value when you query or in your presentation layer. If the prefix could vary, then you would need to state the rules if you want a concrete answer.
For example:
CREATE TABLE yourTable (
id int NOT NULL AUTO_INCREMENT,
some_col varchar(255) NOT NULL,
-- other columns here
PRIMARY KEY (id)
);
SELECT CONCAT('UID', LPAD(id, 7, '0')) AS uid
FROM yourTable;
I am trying to calculate the differential column of the score table upon inserting into a MySQL 8.0 database using a before trigger. The calculation uses the coursetee table as well. The trigger works fine on all but the first record in the table, which doesn't get updated. Is there something that I am missing? All relevant code is below.
CREATE TABLE coursetee (
teeID INT UNSIGNED AUTO_INCREMENT,
tee_name VARCHAR(20) NOT NULL,
course_rating DECIMAL(3,1) NOT NULL,
slope_rating INT UNSIGNED NOT NULL,
par INT UNSIGNED,
CONSTRAINT pk_coursetee PRIMARY KEY (teeID),
CREATE TABLE score (
roundID INT UNSIGNED AUTO_INCREMENT,
teeID INT UNSIGNED,
round_score INT UNSIGNED NOT NULL,
round_date DATETIME NOT NULL,
entry_date DATETIME DEFAULT NOW() NOT NULL,
differential DECIMAL(3,1),
CONSTRAINT pk_score PRIMARY KEY (roundID),
CONSTRAINT fk_score_coursetee FOREIGN KEY (teeID) REFERENCES coursetee(teeID));
DELIMITER $$
CREATE TRIGGER calculate_differential
BEFORE INSERT ON score
FOR EACH ROW
BEGIN
SET NEW.differential = (SELECT ROUND((113/ct.slope_rating)*(NEW.round_score-ct.course_rating),1)
FROM score, coursetee as ct
WHERE NEW.teeID = ct.teeID AND differential IS NULL);
END$$
DELIMITER ;
INSERT INTO coursetee
(courseID,tee_name,course_rating,slope_rating,par)
VALUES
(1,'Back',74.7,143,72),
(1,'Middle',72.6,136,72),
(1,'Front',71.3,132,72),
(2,'Back',76.8,155,72),
(2,'Middle',73.9,146,72),
(2,'Front',65.3,125,72);
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(1,2,79,'2019-07-25');
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(2,2,80,'2019-07-25');
INSERT INTO score
(playerID,teeID,round_score,round_date)
VALUES
(1,2,77,'2019-08-06');
The query returns:
image of query not returning calculated record for row 1
CREATE TRIGGER calculate_differential
BEFORE INSERT
ON score
FOR EACH ROW
SET NEW.differential = ( SELECT ROUND((113/ct.slope_rating)*(NEW.round_score-ct.course_rating),1)
FROM coursetee ct
WHERE NEW.teeID = ct.teeID);
fiddle
The problem was in using score table as a source of the subquery. And the hope that differential BEFORE inserting the first record will give anything except NOT FOUND. And testing the field of the record BEFORE INSERT for NULL makes no sense.
My assumption is about the FROM clause of the differential query in the trigger. i'd suggest you to try change the order of the tables -
FROM score, coursetee as ct
to
FROM coursetee as ct, score
Seems like its trying to extract nothing for the first insert...
when I update the data in a table Form in the tables Book from the number of colbook must be subtracted -1.
please help to do this with a trigger
table Form
Create table Form (
idForm int not null primary key auto_increment,
date_of_issue date not null,
return_date date ,
idBook int not null,
Foreign key(idBook) references Book (idBook));
table Book
Create table Book (
idBook int not null primary key auto_increment,
name varchar(45) not null,
colBook int(11) null;
Filling a table Form
Insert into Form (idForm, date_of_issue)
Values(1, "2018-11-11");
Filling a table Book
Insert into Book (idBook, name, colBook)
Values(1, Garri Potter, 5);
table update request Form
update Form
set return_date = "2000-03-03"
where idBook = 1;
You just need to create a trigger on table "Form" as below:
delimiter $$
CREATE TRIGGER form_trigger_1
AFTER INSERT ON form FOR EACH ROW
BEGIN
update book
set colbook = colbook - 1
where idbook = old.idbook;
END
delimiter ;
I have an auto incremented field in my table. It should reset every new year 01/01 and then the prefix part should increment.
For example in 2016 my auto incremented field was A1,A2,A3..... etc but on 12:00 AM 2017 it should reset to B1 and go from there `(B1,B2,B3... etc), until Z when prefix should stop incrementing.
I created two tables... one for integer and one for varchar
CREATE TABLE t1
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE t2
(
id VARCHAR(1) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);
and am creating a trigger
DELIMITER $$
CREATE TRIGGER tg1
BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 VALUES (NULL);
SET NEW.id = CONCAT('A', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;
but am not sure how to involve date.
My db is mysql
I'm trying to keep a list of current content and archived content in my PHP Internet application. I want to be able to identify the content that as archived as having an enddate, and the content that is not archived as having no enddate. It would be ideal if I could create more paths, but I'm hoping to just start here.
The first thing I'm noticing is that I'm getting a syntax error at the " on line 1, but there is no double quote where I create the table. The second issue I'm having is the use of TIMESTAMP as a datatype. I tried to use CURRENT_TIMESTAMP for the startdate, and it returned syntax errors. The final problem I am having is with the trigger construction. I'm not able to get down far enough to troubleshoot it. As soon as I get past the references, I'll also try to troubleshoot that.
CREATE TABLE plan(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
startdate TIMESTAMP NOT NULL,
enddate TIMESTAMP);
CREATE TABLE level(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
description VARCHAR(500),
startdate TIMESTAMP NOT NULL,
enddate TIMESTAMP);
CREATE TABLE planIDxlevelID(
planID INT NOT NULL REFERENCES plan(id),
levelID INT NOT NULL REFERENCES level(id),
arXORcur ENUM('archive', 'current');
);
delimiter |
CREATE TRIGGER testref BEFORE INSERT ON plan
FOR EACH ROW BEGIN
INSERT INTO plan(id, plan, startdate, enddate)
SET id = LAST_INSERT_ID( id + 1), name = NEW.name, startdate = NEW.UTC_TIMESTAMP, enddate = NULL;
UPDATE plan(enddate) WHERE plan.id = OLD.id
SET enddate = UTC_TIMESTAMP;
INSERT INTO planIDxlevelID(planID, levelID, arXORcur)
SET planID = NEW.planID, levelID = OLD.levelID, arXORcur = current;
UPDATE planIDxlevelID(planID, levelID, arXORcur) WHERE planID = OLD.planID
SET planID = OLD.planID, levelID = OLD.levelID, arXORcur = archive;
END;
|
delimiter ;
INSERT INTO plan (name) VALUES
"Frogs", "Toys", "Trucks", "Nature", "Seasons",
"Construction", "Candy", "Rainbows", "Telephone", "Breakfasts";
TIMESTAMP vs DATETIME
This is a classic gotcha: TIMESTAMP is a special datatype that
is updated with "now" every time the row is touched, whether you update it to another value or leave it alone. What you want is DATETIME.
Next, you have numerous syntax and other errors. The following executes without error, however it may not now have the logic you want, but you can edit it to fix that:
CREATE TABLE plan (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
startdate DATETIME NOT NULL, -- changed TIMESTAMP to DATETIME
enddate DATETIME -- changed TIMESTAMP to DATETIME
);
CREATE TABLE level (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32),
description VARCHAR(500),
startdate DATETIME NOT NULL, -- changed TIMESTAMP to DATETIME
enddate DATETIME -- changed TIMESTAMP to DATETIME
);
CREATE TABLE planIDxlevelID (
planID INT NOT NULL REFERENCES plan(id),
levelID INT NOT NULL REFERENCES level(id),
arXORcur ENUM('archive', 'current')
);
DROP TRIGGER IF EXISTS test_insert;
delimiter |
CREATE TRIGGER test_insert BEFORE INSERT ON plan
FOR EACH ROW BEGIN
INSERT INTO plan (id, plan, startdate)
values (LAST_INSERT_ID() + 1, NEW.name, NEW.UTC_TIMESTAMP());
INSERT INTO planIDxlevelID (planID, levelID, arXORcur)
values (NEW.ID, null, arXORcur = current);
END;|
delimiter ;
DROP TRIGGER IF EXISTS test_update;
delimiter |
CREATE TRIGGER test_update BEFORE UPDATE ON plan
FOR EACH ROW BEGIN
UPDATE plan SET
enddate = UTC_TIMESTAMP
WHERE plan.id = OLD.id;
UPDATE planIDxlevelID SET
planID = NEW.ID,
levelID = null,
arXORcur = archive
WHERE planID = OLD.ID;
END;|
delimiter ;
INSERT INTO plan (name) VALUES
("Frogs"), ("Toys"), ("Trucks"), ("Nature"), ("Seasons"),
("Construction"), ("Candy"), ("Rainbows"), ("Telephone"), ("Breakfasts");