I am trying to create a fairly complicated Trigger and I'm not sure if it can be done on phpMyAdmin.
Right now I have this query that creates a table with all the information I need from it.
CREATE TABLE SeniorDB_Shipping
SELECT
SeniorDB_Invoice.ID_Order,
SeniorDB_Customer.MCT_Code,
SeniorDB_Customer.Customer_Name,
SeniorDB_Customer.Customer_Address,
SeniorDB_Customer.Customer_City,
SeniorDB_Customer.Customer_State,
SeniorDB_Invoice.Shipping_Company
FROM SeniorDB_Customer
Join SeniorDB_Invoice ON SeniorDB_Customer.MCT_Code = SeniorDB_Invoice.MCT_Code
As you can see in the image, when I run the query, it pulls in information from the tables above the information. I'm trying (and failing) to create a trigger that will do this same thing without having to create a brand new table every single time. All the other posts I have seen are similar in regards to creating a table instead of inserting to a table.
What the trigger does is, when I enter the ID_Order, the rest of the information will get pulled from the database.
This is the trigger I have so far:
delimiter ~
create trigger SeniorDB_Shipping before insert on SeniorDB_Shipping
for each row begin
set new.SeniorDB_Shipping.MCT_Code = new.SeniorDB_Customer.MCT_Code,;
set new.SeniorDB_Shipping.Customer_Name = new.SeniorDB_Customer.Customer_Name,;
set new.SeniorDB_Shipping.Customer_Address = new.SeniorDB_Customer.Customer_Address,;
set new.SeniorDB_Shipping.Customer_City = new.SeniorDB_Customer.Customer_City,;
set new.SeniorDB_Shipping.Customer_State = new.SeniorDB_Customer.Customer_State,;
set new.SeniorDB_Shipping.Shipping_Company = new.SeniorDB_Customer.Shipping_Company,;
end~
delimiter ;
I feel like I'm right there. I just can't link it to when I enter the ID_Order.
This is the page if you would like to see the databases: http://polonium.forest.usf.edu/~sngamwon/SeniorProject/SeniorDB_Order.php
Ok, so you'll need to run this once:
/* Create the table with a primary key */
create table `SeniorDB_Shipping` (
`id` INT unsigned AUTO_INCREMENT NOT NULL,
primary key(id),
`ID_Order` int NOT NULL,
`MCT_Code` int NOT NULL,
`Customer_Name` varchar(255) NOT NULL,
`Customer_Address` varchar(255) NOT NULL,
`Customer_City` varchar(255) NOT NULL,
`Customer_State` varchar(255) NOT NULL,
`Shipping_Company` varchar(255) NOT NULL
) ENGINE=MyISAM CHARACTER SET=utf8 COLLATE utf8_general_ci;
Then you can run
/* Insert statement */
INSERT INTO `SeniorDB_Shipping` (
`ID_Order`,
`MCT_Code`,
`Customer_Name`,
`Customer_Address`,
`Customer_City`,
`Customer_State`,
`Shipping_Company`
) SELECT
invoice.ID_Order,
customer.MCT_Code,
customer.Customer_Name,
customer.Customer_Address,
customer.Customer_City,
customer.Customer_State,
invoice.Shipping_Company
FROM
SeniorDB_Customer as customer
Join SeniorDB_Invoice as invoice
ON customer.MCT_Code = invoice.MCT_Code;
I've run this in my own PHPMyAdmin, so it works. But I obviously don't have your schema. Known issues:
This will populate SeniorDB_Shipping with ALL the data from your two tables each time. Modify the query as required to select only recent data if that's not what you want. If ID_Order is a primary key you could check that doesn't already exist.
Related
Following up to see if there is a way, know this might be simple for you guys:
I need to create a table with 5 columns where columns(CostPrice) and columns(SellPrice) need to add a value into columns(Difference) in MySQL. In the example let's say I have items I wish to load and upon selling them I want that Difference calculated in the database not through a view because I'd like to reference that "Difference" value in another table when I'll at a later stage be doing a view.
What I'm trying to achieve:
itemAdd/itemName/costPrice/sellPrice/difference
2019-08-22/Table/100/150/50
CREATE TABLE Results (
itemAdd Timestamp,
itemName varchar(255) NOT NULL,
costPrice int(11) NOT NULL,
sellPrice int(11) NOT NULL,
(costPrice - sellPrice) as 'difference'
)
Reason why I want to do this through table create is because I'd update the costPrice and sellPrice of the items and would like to keep track of how the difference changed, but at the same time I'd like to reference the difference column from another table so that value shouldn't stay statically the same. Hope this makes sense. . .
If you set up insert/update triggers, you can determine the difference any time there is a change.
(live sandbox example: https://www.db-fiddle.com/f/8DVeXFdsrEBwHg168GZU2o/22)
Update your table to define the difference column.
CREATE TABLE Results (
itemAdd Timestamp,
itemName varchar(255) NOT NULL,
costPrice int(11) NOT NULL,
sellPrice int(11) NOT NULL,
difference int(11) NOT NULL
);
Then define triggers to handle the insert/updates:
-- handle inserts
DELIMITER $$
CREATE TRIGGER trg_insert_price_diff
BEFORE INSERT ON Results
FOR EACH ROW
BEGIN
SET NEW.difference = NEW.sellPrice - NEW.costPrice;
END$$
DELIMITER ;
-- handle updates
DELIMITER $$
CREATE TRIGGER trg_update_price_diff
BEFORE UPDATE ON Results
FOR EACH ROW
BEGIN
SET NEW.difference = NEW.sellPrice - NEW.costPrice;
END$$
DELIMITER ;
I have the following table:
CREATE TABLE IF NOT EXISTS PDF_STORAGE (
ID_PDF_STORAGE bigint(20) NOT NULL AUTO_INCREMENT,
DESC_FILE varchar(255) DEFAULT NULL,
PDF_FILE longblob,
LINK_FILE varchar(255) DEFAULT NULL,
VERSION int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (ID_PDF_STORAGE)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Where PDF_FILE is a file of 10 MB on average. Today it has about 50.000 rows. I need to add a new column to this table but it is taking a long time, more than 10 min, some times giving a 401 error in PhpMyAdmin, so I'd like to know what is the proper way to achieve this...
I already tried:
ALTER TABLE PDF_STORAGE ADD VERSION INT NOT NULL DEFAULT '0' AFTER LINK_FILE ;
and
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE PDF_STORAGE_new LIKE PDF_STORAGE;
ALTER TABLE PDF_STORAGE_new ADD VERSION INT NOT NULL DEFAULT '0' AFTER LINK_FILE ;
INSERT INTO PDF_STORAGE_new (PDF_STORAGE, DESC_FILE, ID_PDF_STORAGE, LINK_FILE) SELECT * FROM PDF_STORAGE;
RENAME TABLE PDF_STORAGE TO PDF_STORAGE_old, PDF_STORAGE_new TO PDF_STORAGE;
DROP TABLE PDF_STORAGE_old;
SET FOREIGN_KEY_CHECKS = 1;
but they are also slow.. is there a better way?
Thanks
What you are doing now ALTER TABLE is the best approach to my knowledge. You can try making this change when there is not much transaction (or) DB operation going on. I mean say, do the changes in idle time.
ALTER TABLE PDF_STORAGE ADD VERSION INT NOT NULL DEFAULT '0' AFTER LINK_FILE ;
You can as well create a new table same as this table schema along with the new column.
Insert all the records from this table to the newly created table.
Rename the new table to the old table name.
delete the old table.
I'm supposed to write a trigger that checks BEFORE INSERT whether the record already exists, and then take some actions. I'm stuck with this error returned on issuing an INSERT statement against Koncerty view:
Error Code: 1347. 'BazyLista3.Koncerty' is not BASE TABLE
Here's the code for view Koncerty:
CREATE VIEW Koncerty (`nazwa_klubu`, `adres_klubu`, `nazwa_zespolu`,
`ilosc_czlonkow_zespolu`, `data_wystepu`) AS
( SELECT `nazwa_klubu`, `kb`.`adres`, `nazwa_zespolu`, `zs`.`ilosc_czlonkow`,
`data_wystepu` FROM `Koncert` AS kc
INNER JOIN `Klub` AS kb ON `kc`.`nazwa_klubu` = `kb`.`nazwa`
INNER JOIN `Zespol` AS zs ON `kc`.`nazwa_zespolu` = `zs`.`nazwa` );
And my trigger, where I have this error:
DROP TRIGGER IF EXISTS `before_koncerty_insert`
DELIMITER $$
CREATE TRIGGER `before_koncerty_insert` BEFORE INSERT ON `Koncerty`
FOR EACH ROW
BEGIN
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) INTO i FROM `Koncerty` WHERE
`nazwa_klubu` = NEW.`nazwa_klubu` AND
`adres_klubu` = NEW.`adres_klubu` AND
`nazwa_zespolu` = NEW.`nazwa_zespolu` AND
`ilosc_czlonkow_zespolu` = NEW.`ilosc_czlonkow_zespolu` AND
`data_wystepu` = NEW.`data_wystepu`;
IF i > 0 THEN
SIGNAL SQLSTATE '58005'
SET MESSAGE_TEXT = 'Blad! Taka krotka juz istnieje';
END IF;
END $$
DELIMITER ;
Tables
CREATE TABLE IF NOT EXISTS `Klub`
(
`nazwa` varchar(50) NOT NULL,
`adres` varchar(70) NOT NULL,
PRIMARY KEY (`nazwa`)
) ENGINE = InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `Zespol`
(
`nazwa` varchar(50) NOT NULL,
`ilosc_czlonkow` int(3) NOT NULL,
PRIMARY KEY (`nazwa`)
) ENGINE = InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `Koncert`
(
`nazwa_klubu` varchar(50) NOT NULL,
`nazwa_zespolu` varchar(50) NOT NULL,
`data_wystepu` datetime NOT NULL,
FOREIGN KEY (`nazwa_klubu`) REFERENCES `Klub`(`nazwa`),
FOREIGN KEY (`nazwa_zespolu`) REFERENCES `Zespol`(`nazwa`)
) ENGINE = InnoDB DEFAULT CHARSET=utf8;
How do I get around this issue?
MySQL does not support triggers on views.
The way to do this task is to make Koncerty a table without keys, in order to then operate on it with trigger actions. It all worked out just as I wanted.
Also, making UNIQUE CONSTRAINTS on records in tables does the job for the unique record, because it pops up an error when trying to add anything alike.
MySQL does not support triggers on views, from MySQL reference manual:
You cannot associate a trigger with a TEMPORARY table or a view.
The error might come if the view has used the database name in it. For example if a view has used a table as <dbname>.<tablename>:
create or replace view dealer_current_stage as
select
dsc.dealer_id,
dsc.new_stage current_stage,
dsc.change_date last_stage_change_date
from
dealer_current_stage_pre dcsp
left join
risk.dealer_stage_changes dsc ON dsc.change_date = dcsp.max_stage_change_date
and dsc.dealer_id = dcsp.dealer_id
group by dsc.dealer_id;
Here, risk is a different database and its table is being used. So better do not use the separate database and table, if you have to use it then consider the privileges, etc.
I have this table for users that stores their usernames and other data, thats done like this (stripped down):
CREATE TABLE `prod_users` (
`p_user_id` INT(11) NOT NULL AUTO_INCREMENT,
`p_user_name` VARCHAR(200) NOT NULL DEFAULT ''
`p_comp_name` VARCHAR(300) NOT NULL DEFAULT '',
PRIMARY KEY (`p_user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
Each time a user signs up, he'll provide a company name as well.
There's another table called prod_profiles, which stores profile details like phone nos. fax nos. etc.
CREATE TABLE `prod_profiles` (
`pf_gen_id` INT(11) NOT NULL AUTO_INCREMENT,
`pf_user_id` INT(11) NOT NULL DEFAULT '0',
`pf_user_name` VARCHAR(200) NOT NULL DEFAULT ''
`pf_comp_name` VARCHAR(300) NOT NULL DEFAULT '',
PRIMARY KEY (`pf_gen_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
When a new user signs up and his details are added to prod_users, is it possible to automatically add his new user_id, user_name and comp_name details to prod_profile using MySql itself? Since each user will have a new p_user_id and we wont know it, it'll be difficult using php. Can this be achieved inside MySql itself without any problems?
It isn't difficult using PHP, since you have the LAST_INSERT_ID() available for use, be it via mysql_insert_id() or mysqli::$insert_id, PDO::lastInsertId() or whatever your API provides. As long as you call the two INSERT statements in immediate succession on the same script (it is connection dependent), MySQL will supply the correct p_user_id.
However, you can use an AFTER INSERT trigger to force MySQL to create the new row automatically:
CREATE TRIGGER build_profile AFTER INSERT ON prod_users
FOR EACH ROW
BEGIN
INSERT INTO prod_profiles
(pf_user_id, pf_user_name, pf_comp_name)
VALUES (NEW.p_user_id, NEW.p_user_name, NEW.p_comp_name)
END
Review the MySQL CREATE TRIGGER syntax reference for full details and options.
You can use the next mysql function: LAST_INSERT_ID(); which returns the last auto increased id.
Therefore , add a user and then add a prod_profile , while pf_user_id value will be the returned value of last_insert_id().
INSERT INTO `prod_users`(`p_user_name`,`p_comp_name`) VALUES('Dan' , 'Stackover')
INSERT INTO `prod_profiles`(`pf_user_id`,`pf_user_name`,`pf_comp_name`) VALUES(LAST_INSERT_ID(),'Dan','Stackover')
Please notice: I have to say , that storing the username and company_name twice for the same user in two different tables is a reall waste...
Consider re-thinking about your DB structre and logic.
I'm new to mysql triggers and I'm trying to figure it out how should a trigger be created for the following case.
I have a table with the following structure:
CREATE TABLE `trigger` (
`group` int(3) NOT NULL,
`order` int(3) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`group`,`order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
This is how the table would look with some sample data:
The trigger that I want to create should make sure that, for each new record added with a given group, the order field is updated with the correct order index.
So, if I were to add a new record with the group 1, the order field will be automatically be updated to the next order which, for the given example would be 4.
The following statements inside a trigger should do the trick.
DECLARE neworder INTEGER;
SELECT max(`order`) + 1 INTO neworder FROM `trigger` WHERE `group` = NEW.`group`;
SET NEW.`order` = neworder;
BTW, it's not a great idea to use reserved words for table or column names.
You might want to reconsider your naming scheme.