MYSQL stock entry - mysql

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)

Related

Randomly Assign Rows in Child Table to Row in Parent Table

Using MySQL, I am trying to randomly assign rows in a child table to point to a row in a parent table, per following:
Parent table: There are 50 WorkGroups (Team Alpha, Team Bravo, etc.), each of which can have a maximum number of WorkEmployees.
Child table: There are 2,000 WorkEmployees (Ann, Bob, Carl, etc.) each of whom needs to be assigned to exactly one WorkGroup at random.
Using MySQL Each WorkEmployee needs to be assigned to exactly one WorkGroup
Each WorkGroup has a specified maximum number of WorkEmployees it can accommodate
There are sufficient slots in the WorkGroups to accommodate all WorkEmployees
I cannot used stored procedures
Following are the table structures and the UPDATE script I have developed for this purpose. The script is not working. Any guidance on what I have done wrong would be very much appreciated. Thank you.
CREATE TABLE WorkGroups ( ID varchar(64), GroupName varchar(64), MaxMembers int );
CREATE TABLE WorkEmployees ( ID varchar(64), EmployeeName varchar(64), WorkGroupFK varchar(64) );
UPDATE WorkEmployees
SET WorkGroupFK = ( SELECT WorkGroups.ID
FROM WorkGroups
WHERE ( SELECT COUNT(*)
FROM (SELECT * FROM WorkEmployees) WorkEmployees2
WHERE WorkEmployees2.WorkGroupFK = WorkGroups.ID )
< WorkGroups.MaxMembers ) /* max capacity */
WHERE WorkEmployees.WorkGroupFK IS NULL /* employee not yet assigned */
;
The problem besides, that it tales tome to make sample data, is that you havn't introduced the random factor and that you can only add 1 workgroup to a emplyoee
So adding a ORDER BY RAND() and a 'LIMIT 1 does the trick
CREATE TABLE WorkGroups ( ID varchar(64), GroupName varchar(64), MaxMembers int );
CREATE TABLE WorkEmployees ( ID varchar(64), EmployeeName varchar(64), WorkGroupFK varchar(64) );
INSERT INTO WorkGroups VALUES(1,'test1',2),(2,'test1',3),(3,'test1',2)
INSERT INTO WorkEmployees VALUES (1,'emp1', NULL),(2,'emp2', NULL),(3,'emp3', NULL),(4,'emp4', NULL)
,(5,'emp5', NULL),(6,'emp6', NULL),(7,'emp7', NULL)
UPDATE WorkEmployees
SET WorkGroupFK = ( SELECT WorkGroups.ID
FROM WorkGroups
WHERE ( SELECT COUNT(*)
FROM (SELECT * FROM WorkEmployees) WorkEmployees2
WHERE WorkEmployees2.WorkGroupFK = WorkGroups.ID )
< WorkGroups.MaxMembers
ORDER BY RAND()
LIMIT 1) /* max capacity */
WHERE WorkEmployees.WorkGroupFK IS NULL /* employee not yet assigned */
;
SELECT * FROM WorkEmployees
ID | EmployeeName | WorkGroupFK
:- | :----------- | :----------
1 | emp1 | 2
2 | emp2 | 2
3 | emp3 | 3
4 | emp4 | 3
5 | emp5 | 1
6 | emp6 | 3
7 | emp7 | 2
db<>fiddle here

Using trigger to make sure inserted data doesnt cross limit

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.

how to add data to a column table from mysql function

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.

Declare a table has a column that is the product of two columns

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

Manage revisions in postgresql

I am currently trying to manage revisions of a data set in a postgreSql database. The table I would like to use has the following structure:
CREATE TABLE dataset (
id BIGSERIAL PRIMARY KEY,
revision INTEGER NOT NULL,
object_id BIGINT NOT NULL
);
The id field is a unique auto-increment identifier. The object_id should be the identifier for a object, while revision keeps track of the revisions:
id | object_id | revision
-------------------------
1 | 1 | 1
2 | 2 | 1
3 | 1 | 2
4 | 1 | 3
5 | 3 | 1
6 | 4 | 1
What I now need is a function, that:
Sets a auto-increment object_id and sets revision to 1, if no object_id is provided.
Sets a auto-increment revision for this object_id, if an object_id is provided.
I already found this answer, but this does not really solve the problem of creating consecutive revisions for a object_id and it does not solve the problem of auto creating consecutive object_ids.
EDIT:
I would do something like the following, but this doesn't feel very comfortable:
CREATE OR REPLACE FUNCTION update_revision() RETURNS TRIGGER LANGUAGE plpgsql AS
$$
BEGIN
IF tg_op='INSERT' THEN
IF NEW.object_id != NULL THEN
NEW.object_id = SELECT nextval(object_id_seq_id);
NEW.revision = 1;
ELSE
NEW.revision = SELECT MAX(revision)+1 FROM dataset WHERE spot_id = NEW.spot_id;
END IF;
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER update_revision BEFORE INSERT OR UPDATE ON dataset
FOR EACH ROW EXECUTE PROCEDURE update_revision();
Make (object_id, revision) unique. BTW why aren't they the primary key?
create table dataset (
id bigserial primary key,
object_id bigint not null,
revision integer not null,
unique (object_id, revision)
);
create or replace function include_revision (_object_id integer)
returns dataset as $$
with object_id as (
select coalesce(max(object_id), 0) + 1 as object_id
from dataset
), revision as (
select coalesce(max(revision), 0) + 1 as revision
from dataset
where object_id = _object_id
)
insert into dataset (object_id, revision)
select
coalesce(_object_id, (select object_id from object_id)),
(select revision from revision)
returning *
;
$$ language sql;
object_id is set to coalesce(_object_id, (select object_id from object_id)), that is, only if _object_id is null it will use the calculated max(object_id)
Testing:
select include_revision(null);
include_revision
------------------
(1,1,1)
select include_revision(1);
include_revision
------------------
(2,1,2)
select include_revision(null);
include_revision
------------------
(3,2,1)