I want to use a function inside a select query.
This is my test database.
When I use a select, get a result, but the function is running twice... why? I want to insert one row in this case.
Help, please!
create database db1_test;
use db1_test;
create table t1(
id int(11) primary key auto_increment,
t1col1 varchar(20) not null,
t1col2 int(1) not null
);
create table t2(
id int(11) primary key auto_increment,
t2col1 int(11) not null,
t2col2 datetime
);
insert into t1 (t1col1, t1col2) values ('row1', 1);
insert into t1 (t1col1, t1col2) values ('row2', 0);
insert into t1 (t1col1, t1col2) values ('row4', 1);
drop function if exists func1;
DELIMITER $$
CREATE FUNCTION func1(id int) RETURNS datetime
BEGIN
insert into t2 (`t2col1`, `t2col2`) values (id, now());
RETURN now();
END $$
DELIMITER ;
TEST :
SELECT id, t1col2, func1(id) FROM `t1` WHERE 1 and `t1`.`t1col1`='row1';
SELECT id, t1col2, func1(id) FROM `t1` WHERE 1 and `t1`.`t1col1`='row2';
SELECT id, t1col2, func1(id) FROM `t1` WHERE 1 and `t1`.`t1col1`='row4';
Functions are generally used to store reuseable code which returns a scalar value from a calculation or transformation. I think you could
insert into t2(t2col1,t2col2)
SELECT id, now()
FROM `t1`
WHERE `t1`.`t1col1`='row1';
Related
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
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...
I have big data and The first query is too big.
So I make a procedure from the first query. I need procedure (data) join another table join.
DELIMITER $$
CREATE PROCEDURE sales_pro()
BEGIN
SELECT * FROM sales;
END;
select * from sales
where sales.rep_id= sales_pro.rep_id
CREATE TABLE IF NOT EXISTS `reps` (
`rep_id` int(11) NOT NULL,
`rep_name` TEXT(50) NOT NULL
);
INSERT INTO `reps` (`rep_id`, `rep_name`) VALUES
(1, 'John'),
(2, 'Sally'),
(3, 'Joe'),
(4, 'Bob');
CREATE TABLE IF NOT EXISTS `sales` (
`prod_id` int(11) NOT NULL,
`rep_id` int(11) NOT NULL,
`sale_date` DATE NOT NULL,
`quantity` int(11) NOT NULL,
PRIMARY KEY (`prod_id`,`rep_id`,`sale_date`),
KEY `rep_id` (`rep_id`)
);
INSERT INTO `sales` (`prod_id`, `rep_id`, `sale_date`, `quantity`) VALUES
(1, 1, '2013-05-16', 20);
You can't join with a procedure, but you can do it with a view, which can be treated like a table (although there are some restrictions).
CREATE VIEW sales_view AS
SELECT * FROM sales;
SELECT *
FROM sales AS s
JOIN sales_view AS sv ON s.rep_id = sv.rep_id
You can't pass parameters to a view, but you can access columns in the WHERE clause.
SELECT *
FROM sales AS s
JOIN sales_view AS sv ON s.rep_id = sv.rep_id
WHERE sv.quantity > 10;
I've successful execute this procedure when I call the stored procedure, I get error message:
Can't reopen table: 'temp1'.
Its like temporary table used more than once in the query. Any ideas or other solution to solve this problem ?
DELIMITER //
CREATE PROCEDURE menu_t1()
BEGIN
CREATE TEMPORARY TABLE if not exists temp1(
object_id VARCHAR(50) NULL,
description VARCHAR(100) NULL,
display_name VARCHAR(60) NULL,
menu_id VARCHAR(40) NULL,
order_seq int NULL,
menu_level int NULL,
link_url VARCHAR(200) NULL,
OrderString VARCHAR(200) NULL
);
insert into temp1 (object_id, description, display_name, menu_id, order_seq, menu_level, link_url, OrderString)
SELECT mp.object_id, mp.description, mp.display_name, mp.menu_id, mp.order_seq, mp.menu_level, mp.link_url,
concat('00',cast((mp.order_seq) as char)) OrderString
FROM ui_menuitem mp
WHERE mp.parent_id is null and mp.menu_id = '1';
select * from temp1;
select * from temp1
union all
select mc.object_id, mc.description, mc.display_name, mc.menu_id, mc.order_seq, mc.menu_level, mc.link_url,
concat(temp1.OrderString,'-',cast((mc.order_seq) as char)) OrderString
from ui_menuitem mc, temp1
where mc.parent_id = temp1.object_id and mc.menu_id = '1';
TRUNCATE TABLE temp1;
DROP TEMPORARY TABLE IF EXISTS temp1;
COMMIT;
END //
DELIMITER ;
This style looks like recursive.
Thanks
While you have declared the temporary table, you've not defined anything about it, such as columns, types, nor inserted any data into it. All you've done is declare it, and then perform a select statement.
You need to instead define your table by doing something like this
CREATE TABLE #temp1(
object_id INT,
description VARCHAR(200)
...)
And then insert the data into it like this
INSERT INTO #temp1(object_id, description, ...)
SELECT mp.object_id, mp.description, ...
You are getting the error at present as temp1 currently has no OrderString column.
I've 2 tables (t1,t2) on my test db.
CREATE TABLE IF NOT EXISTS `t1` (
`name` varchar(10) NOT NULL,
`code` varchar(10) NOT NULL,
`end_date` varchar(8) NOT NULL
);
CREATE TABLE IF NOT EXISTS `t2` (
`date` varchar(8) NOT NULL
);
I'd like to create a trigger for update t2.date (with t1.end_date value) when update t1.end_date.
I've tried this way but with no success (Variable 'OLD' is not a variable component (can't be used as XXXX.variable_name)).
CREATE TRIGGER update_date BEFORE UPDATE ON t1 FOR EACH ROW
IF NOT (t1.NEW.end_date <=> t1.OLD.end_date) THEN
SET t2.OLD.date = t2.NEW.end_date;
END IF
How can I do this? Thanks
delimiter |
CREATE TRIGGER update_date AFTER UPDATE ON t1
FOR EACH ROW BEGIN
IF NOT (NEW.end_date <=> OLD.end_date) THEN
update t2
SET `date` = NEW.end_date;
END IF;
END
|
delimiter ;
And please don't use strings to store dates. Use the date data type!