mysql how to update a foreign key automatically - mysql

this is my tables
CREATE TABLE IF NOT EXISTS `carslibrary` (
`CarID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`CarName` varchar(255) NOT NULL,
PRIMARY KEY (`CarID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
CREATE TABLE IF NOT EXISTS `colorslibrary` (
`ColorID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`ColorName` varchar(255) NOT NULL,
PRIMARY KEY (`ColorID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
CREATE TABLE IF NOT EXISTS `facerecord` (
`carslibrary_ID` int(10) unsigned NOT NULL,
`colorslibrary_ID` int(11) unsigned NOT NULL,
KEY `carslibrary_ID` (`carslibrary_ID`),
KEY `colorslibrary_ID` (`colorslibrary_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
i noticed carslibrary_ID attribute inside facerecord table is not automatically updated when i add a car record inside carslibrary table, what should i do to be able to?

Firstly, you'll need to have a default value specified for the facerecord.colorslibrary_ID since you will not 'know' what it is when inserting into the carslibrary table. That said you could alter your DDL for the facerecord table to be:
CREATE TABLE `facerecord` (
`carslibrary_ID` int(10) unsigned NOT NULL,
`colorslibrary_ID` int(10) unsigned NOT NULL DEFAULT '0',
KEY `carslibrary_ID` (`carslibrary_ID`),
KEY `colorslibrary_ID` (`colorslibrary_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I've also changed the datatype of the colorslibrary_ID column to match that of the colorslibrary.ColorID column in case you ever feel like setting up a foreign key between facerecord.colorslibrary_ID and colorslibrary.ColorID ;). For the sake of completeness you should insert a row into the colorslibrary table with a ColorID = 0. Hence:
insert into `colorslibrary` (ColorName) values ('unknown color');
update `colorslibrary` set ColorID = 0 where ColorName = 'unknown color';
Then you can go ahead and define your trigger to insert into the facerecord table:
delimiter $$
CREATE TRIGGER carslibrary_trigger
AFTER insert ON carslibrary
FOR EACH ROW
BEGIN
insert into facerecord (carslibrary_ID) values (new.CarID);
END$$
delimiter;
All new rows inserted into the facerecord table will then be inserted with a colorslibrary_ID that relates to the 'unknown color' colorslibrary.ColorName.You can then manually update the facerecord.colorslibrary_ID as and when you know it.
Good luck!
PS If you need to remove any existing AFTER insert triggers from the carslibrary table you can do so by firstly finding the existing triggers:
select trigger_name
from information_schema.triggers
where event_object_table = 'carslibrary'
and action_timing = 'AFTER'
and event_manipulation= 'INSERT';
Then take the name of the trigger returned by the above statement (lets say the string 'carslibrary_trigger' is returned) and run:
drop trigger carslibrary_trigger;
Then re-run the CREATE TRIGGER script.
Once a trigger is set up it will automatically perform the action you have specified when the trigger action you have specified occurs. In this case we are telling the database "after an insert happens into the carslibrary table automatically insert a row into the facerecord table using the CarID of the new carslibrary row to populate the facerecord.carslibrary_ID column". As with most things the best way is to try it! Once you have created the trigger manually insert a new row into the 'carslibrarytable. Now look at the data in thefacerecord` table - you should see a new row that has been inserted by the trigger firing.
It sounds like you would benefit from learning about triggers. I recommend the docs on the MySQL site because this answer is way longer than I first intended it to be!

You will need to use triggers. See http://dev.mysql.com/doc/refman/5.0/en/triggers.html

Related

Use the value of an attribute from another table as a default value of an attribute from another table in MYSQL

I wanted to use the value on student_lastname in table tbl_student as a default value of sis_password in
table tbl_sis_account but I am out of idea on how to do it. I tried putting "Select query" after the "Default" but it doesn'nt work, anyway here's the sql:
DROP TABLE IF EXISTS tbl_sis_account;
CREATE TABLE `tbl_sis_account`(
sis_account_id INT(15) NOT NULL AUTO_INCREMENT,
sis_username INT(15) NOT NULL,
sis_password VARCHAR(8) DEFAULT '====>Value of attribute student_lastname<====',
PRIMARY KEY(`sis_account_id`),
CONSTRAINT `sis_username_student_fk` FOREIGN KEY (`sis_username`) REFERENCES `tbl_student`
(`student_id`) ON UPDATE CASCADE
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
SELECT * FROM tbl_sis_account;
DROP TABLE IF EXISTS tbl_student;
CREATE TABLE `tbl_student` (
`student_id` INTEGER(15) NOT NULL AUTO_INCREMENT,
`student_firstname` VARCHAR(50) NOT NULL,
`student_midname` VARCHAR(50) NOT NULL,
`student_lastname` VARCHAR(50) NOT NULL,
PRIMARY KEY(`student_id`)
)ENGINE=INNODB AUTO_INCREMENT=20201 DEFAULT CHARSET=utf8mb4;
SELECT * FROM tbl_student;
No you can't do that, but you can query the tbl_student table at the time of insertion in the tbl_sis_account table to retrieve student_lastname from `student_id' via a nested sql query or a trigger.
I've figured the solution for this problem, for a while now. Forgot to post the answer though, coz I am no longer using this method. But here's what I did.
On the tbl_student I created a "After Insert trigger"
BEGIN
INSERT INTO tbl_sis_account (student_id,sis_password) values (new.student_id, concat(new.student,new.student_lastname));
END
so the inserted result on tbl_sis_account is
student_id | sis_password
20200001 | 202000001Doe

MySQL storing TIMESTAMP with milliseconds

I need to create a database to store some logs which can occurs once per millisecond.
I've created the following table:
CREATE TABLE `log` (
`DataEvento` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
`CodiceEvento` int(11) NOT NULL,
`IdApplicativo` int(11) NOT NULL,
PRIMARY KEY (`DataEvento`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
And a stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `ScriviEvento`(IN evt_id INT, IN app_id INT, IN evt_descr TEXT)
BEGIN
DECLARE timestamp_now TIMESTAMP(3) DEFAULT NOW(3);
INSERT INTO log (DataEvento, CodiceEvento, IdApplicativo) VALUES (timestamp_now, evt_id, app_id);
IF (LENGTH(evt_descr) > 0) THEN
INSERT INTO descrizionelog (DataEvento, DescrizioneEvento) VALUES (timestamp_now, evt_descr);
END IF;
END
Inserting manually some entries I get the correct timestamp with milliseconds but if I create a thread
with a Sleep(1) I got duplicate key error, same happens if I press execute button fast in workbench with
CALL(1, 0, '');
Is there a workaround to this (excluding using an auto-increment id), or am I doing something wrong?
You are doing something wrong by assuming that the timestamp is going to be unique for log records. That really doesn't make sense.
I'm not sure why you are opposed to an auto-increment solution. This would be the right approach:
CREATE TABLE `log` (
LogId int auto_increment primary key,
`DataEvento` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
`CodiceEvento` int NOT NULL,
`IdApplicativo` int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

SQL #1064 - You have an error in your SQL syntax; near `` in Joomla component install

Hi I am trying to create a trigger in Joomla component installation, However it seems doesn't work
error msg
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 4 SQL=CREATE TRIGGER tg_jws_worksheet_worksheet_insert BEFORE INSERT ON jws_worksheet_worksheet FOR EACH ROW BEGIN INSERT INTO jws_worksheet_worksheet_seq (id) VALUES (NULL);
here is the code
--
-- Table structure for table `client`
--
DROP TABLE IF EXISTS `#__worksheet_client`;
CREATE TABLE IF NOT EXISTS `#__worksheet_client` (
`ClientID` int(11) NOT NULL,
`CompanyId` int(11) NOT NULL,
`FullName` text NOT NULL,
`Email` text,
`ContactNo` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Table structure for table `company`
--
DROP TABLE IF EXISTS `#__worksheet_company`;
CREATE TABLE IF NOT EXISTS `#__worksheet_company` (
`CompanyId` int(5) NOT NULL,
`ABN` int(12) NOT NULL,
`CompanyName` text NOT NULL,
`Street` text,
`City` text,
`State` text,
`PostCode` int(5) DEFAULT NULL,
`Country` text,
`Phone` text,
`HourRate` int(11) NOT NULL,
`Notes` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Table structure for table `worksheet_seq`
--
DROP TABLE IF EXISTS `#__worksheet_worksheet_seq`;
CREATE TABLE IF NOT EXISTS `#__worksheet_worksheet_seq` (
`id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Table structure for table `worksheet`
--
DROP TABLE IF EXISTS `#__worksheet_worksheet`;
CREATE TABLE IF NOT EXISTS `#__worksheet_worksheet` (
`worksheetNo` varchar(9) NOT NULL,
`CompanyId` int(5) NOT NULL,
`UserId` int(5) NOT NULL,
`CompanyName` text NOT NULL,
`Category` varchar(20) NOT NULL,
`JobTitle` text NOT NULL,
`JobDesc` text NOT NULL,
`StartDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`EndDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`TimeSpd` int(11) NOT NULL,
`Tech` text NOT NULL,
`Status` varchar(8) NOT NULL,
`Hardware` text,
`Price` int(11) NOT NULL,
`file` text
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET FOREIGN_KEY_CHECKS=1;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `client`
--
ALTER TABLE `#__worksheet_client`
ADD PRIMARY KEY (`ClientID`), ADD KEY `CompanyId` (`CompanyId`);
--
-- Indexes for table `company`
--
ALTER TABLE `#__worksheet_company`
ADD PRIMARY KEY (`CompanyId`);
--
-- Indexes for table `worksheet`
--
ALTER TABLE `#__worksheet_worksheet`
ADD PRIMARY KEY (`worksheetNo`), ADD KEY `CompanyId` (`CompanyId`);
--
-- Indexes for table `worksheet_seq`
--
ALTER TABLE `#__worksheet_worksheet_seq`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `client`
--
ALTER TABLE `#__worksheet_client`
MODIFY `ClientID` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `company`
--
ALTER TABLE `#__worksheet_company`
MODIFY `CompanyId` int(5) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT for table `worksheet_seq`
--
ALTER TABLE `#__worksheet_worksheet_seq`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `client`
--
ALTER TABLE `#__worksheet_client`
ADD CONSTRAINT `client_ibfk_1` FOREIGN KEY (`CompanyId`) REFERENCES `#__worksheet_company` (`CompanyId`);
--
-- Constraints for table `worksheet`
--
ALTER TABLE `#__worksheet_worksheet`
ADD CONSTRAINT `worksheet_ibfk_1` FOREIGN KEY (`CompanyId`) REFERENCES `#__worksheet_company` (`CompanyId`);
--
-- Triggers `worksheet`
--
DROP TRIGGER IF EXISTS `tg_#__worksheet_worksheet_insert`;
CREATE TRIGGER `tg_#__worksheet_worksheet_insert` BEFORE INSERT ON `#__worksheet_worksheet`
FOR EACH ROW
BEGIN
INSERT INTO `#__worksheet_worksheet_seq` (`id`) VALUES (NULL);
SET NEW.worksheetNo = CONCAT('WS-', LPAD(LAST_INSERT_ID(), 5, '0'));
END
create trigger usually requires redefining the delimiter:
DELIMITER $$
DROP TRIGGER IF EXISTS `tg_#__worksheet_worksheet_insert`$$
CREATE TRIGGER `tg_#__worksheet_worksheet_insert` BEFORE INSERT ON `#__worksheet_worksheet`
FOR EACH ROW
BEGIN
INSERT INTO `#__worksheet_worksheet_seq` (`id`) VALUES (NULL);
SET NEW.worksheetNo = CONCAT('WS-', LPAD(LAST_INSERT_ID(), 5, '0'));
END$$
DELIMITER ;
I had the same issue with Joomla 2.5, unable to create a trigger during the install or update procedure while the sql statements work fine.
You will not be able to create a trigger, function, procedure or any sql statement containing more than 1 semi-colon (;). That's why all other statements seem to work in your script.
I tried many appoaches which did not work including these:
In the manifest file use sql-file:
<install>
<sql>
<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
</sql>
</install>
In the manifest file use install-queries:
<install>
<queries>
<query id="1">
CREATE TRIGGER `...` AFTER UPDATE ON `#__...` FOR EACH ROW
BEGIN
...codeline...;
...codeline...;
END
</query>
<query id="2">
...
</query>
</queries>
</install>
(sorry for using blockquotes in stead of code sample, otherwise post will not be shown correctly)
The only way it did work was via the installscript option available since Joomla 2.5, see https://docs.joomla.org/J2.5:Developing_a_MVC_Component/Adding_an_install-uninstall-update_script_file.
This did not work out-of-the-box. I had to remove the access check (the first line with define) and put the following code in the install($parent) and update($parent) functions to add the trigger:
$db = JFactory::getDbo();
$db->setQuery("DROP TRIGGER IF EXISTS `...`");
$db->query();
$query="CREATE TRIGGER `...` AFTER UPDATE ON `#__...` FOR EACH ROW
BEGIN
...codeline...;
...codeline...;
END";
$db->setQuery($query);
$db->query();
if ($error = $db->getErrorMsg()) {
$this->setError($error);
return false;
}
...next sqlstatement or code...
return true;
Make sure the classname in this installer php file matches your component name including init caps, something like:
class com_YourComponentNameInstallerScript
And also, don't forget to open the file with <?php tag but do not put the ?> end tag at the end.
Save the file as php file in the root of your install package at the same level as the manifest file, and add this filename to the manifest file at somewhere between the component description and administration or site tags:
<scriptfile>yourcomponentname_install.php</scriptfile>
This method will also work with creating Stored Procedures and Functions.

How to create trigger to insert data to a database on another server

I have 2 mysql databases on different hosts, want trigger after insert data to one database it inserted to another . I'm new in mysql , in sql server I can create linked server and do it . But how to do in mysql ?
Both databases have similar table
CREATE TABLE `tsttbl` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`age` smallint(6) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
For you to be able to proceed with this, you must first ensure that both servers have identical configurations. And to accomplish what you are wanting to do, it is possible to use the FEDERATED storage engine on both servers, in conjunction with triggers, to allow each server to update the other server's database.
You need to create the local table that is federated to the user table on the other server. So, if a record already exists on the other server, but not here, we want the insert on the other server to throw an error that prevents us from creating the record here... as opposed to creating a record here with what would be a conflicting ID;
CREATE TABLE remote_user (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`age` smallint(6) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
CONNECTION='mysql://username:pass#the_other_host:port/schema/user';
Then you can create your trigger;
DELIMITER $$
CREATE TRIGGER user_bi BEFORE INSERT ON user FOR EACH ROW
BEGIN
INSERT INTO remote_user (ID,name, age) VALUES (NEW.ID,NEW.name, NEW.Age);
END $$
CREATE TRIGGER user_bu BEFORE UPDATE ON user FOR EACH ROW
BEGIN
UPDATE remote_user
SET ID= NEW.ID,
name= NEW.name
age = NEW.Age
WHERE ID = OLD.ID;
END $$
CREATE TRIGGER user_bd BEFORE DELETE ON user FOR EACH ROW
BEGIN
DELETE FROM remote_user
WHERE ID= OLD.ID;
END $$
DELIMITER ;

MySQL: How to create trigger for setting creation date for new rows

I ran into a problem as I tried to create two TIMESTAMP columns in my database. One called created and one called updated. I figured it would be easy to set the default value of both to CURRENT_TIMESTAMP and then ON UPDATE CURRENT_TIMESTAMP for the updated column. But for some reason MySQL means that's a bad idea... so I have been looking for ways to do this without having to set one of them in the insert query.
I found one way by using a trigger in this answer, but I keep getting errors. I just managed to actually create the trigger, but now I get errors when I try to insert new rows claiming that
1442 - Can't update table 'tasks' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
And I don't get what that means at all. So, I was hoping someone here could shed some light up this subject.
The SQL I used to create the table and the trigger is as follows:
CREATE TABLE `tasks` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`created` DATETIME,
`updated` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`title` VARCHAR(255) NOT NULL,
`notes` TEXT,
`status_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
KEY `status_id` (`status_id`),
CONSTRAINT `fk_tasks_statuses` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TRIGGER task_creation_timestamp AFTER INSERT ON tasks
FOR EACH ROW
UPDATE tasks SET created = updated WHERE id = NEW.id;
What am I doing wrong here?
Your trigger needs to be "before insert", and you need to use SET instead of UPDATE:
CREATE TRIGGER task_creation_timestamp BEFORE INSERT ON tasks
FOR EACH ROW
SET NEW.created = NOW();