How do I limit the total columns and rows in mysql - mysql

How do I limit the total column to 10 columna and total rows to 500 data per table in Mysql

Like P.Salmon suggested,we can restrict users from altering table structures. This can be done by revoking their ALTER privilege on said tables. e.g revoke alter on testdb.thistable from thisuser; As to limit the total rows , we can use a trigger to check the existing row number every time a new row is to be inserted. If the limit is reached, abort the INSERT as well as raise a warning. The trigger looks like this:
delimiter //
drop trigger if exists check_row_limit ;
create trigger check_row_limit before insert on thistable for each row
begin
if (select count(*) from thistable) >= 500 then
signal SQLSTATE VALUE '99999' SET MESSAGE_TEXT = 'The number of rows has reached the limit. INSERT fails. ';
end if;
end//
delimiter ;

Related

How to add a max item limit to mysql database?

I want to add a limit to how many items my table can have. I want the maximum amount of items to be 10. I want it to only be 10 people in my table. I dont want it to be able to add items after the 10th person. Here is my code:
CREATE TABLE person (
name VARCHAR(233) NOT NULL,
number int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(number),
Check(number>10))
delimiter //
create trigger limit_persons before insert on person for each row
begin
declare count integer
select COUNT(*) FROM person INTO count;
if count>=10 then
signal sqlstate '45000' set message_text = 'Limit exceeded';
end if;
end
//
I would advise to handle such stuff as limitations in the software itself. So you have control over it later and it is overall a cleaner solution. But you can try this, if you really want to limit it in mysql:
ALTER TABLE tbl_name MAX_ROWS=10 AVG_ROW_LENGTH=nnn;
You can also check out triggers and signals:
https://dev.mysql.com/doc/refman/5.5/en/signal.html
https://dev.mysql.com/doc/refman/5.5/en/trigger-syntax.html
You can set up a trigger (to be specific, an Insert trigger) that counts the records and, if count is more than 10, it does not allow the insert operation.
Following code will be helpful to you,
DELIMITER $$
CREATE TRIGGER LimitRowCountTrigger
BEFORE INSERT
ON person
FOR EACH ROW
BEGIN
SELECT COUNT(*) INTO #cnt FROM person;
IF #cnt > 10 THEN
CALL sth(); -- raise an error
END IF;
END
$$
DELIMITER ;

Trigger to Insert data in a table before updating a column MYSQL

I want to create a trigger that inserts a timestamp to table log before I update column within a table. For example if I update table hits column number from 1 to 2. I want the time recorded before the column was updated, but this record of the time the update was done must only be when hits.number is updated. How can this be done?
You just need to check if old.number <> new.number then insert.
mysql> delimiter //
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON hits
-> FOR EACH ROW
-> BEGIN
-> IF NEW.number <> OLD.number THEN
-> INSERT ...
-> END IF;
-> END;//

create a trigger to for conditional update on same table

delimiter //
create trigger T1 before update on account
for each row
if NEW.balance <= 0 then
update account set balance=OLD.balance;
end if;
//
Query OK, 0 rows affected (0.09 sec)
delimiter ;
update account set balance=-1 where id=101;
ERROR 1442 (HY000): Can't update table 'account' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
MySQL uses row level triggers, so the trigger is fired for each row that is being changed. Because of that there is no reason to update the target table, just assign the value:
create trigger T1 before update on account
for each row
if NEW.balance <= 0 then
set new.balance = OLD.balance; -- this is the difference
end if;
SQLFiddle example: http://sqlfiddle.com/#!2/34aebb/1
Your update wouldn't have worked anyway because it was missing a where clause which means you would have updated the entire table just because a single row was changed.

How to limit total no of rows in mysql table

I want a table maximum rows to 100, If i add 101 row to that table, the 1 row should delete automatically. likewise i just want table total row count to 100, delete order should be FIFO.
Is there any direct MySQL function for that?
Use BEFORE INSERT trigger for this.
Below, I kept limit of 25, set according to your need.
DELIMITER $$
CREATE TRIGGER trigger1
BEFORE INSERT
ON table1
FOR EACH ROW
BEGIN
SELECT COUNT(*) INTO #cnt FROM table1;
IF #cnt >= 25 THEN
CALL sth(); -- raise an error
END IF;
END
$$
DELIMITER ;
You can a simple trigger like below:
CREATE TRIGGER Deleter AFTER INSERT on YourTable FOR EACH ROW
BEGIN
Delete from yourTable where ID = (Select MIN(id) from yourTable);
END;
Same as :
How do you make a threshold or limit mysql table?

Creating a trigger to update a sort/order column

I have created this trigger to update the seq column. I have to keep track of the order of certain items in the table, but only if the liability_category_id = 1,2. So my ordering is tricky because any item with a liability_category_id = 3 I don't need to track.
In my trigger, I'm querying to find the last entered seq number (using max(seq)), then turning around and updating the new entry with the seq + 1.
DELIMITER $$
USE `analysisdb`$$
DROP TRIGGER /*!50032 IF EXISTS */ `trigger_liability_detail_after_insert`$$
CREATE
/*!50017 DEFINER = 'admin'#'%' */
TRIGGER `trigger_liability_detail_after_insert` AFTER INSERT ON `liability_detail`
FOR EACH ROW BEGIN
DECLARE SortOrder INT;
IF NEW.liability_category_id = 1 OR NEW.liability_category_id = 2 THEN
SET SortOrder = (SELECT MAX(seq) FROM liability_detail WHERE analysis_id = new.analysis_id AND liability_category_id IN (1, 2));
UPDATE liability_detail SET seq = (SortOrder + 1) WHERE id = NEW.id;
END IF;
END;
$$
DELIMITER ;
However, when entering a new item, I get this error: Can't update table 'liability_detail' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Is there a better way to control the ordering of these items? My original thought was to simply set the first seq = 1, then seq = 2, etc. The ordering is reset for each new analysis_id though.
I think the workaround is to make this a before trigger and update the record being insert itself prior to insert.
So
CREATE
/*!50017 DEFINER = 'admin'#'%' */
TRIGGER `trigger_liability_detail_after_insert` BEFORE INSERT ON `liability_detail`
FOR EACH ROW BEGIN
DECLARE SortOrder INT;
IF NEW.liability_category_id = 1 OR NEW.liability_category_id = 2 THEN
SET NEW.seq = 1 + IFNULL((SELECT MAX(seq) FROM liability_detail WHERE analysis_id = new.analysis_id AND liability_category_id IN (1, 2)), 0);
END IF;
END;
$$
That was a quick copy/paste, but it should be something along those lines.
That's going to be tricky to handle.
The easy answer is if this could be changed to a BEFORE INSERT FOR EACH ROW trigger,
then you could:
SET NEW.seq = (SortOrder + 1);
to set the value on the row BEFORE it gets inserted into the table. But you can't do that in an AFTER INSERT FOR EACH ROW trigger.
There are some performance and concurrency concerns with using a trigger. (You don't have any guarantee that you won't be generating a "duplicate" value for the seq column when concurrent inserts are running; but that may not be a show stopper issue for you.)
I would prefer the approach of using a simple AUTO_INCREMENT column for the whole table.
The values from that would be "in order" for all the rows, so a query like
... WHERE liability_category_id = 1 ORDER BY seq
would return rows "in the order" those rows were inserted. There would be "gaps" in the sequence number for a given liability_category_id, but the sequence (order) of the inserts would be preserved.
(NOTE: MyISAM has a nifty feature of an AUTO_INCREMENT column, let's it "increment" separately for different values of a leading column in an index. But that only works in the MyISAM engine, it doesn't work in InnoDB.)
Aside from an AUTO_INCREMENT column, I would also consider a TIMESTAMP DEFAULT CURRENT_TIMESTAMP column to record the date/time when the row is inserted.
... WHERE liability_category_id = 1 ORDER BY timestamp_default_current ASC
Both of those approaches are simple column definitions, and do not require any procedural code to be written or maintained.