Using mysql triggers to update fields part of a composite primary key - mysql

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.

Related

Auto create unique ID based on id

Based on my question above, I have a MySQL table called qrc_creation. This table consists of columns like id (auto increment), creation_code, and creation_name. For example, if I want to insert a new creation_name, the ID will auto 1. But, I also want the creation_code to become qrc_00000001, where 1 comes from ID.
Thus, can I know what is the query to do this? Thank you in advance!
You have two options. If you want, the column to autopopulate during insert, you can use MySQL generated columns while defining table schema. However, you cannot use Auto Increment column with this method.
CREATE TABLE `table_1` (
`id` INT(10) ZEROFILL NOT NULL,
`creation_name` VARCHAR(45) NOT NULL,
`creation_code` VARCHAR(55) GENERATED ALWAYS AS (CONCAT(`name`, '_', `id`)),
PRIMARY KEY (`id`));
If you don't want that dedicated column in your table, you can easily get calculated field on your SQL query by using a simple concat function.
SELECT
`id`, `creation_name`, CONCAT(`name`, '_', `id`) AS `creation_code`
FROM
table_1;
Hope it helps.
first of all you need to show your code so that stackoverflow community respond. But still i got your problem and given below is the solution-
CREATE TABLE qrc_creation
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
creation_code AS 'qrc' + RIGHT('0000000' + CAST(ID AS VARCHAR(7)), 7) PERSISTED,
creation_name varchar(255),
);
Select * from qrc_creation;
INSERT INTO qrc_creation(creation_name)
VALUES ('Monsen');
Select * from qrc_creation;
Hope you like my answer.

Let field value set sort order direction in Mysql

Given the following table:
CREATE TABLE `example` (
`Identifier` int(11) NOT NULL AUTO_INCREMENT,
`FieldValue` varchar(255) DEFAULT NULL,
`FieldOrder` enum('asc','desc') DEFAULT 'asc',
PRIMARY KEY (`Identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I want to run a query that sorts the FieldValue field based on the value in the FieldOrder field. E.g.
Select * from example order by FieldValue [here should the FieldOrder value be placed]
Is it possible to make a reference to the FieldOrder field in the sort by part of the query?
One way to approach this is to treat FieldValue as positive or negative for FieldOrder values of "asc" and "desc" respectively. This can be expressed by a case expression:
SELECT *
FROM example
ORDER BY CASE FieldOrder WHEN 'asc' THEN 1 ELSE -1 END * FieldValue
Not that I know of ...
Please note that every row has a FieldOrder so what you seek to achieve seems to be questionable. What if one row says asc and another row say desc? How should the order of the two rows be shown then?
If you want to have parameterized order by action, you can consider using the following two methods:
Use a stored procedure that takes an argument for, say,
sortingOrder
Use a programming language (e.g. Java) to construct a query string and
inject the sorting order dynamically, and
then execute the query string to MySQL
You need to normalize your data and store it in a better schema. Do not store multiple values in a single field, only store one value per row. What you can do is store the multiple data in its own table, where each piece of data is in its own row.
Try a schema like this:
CREATE TABLE `example` (
`Identifier` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`Identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `exampleData` (
`RowID` int(11) NOT NULL AUTO_INCREMENT,
`Identifier` int(11) NOT NULL,
`FieldValue` varchar(255) DEFAULT NULL,
PRIMARY KEY (`RowID`),
INDEX `Identifier` (`Identifier`),
FOREIGN KEY (Identifier) REFERENCES example(Identifier)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Now you have two tables, and in your exampleData table, you have one row per each piece of data in FieldValue.
Now you can query like so:
SELECT Identifier, FieldValue
FROM example
JOIN exampleData USING(Identifier)
WHERE Identifier = 3
ORDER BY FieldValue ASC

Creating a trigger that pulls information from another table in phpMyAdmin

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.

Adding a new non-nullable column to a table in MySQL

I have a table for an event, and I have just made a new table for ticketing_information. Each event in the event table should have a ticketing_information, referenced by a unique id. I'm new to sql, so forgive me if this is a very basic/repeated question, but how should I go about making the migration add a new row to the ticketing_information table for every existing event, and giving the event the generated ticketing_information id?
If it helps, some of my sql is attached:
CREATE TABLE `ticketing_information` (
`id` INT(10) unsigned NOT NULL AUTO_INCREMENT,
`tickets_available` BOOLEAN DEFAULT TRUE NOT NULL,
`ticketing_url` VARCHAR(2000) DEFAULT NULL,
`additional_info_url` VARCHAR(2000) DEFAULT NULL,
PRIMARY KEY (`id`);)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
ALTER TABLE event
ADD COLUMN ticketing_information_id Int(10) unsigned DEFAULT NULL;
(This is a very stripped-down version of the code, but it should help illustrate the behavior I want)
I was thinking it should be something along the lines of
UPDATE event SET
ticketing_information_id = SELECT `id` FROM `ticketing_information` WHERE <some way of making a new ticketing_information?>;
But I don't really know what I'm doing :)
how i would perform something like, adding a new non-nullable column to an existing table, would be:
adding that column in first step as nullable, otherwise you will not get the rdbms to modify the table, because it will violate the not null constraint.
updating the new column to the data you want it to have
UPDATE event e
SET e.ticketing_information_id = (SELECT `id` FROM `ticketing_information` WHERE id = e.id)
Your update needs to tell the inner select, which row it is currently updating, so you are able to filter only the data of that particular row in the inner select.
modifying the column to be not null

MySQL trigger delete passing user ID

I need to create MySQL trigger that would log user ID on delete table row statement which must fit in one query, since I'm using PHP PDO. This is what I've come up so far:
I need the way to pass user ID in the delete query even though it is irrelevant to delete action to be performed:
Normally the query would look like this:
DELETE FROM mytable WHERE mytable.RowID = :rowID
If I could use multiple queries in my statement, I would do it like this:
SET #userID := :userID;
DELETE FROM mytable WHERE mytable.RowID = :rowID;
This way the variable #userID would be set before trigger event fires and it can use it. However since I need to squeeze my delete statement in one query, so I came up with this:
DELETE FROM mytable
WHERE CASE
WHEN #userID := :userID
THEN mytable.RowID = :rowID
ELSE mytable.RowID IS NULL
END
Just a note: RowID will never be null since it's the primary key. Now I have to create a delete trigger to log the user ID to the audit table, however I suppose that in this case trigger will be fired before the delete query itself which means that #userID variable will not be created? This was my idea of passing it as a value to the trigger.
I feel like I'm close to the solution, but this issue is a blocker. How to pass user ID value to the trigger without having multiple queries in the statement? Any thoughts, suggestions?
You can use NEW / OLD mysql trigger extensions. Reference: http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
Here is a sample code :
drop table `project`;
drop table `projectDEL`;
CREATE TABLE `project` (
`proj_id` int(11) NOT NULL AUTO_INCREMENT,
`proj_name` varchar(30) NOT NULL,
`Proj_Type` varchar(30) NOT NULL,
PRIMARY KEY (`proj_id`)
);
CREATE TABLE `projectDEL` (
`proj_id` int(11) NOT NULL AUTO_INCREMENT,
`proj_name` varchar(30) NOT NULL,
`Proj_Type` varchar(30) NOT NULL,
PRIMARY KEY (`proj_id`)
);
INSERT INTO `project` (`proj_id`, `proj_name`, `Proj_Type`) VALUES
(1, 'admin1', 'admin1'),
(2, 'admin2', 'admin2');
delimiter $
CREATE TRIGGER `uProjectDelete` BEFORE DELETE ON project
FOR EACH ROW BEGIN
INSERT INTO projectDEL SELECT * FROM project WHERE proj_id = OLD.proj_id;
END;$
delimiter ;
DELETE FROM project WHERE proj_id = 1;
SELECT * FROM project;
SELECT * FROM projectDEL;