I want to add the return values of a function to a table's column
It should all be in mysql no php
I have a table with price,tax and price with tax I implemented the function to calculate the price with tax but I don't know how to add those values to that table
CREATE TABLE Faturat
(Fatura_ID varchar(10),
price real
,tax real,
CmimiMeTvsh real as (total(price,tax)),
Data varchar(20),
PRIMARY KEY (Fatura_ID));
drop function if exists total;
delimiter //
create function total( x real, y real)
returns real
begin
return X+x*Y/100;
select fatura_id,total(price,tax)
from FATURAT;
CREATE TRIGGER trgAuditOnInsertPunetoret AFTER INSERT ON faturat
FOR EACH ROW
BEGIN
INSERT INTO faturat
VALUES (fatura_id,price,tax,total(price,Tax),data);
end ;
delimiter //
A generated column may be all you need here
drop table if exists t;
create table t(id int auto_increment primary key, price int, tax int, pricetax int as (price + price *tax/100));
insert into t (price,tax) values (100,6);
select * from t;
+----+-------+------+----------+
| id | price | tax | pricetax |
+----+-------+------+----------+
| 1 | 100 | 6 | 106 |
+----+-------+------+----------+
1 row in set (0.00 sec)
BTW From memory I don't think user defined functions are allowed in generated columns and your trigger won't work - you are not allowed to action the table which fired the trigger.
Related
I want to compare the sum of values in table one with the limit value in table 2 . I tried with constraint or triggers but did not work any help
As in the photo below there are 2 table
table 1 has 2 columns reserve and available
The in these columns come from users and the it must not excees more than the limit on second table ..
As example user can enter any amount where sum of all the column must be less than the limit
As of table one i can enter value in booked column that can be between 0 to the limit in table 2 but if the limit is reached then it cannot add more rows for that element
create table booked (room_id foreign key (room_id),
booked datetime, booked_seats int, remaining_seats);
create table rooms ( room_id primary key
room_size int);
booked seats are done by user, i have seperate trigger for that to ensure user enters corrected,
in want a trigger or something similar that will check the sum of all seats booked in the firsts table and compare with the room_size in second table.
if the sum is less that the size it will edit or else return error
create trigger test after insert on booked
begin
if sum of all (new.booked ) where the id is same > table2.limit then
....
end
For a quick and good answer you need more things than you provided a functioning example data for example
This Trigger will block any attempts to insert if the room_size is smaller than the the sumed up seats.
Please read the end there i explain, where you must put some work in
DELIMITER $$
CREATE TRIGGER check_roomsize_Before_Insert BEFORE insert on booked
FOR EACH ROW
begin
if (SELECT SUM(booked_seats) + NEW.booked_seats FROM booked WHERE room_id = NEW.room_id AND booked = NEW.booked GROUP BY room_id)
> (select room_size from rooms where rooms.room_id= new.room_id) then
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Roomsize too smal!';
end if;
END$$
DELIMITER ;
Schema (MySQL v5.7)
create table rooms ( room_id int primary key,
room_size int);
create table booked (room_id int,
booked datetime, booked_seats int, remaining_seats int, CONSTRAINT fk_category
FOREIGN KEY (room_id)
REFERENCES rooms(room_id));
INSERT INTO rooms VALUES ( 1,5);
DELIMITER $$
CREATE TRIGGER check_roomsize_Before_Insert BEFORE insert on booked
FOR EACH ROW
begin
if (SELECT SUM(booked_seats) + NEW.booked_seats FROM booked WHERE room_id = NEW.room_id AND booked = NEW.booked GROUP BY room_id)
> (select room_size from rooms where rooms.room_id= new.room_id) then
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Roomsize too smal!';
end if;
END$$
DELIMITER ;
INSERT INTO booked VALUES (1,now(),3,2);
#INSERT INTO booked VALUES (1,now(),3,0);
Query #1
SELECT * FROM booked;
| room_id | booked | booked_seats | remaining_seats |
| ------- | ------------------- | ------------ | --------------- |
| 1 | 2020-04-19 20:04:07 | 3 | 2 |
View on DB Fiddle
As you can see in the example 1 row is inserted and the second, gives an exception.
you need to improve the part where i sum up the booked seats there i make a
AND booked = NEW.booked
Because i don't know absolutely what time criteria will count to sum the complete seats number. The now timestamp makes no sense put to test the trigger i need some date.
PURCHASE TABLE
id (Primary Key) ItemNo, ItemName, Units, Qty, Location, CPrice,
SPrice, Supplier, PONo
STOCK TABLE
id (Primary Key), ItemNo, Qty, Location
IF EXISTS (SELECT ItemNo, Location FROM stock WHERE stock.ItemNo = 'poitem.ItemNo' AND stock.Location = 'poitem.Location') THEN
UPDATE stock SET stock.Qty = stock.Qty + poitem.Qty WHERE stock.ItemNo = 'poitem.ItemNo';
ELSE
INSERT INTO stock (stock.ItemNo, stock.Qty, stock.Location) SELECT poitem.ItemNo, poitem.Qty, poitem.Location FROM poitem;
END If
THis is my Code, but its not working as it should be
I need to update stock table when i enter a record through purchase table only is the record already exists, otherwise new record need to be entered.
Example:
ItemNo - Qty - Location
1001 - - - 15 - - - A
1001 - - - 12 - - - B
1002 - - - 50 - - - C
1003 - - - 12 - - - A
Can any one please write MYSQL code for this.
Thank you.
Your if exists will always evaluate to true (unless the stock table is empty) so the update will never happen (unless the stock table is empty). I think a procedure is inappropriate here unless you are calling it for every insert. Even if you are a trigger is probably a better bet.
drop trigger if exists t;
delimiter $$
create trigger t after insert on poitems
for each row
begin
IF EXISTS (SELECT ItemNo, Location FROM stock WHERE stock.ItemNo = new.ItemNo AND stock.Location = new.Location) THEN
UPDATE stock SET stock.Qty = stock.Qty + new.Qty WHERE stock.ItemNo = new.ItemNo and stock.Location = new.Location;
ELSE INSERT INTO stock (ItemNo, Qty, Location) values(new.ItemNo, new.Qty, new.Location) ;
END If;
end $$
I have also amended your update statement to match the if exists clause and fixed the insert statement and a few other things which looked wrong.
so given
drop table if exists poitems,stock;
create TABLE poitems(id int auto_increment Primary Key, ItemNo int, ItemName varchar(10), Units int, Qty int, Location int, CPrice int
, SPrice int, Supplier int, PONo int);
create table stock(id int auto_increment Primary Key ,ItemNo int, Qty int, Location int);
insert into poitems(itemno,qty,location) values (1,1,1),(1,1,1),(2,2,1);
results in
+----+--------+------+----------+
| id | ItemNo | Qty | Location |
+----+--------+------+----------+
| 1 | 1 | 2 | 1 |
| 2 | 2 | 2 | 1 |
+----+--------+------+----------+
2 rows in set (0.00 sec)
Table Product
id name price quantity total
1 food 50 1 50
2 drink 20 2 40
3 dress 100 3 300
How do I declare a table that has a column that is the product of two columns?
I have this code:
CREATE TABLE [dbo].[Orders] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ProductName] NCHAR (70) NULL,
[Price] INT NULL,
[Quantity] INT NULL,
[Total] INT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
Sounds like you want a VIEW.
Their example is exactly what you're describing
mysql> CREATE TABLE t (qty INT, price INT);
mysql> INSERT INTO t VALUES(3, 50);
mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql> SELECT * FROM v;
+------+-------+-------+
| qty | price | value |
+------+-------+-------+
| 3 | 50 | 150 |
+------+-------+-------+
You can try this mate:
DROP TRIGGER IF EXISTS trg_product_total;
DELIMITER //
CREATE TRIGGER trg_product_total AFTER INSERT ON product
FOR EACH ROW BEGIN
SET #price = NULL, #quantity = NULL;
SELECT price INTO #price FROM product
WHERE id = NEW.id;
SELECT quantity INTO #quantity
WHERE id = NEW.id;
UPDATE product SET total = #price * #quantity
WHERE id = NEW.id;
END;
You can use this kind of approach if you don't really want to process the product.total before inserting it into the DB.
The Trigger will execute each time a new record is added into the table, wherein the expected insert for the total column is either 'NULL' or '0' depending on your default value.
But I think it would be better if you calculate it before the insert.
The flow would be like:
Application side
1. get price and quantity for the product
2. calculate for the total
3. insert values into the query
4. execute query
In case you want to learn more about MySQL Trigger: Link
Also, PHP Transaction: Link
I have this mysql table built like this:
CREATE TABLE `posts` (
`post_id` INT(10) NOT NULL AUTO_INCREMENT,
`post_user_id` INT(10) NOT NULL DEFAULT '0',
`gen_id` INT(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`post_user_id`, `post_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
When I do:
insert into posts (post_user_id) values (1);
insert into posts (post_user_id) values (1);
insert into posts (post_user_id) values (2);
insert into posts (post_user_id) values (1);
select * from posts;
I get:
post_id | post_user_id | gen_id
1 1 0
2 1 0
1 2 0
3 1 0
A unique post_id is generated for each unique user.
I need the gen_id column to be 1 2 3 4 5 6 etc. How can I increment this column when I do an insert. I tried the one below, but it won't work. What's the right way to do this?
insert into posts (post_user_id,gen_id) values (1,select max(gen_id)+1 from posts);
//Select the highest gen_id and add 1 to it.
Try this:
INSERT INTO posts (post_user_id,gen_id)
SELECT 1, MAX(gen_id)+1 FROM posts;
Use a TRIGGER on your table. This sample code can get you started:
DELIMITER //
CREATE TRIGGER ai_trigger_name AFTER INSERT ON posts
FOR EACH ROW
BEGIN
UPDATE posts
SET gen_id = (SELECT MAX(gen_id) FROM posts) + 1
WHERE post_id = LAST_INSERT_ID()
LIMIT 1;
END;//
DELIMITER ;
For my case the first number to increment was null. I resolve with
IFNULL(MAX(number), 0) + 1
or better the query became
SELECT IFNULL(MAX(number), 0) + 1 FROM mytable;
Here is the table "Autos" and the data that it contains to begin with:
AutoID | Year | Make | Model | Color |Seq
1 | 2012 | Jeep |Liberty| Black | 1
2 | 2013 | BMW | 330XI | Blue | 2
The AutoID column is an auto incrementing column so it is not necessary to include it in the insert statement.
The rest of the columns are varchars except for the Seq column which is an integer column/field.
If you want to make it so that when you insert the next row into the table and the Seq column auto increments to the # 3 you need to write your query as follows:
INSERT INTO Autos
(
Seq,
Year,
Make,
Model,
Color,
)
Values
(
(SELECT MAX(Seq) FROM Autos) + 1, --this increments the Seq column
2013,'Mercedes','S550','Black');
The reason that I put the Seq column first is to ensure that it will work correctly... it does not matter where you put it, but better safe than sorry.
The Seq column should now have a value of 3 along with the added values for the rest of that row in the database.
The way that I intended that to be displayed did not happen...so I will start from the beginning: First I created a table.
create table Cars (
AutoID int identity (1,1) Primary Key,
Year int,
Make varchar (25),
Model varchar (25),
TrimLevel varchar (30),
Color varchar (30),
CreatedDate date,
Seq int
)
Secondly I inserted some dummy values
insert into Cars values (
2013,'Ford' ,'Explorer','XLT','Brown',GETDATE(),1),
(2011,'Hyundai' ,'Sante Fe','SE','White',GETDATE(),2),
(2009,'Jeep' ,'Liberty','Jet','Blue',GETDATE(),3),
(2005,'BMW' ,'325','','Green',GETDATE(),4),
(2008,'Chevy' ,'HHR','SS','Red',GETDATE(),5);
When the insertion is complete you should have 5 rows of data.
Since the Seq column is not an auto increment column and you want to ensure that the next Seq's row of data is automatically incremented to the # 6 and its subsequent rows are incremented as well you would need to write the following code:
INSERT INTO Cars
(
Seq,
Year,
color,
Make,
Model,
TrimLevel,
CreatedDate
)
Values
(
(SELECT MAX(Seq) FROM Cars) + 1,
2013,'Black','Mercedes','A550','AMG',GETDATE());
I have run this insert statement many times using different data just to make sure that it works correctly....hopefully this helps!
MySQL. Two columns, same table.
Column 1 has product_id
Column 2 has category_ids (sometimes 2 categories, so will look like 23,43)
How do i write a query to return a list of product_id, category_ids, with a seperate row if there is more than 1 category_id associated with a product_id.
i.e
TABLE:
product_id | category_ids
100 | 200,300
101 | 201
QUERY RESULT: Not trying to modify the table
100 | 200
100 | 300
101 | 201
EDIT: (note) I don't actually wish to manipulate the table at all. Just doing a query in PHP, so i can use the data as needed.
Your database table implementation seems bad designed, however in your case what you need would be a reverse function of GROUP_CONCAT, but unfortunately it doesn't exist in MySQL.
You have two viable solutions :
Change the way you store the data (allow duplicate on the product_id field and put multiple records with the same product_id for different category_id)
Manipulate the query result from within your application (you mentioned PHP in your question), in this case you have to split the category_ids column values and assemble a result set by your own
There is also a third solution that i have found that is like a trick (using a temporary table and a stored procedure), first of all you have to declare this stored procedure :
DELIMITER $$
CREATE PROCEDURE csv_Explode( sSepar VARCHAR(255), saVal TEXT )
body:
BEGIN
DROP TEMPORARY TABLE IF EXISTS csv_Explode;
CREATE TEMPORARY TABLE lib_Explode(
`pos` int unsigned NOT NULL auto_increment,
`val` VARCHAR(255) NOT NULL,
PRIMARY KEY (`pos`)
) ENGINE=Memory COMMENT='Explode() results.';
IF sSepar IS NULL OR saVal IS NULL THEN LEAVE body; END IF;
SET #saTail = saVal;
SET #iSeparLen = LENGTH( sSepar );
create_layers:
WHILE #saTail != '' DO
# Get the next value
SET #sHead = SUBSTRING_INDEX(#saTail, sSepar, 1);
SET #saTail = SUBSTRING( #saTail, LENGTH(#sHead) + 1 + #iSeparLen );
INSERT INTO lib_Explode SET val = #sHead;
END WHILE;
END; $$
DELIMITER ;
Then you have to call the procedure passing the array in the column you want to explode :
CALL csv_explode(',', (SELECT category_ids FROM products WHERE product_id = 100));
After this you can show results in the temporary table in this way :
SELECT * FROM csv_explode;
And the result set will be :
+-----+-----+
| pos | val |
+-----+-----+
| 1 | 200 |
| 2 | 300 |
+-----+-----+
It could be a starting point for you ...