My sql script is like this :
CREATE
EVENT `deleteEvent`
ON SCHEDULE EVERY 30 MINUTE STARTS '2016-03-23 00:00:00'
ON COMPLETION NOT PRESERVE
ENABLE
DO
DELETE FROM hotel;
ALTER TABLE hotel AUTO_INCREMENT = 1;
I don't using truncate. Because, there is error like this :
Cannot truncate a table referenced in a foreign key constraint.........
So, I using Delete and alter
But, when using delete and alter, it's not working
Any solution to solve my problem?
Thank you
you can try: so you can use TRUNCATE if clear both Tables. After Truncate the Auto_inc is also 1
SET foreign_key_checks = 0;
TRUNCATE FROM hotel;
TRUNCATE FROM ConstraintsTable;
SET foreign_key_checks = 1;
You can set more queries like this:
DELIMITER //
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
BEGIN
SET foreign_key_checks = 0;
TRUNCATE FROM hotel;
TRUNCATE FROM ConstraintsTable;
SET foreign_key_checks = 1;
END
//
DELIMITER ;
Related
This is a continuation of this question: Insert data into a table with a foreign key SQL
I need to create a trigger that updates a counter variable after I insert a row into a table. The counter variable keeps track of how many new rows are inserted into the ItemBook table. However, after running the script, the trigger doesn't seem to be working. Also how can I reuse this trigger if I have created it already?
CREATE TABLE count (
countBook INT DEFAULT 0 NOT NULL,
);
CREATE
TRIGGER count_trigger AFTER INSERT
ON ItemBook
FOR EACH ROW
UPDATE count
SET countBook = (SELECT COUNT(*) FROM Itembook)
INSERT INTO Item
VALUES('Clippers','amazon.com', 'hair clippers');
SET SQL_SAFE_UPDATES = 0;
INSERT INTO ItemBook
VALUES('Clippers','Bob')
SET SQL_SAFE_UPDATES = 1;
SELECT * FROM count;
The countBook column returns nothing after running the script. Furthermore, if I try to rerun this script again it will say Trigger already exists (after creating it). How do I reuse this trigger?
The trigger would look something like this:
CREATE TRIGGER count_trigger AFTER INSERT ON ItemBook
FOR EACH ROW
BEGIN
UPDATE count
SET countBook = countBook + 1;
END;
It seems very curious to have a table with one row for this information. But this appear to be what you are trying to do.
I know this is against normalization rules, but how can I (if it is possible) set default value for column as a query, eg.:
ALTER TABLE Data
ALTER Sum SET DEFAULT SELECT Total*0.15 FROM Data;
Assuming to trigger on UPDATE:
DELIMITER $$
CREATE TRIGGER after_data
AFTER UPDATE ON Data
FOR EACH ROW BEGIN
UPDATE Data
SET NEW.Sum = (SELECT OLD.Total * 0.15)
END$$
DELIMITER ;
I'd like to make a TIMESTAMP field DEFAULT CURRENT_TIMESTAMP, for 'creation time' purpose. But if someone or somehow something changes that TIMESTAMP, my data won't be consistent.
Is there a way I can ensure it won't change unless I delete the row and reinsert it, other than application level?
With the suggested answer provided, i could work around with something like this
CREATE TRIGGER consistency1 BEFORE UPDATE ON table1
FOR EACH ROW
BEGIN
IF NEW.creationtime != OLD.creationtime THEN
SET NEW.creationtime = OLD.creationtime;
END IF;
END;
Since my comment has been appreciated, here's the extended version.
I personally don't think that it's possible.
Anyway, there are a couple of things you can try:
Make sure that only your application can write on the database
Write a trigger like this (pseudocode!)
create trigger prevent_change_timestamp on tbl_name
before update
#fetch old row value
#verify if the timestamp field has been changed
#raise an error (any SQL error will do)
Or like this
create trigger revert_change_timestamp on tbl_name
after update
#fetch pre-change row value
#update the row with the "old" value in place of the new one
I'd personally go with the 3rd option, if possible. Anyway, the 2nd one is good too. I'd not rely on the 1st option unless necessary (eg: no access to trigger functionality)
More info here: reference
It's funny in a way that database apps don't offer this functionality as standard: not only for a "created" timestamp field, but for things like autoincrement id fields, and any miscellaneous values which you may want to set on creating a record and then never allow to be changed... wonder what the rationale is?
What you can do here is, you can write a TRIGGER on the table when a row is being updated. In that trigger, you can compare the old and new values, and if they are different then you can just overwrite the new value with the old one.
I tried this in MySQL 5.1 and got an error
DELIMITER //
CREATE TRIGGER member_update_0
-> AFTER UPDATE ON members
-> FOR EACH ROW
-> BEGIN
-> IF NEW.id != OLD.id THEN
-> SET NEW.id = OLD.id;
-> END IF;
-> END;//
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
The same trigger with AFTER replaced by BEFORE is accepted;
to me, this is a counter-intuitive way to do it, but it works
delimiter ;
UPDATE members SET id=11353 WHERE id=1353;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
It is actually possible to do this very neatly if you are using InnoDB.
Create another table with just one column. That column should have a foreign key (hence the innodb requirement in this solution) that points to the immutable column of the original table in question.
Put a restriction like "ON UPDATE RESTRICT".
In summary:
CREATE TABLE original (
....
immutable_column ...
INDEX index1(immutable_column)
....
) ENGINE=INNODB;
CREATE TABLE restricter (
.....
col1,
INDEX index2(col1),
FOREIGN KEY (col1) REFERENCES original (immutable_colum) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE=INNODB;
Taking the idea a step further (for those of us still stuck with a legacy version of MySQL) you can have BOTH a protected & defaulted create_stamp AND an auto-updating update_stamp as follows:
If you have a table such as
CREATE TABLE `csv_status` (
`id` int(11) NOT NULL primary key AUTO_INCREMENT,
`create_stamp` datetime not null,
`update_stamp` timestamp default current_timestamp on update current_timestamp,
`status` enum('happy','sad') not null default 'happy'
);
Then you can define these triggers on it
drop trigger if exists set_create_stamp ;
create definer = CURRENT_USER trigger set_create_stamp BEFORE INSERT on
csv_status for each row
set NEW.create_stamp = now();
drop trigger if exists protect_create_stamp ;
delimiter //
create definer = CURRENT_USER trigger protect_create_stamp BEFORE UPDATE on
csv_status for each row
begin
if NEW.create_stamp != OLD.create_stamp then
set NEW.create_stamp = OLD.create_stamp;
end if;
end;//
delimiter ;
I need to delete all rows from a table but when I add a new row, I want the primary key ID, which has an auto increment, to start again from 0 respectively from 1.
Do not delete, use truncate:
Truncate table XXX
The table handler does not remember the last used AUTO_INCREMENT value, but starts counting from the beginning. This is true even for MyISAM and InnoDB, which normally do not reuse sequence values.
Source.
If you cannot use TRUNCATE (e.g. because of foreign key constraints) you can use an alter table after deleting all rows to restart the auto_increment:
ALTER TABLE mytable AUTO_INCREMENT = 1
If table has foreign keys then I always use following code:
SET FOREIGN_KEY_CHECKS = 0; -- disable a foreign keys check
SET AUTOCOMMIT = 0; -- disable autocommit
START TRANSACTION; -- begin transaction
/*
DELETE FROM table_name;
ALTER TABLE table_name AUTO_INCREMENT = 1;
-- or
TRUNCATE table_name;
-- or
DROP TABLE table_name;
CREATE TABLE table_name ( ... );
*/
SET FOREIGN_KEY_CHECKS = 1; -- enable a foreign keys check
COMMIT; -- make a commit
SET AUTOCOMMIT = 1 ;
But difference will be in execution time. Look at above Sorin's answer.
if you want to use truncate use this:
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table $table_name;
SET FOREIGN_KEY_CHECKS = 1;
An interesting fact.
I was sure TRUNCATE will always perform better, but in my case, for a database with approximately 30 tables with foreign keys, populated with only a few rows, it took about 12 seconds to TRUNCATE all tables, as opposed to only a few hundred milliseconds to DELETE the rows.
Setting the auto increment adds about a second in total, but it's still a lot better.
So I would suggest try both, see which works faster for your case.
I want to execute multiple command to update a customer database, but I want this command to execute in a transaction, and when an error occurs in one command all changes would be rolled backed.
When I run the code in this example, if test2 table has existed the rollback has not worked and the inserted row exists in test table.
What am I doing wrong?
MySQL server is 5.1.
the engine of tables is Innodb.
code example:
set autocommit = 0;
drop procedure if EXISTS rollbacktest;
delimiter //
CREATE PROCEDURE rollbacktest ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION,SQLWARNING SET #x2 = 4;
SET autocommit = 0;
start transaction;
SET #x2 = 0;
insert into test(t)values (800);
CREATE TABLE `test2` (
`t` int(11) UNSIGNED NOT NULL
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_persian_ci ;
if #x2 = 4 THEN ROLLBACK; else commit; end if;
END;
//
CALL rollbacktest()
Your problem is that you're doing DDL (CREATE TABLE), which cannot be done in a transaction, so it'll implicitly commit the stuff you've done before.
This will also be the case if you tro to do DROP TABLE, ALTER TABLE, or TRUNCATE TABLE, among other things. Essentially any statement that cannot be rolled back will cause existing transactions to be auto-COMMITed
If I remember correctly, the CREATE TABLE implicitly commits the transaction.
http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html