Say I have the following table
//table user_update
update_id | userid | update_message | timestamp
Is there a way to set a maximum number of entries per userid? I want to make it so after a user types say 5 updates, any more updates entered after that deletes the oldest update. I know how to do this through PHP, just curious if there's any way to do this through MySQL only.
The only way I can think of doing this database-side would be to use a TRIGGER on the table. Maybe something like this:
CREATE TRIGGER check_for_too_many_rows
AFTER INSERT ON User_Update
FOR EACH ROW BEGIN
DO SOME LOGIC TO CHECK THE COUNT AND DELETE IF MORE THAN 5...
END;
Here is some additional information:
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
Good luck.
That is actually possible. but it is questionable if you really want to make that effort.
Read a little about 'triggers'. You can use a trigger to start an action when certain conditions are met. This way you can trigger a delete action on every insert action on that table. Then all that is left is a condition that up to five entries are kept.
Related
everyone! I'm making a simple todo app. I stopped on the one problem. I want to allow users to change the order of elements in a list (saving this to database).
One of first idea was:
Create a column (order) and change it every time when user do something.
It's good when we have a few records, but what with bigger number?
My thought:
id | name | order
1 | lorem| 1
2 | ipsum| 2
3 | dolor| 3
When user change "dolor" to first position, script must update all of records.
This isn't the best solution I think.
Anyone can share the knowledge how to optimize that?
I will be grateful!
You could use a column called next or previous. This is called a linked list, or if you use both, a double linked list. See:
https://en.wikipedia.org/wiki/Doubly_linked_list
Moving a record up one step in a database table would involve two steps:
Remove the record from the order.
Insert the record back into the order.
In all you would always need about five record changes for a double linked list, and a minimum of three records for a linked list.
If you want to store this data in a database, then an "ordering" column is appropriate.
Whenever you update or insert into the table, you will need to update this column (deletes are unnecessary). In general, you will need to update all the rows after the changed row. A trigger can do this work.
Cycling through rows is probably fine for a few dozen or even a few hundred rows (depending on how powerful your database is). So, depending on the length of the list, this is likely to be fine.
Any enhancements depend on additional factors. Some that I can think of:
How large will the lists really be?
What kind of transformations are most import? (Swaps? Inserts? deletes? updates?)
Will the transformations happen in bulk?
Will multiple users be changing the list at the same time.
I am trying to develop a system to assign room numbers to tenants of a hostel upon registration, using the auto increment feature of sql.
However, it automatically increases by one after every entry. Because the hostel accommodates four people in one room, I want to change this to 4, so that after every 4 entries I get only one id/room number.
How do I go about this? I am using php and sql. If the autoincrement feature is not possible can you please suggest another way to achieve this? Thanks.
You would need:
http://dev.mysql.com/doc/refman/5.1/en/replication-options-master.html#sysvar_auto_increment_increment
It works like this:
mysql> SET ##auto_increment_increment=4;
So when you insert 4 rows, the auto increment column will be:
4,8,12,16
as best of my knowledge you cannot change the steps of auto-increment field. I suggest add another field and write a trigger to update its value based on auto-increment field (auto-increment/4).
I don't think this is possible with autoincrement..
Maybe you can do something like this:
//Pseudo code
//First you get the count of the highest id, to see how many users are in the last room.
SELECT COUNT(*) FROM table WHERE id=(SELECT id FROM table ORDER BY id DESC LIMIT 1)
//If the result of the last query is >= 4 then insert the next customer with id +1
Don't use auto_increment for this - it can't handle a situation where multiple records will share the same number and although you can reset it manually (see below) it's also not designed for a situation where numbers may get reused in a random order.
You could just have a room_number field with one of the mysql integer types (e.g. tinyint, smallint, mediumint…) or you could separate your database into two tables, one for people (each of whom have an id) and a second to map those ids to rooms.
However you do it, you'd then write a select query to check which room numbers are available before you add the person's details to the database.
You may need to read up on relational databases if that doesn't sound very clear.
If you do need to reset the auto_increment (sometimes it's nice to do it if you've filled a database with test data which you're about to wipe, and you want the real "production" data to begin at 1) you can use:
ALTER TABLE [tablename] AUTO_INCREMENT = 1
https://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
I read the topic https://meta.stackexchange.com/questions/36728/how-are-the-number-of-views-in-a-question-calculated . I understand the algorithm, but I not understand how do that thing in mysql, php.
Every time a new hit is registered, it is also added to a memory buffer in addition to the expiring cache entry. The buffer itself also expires after a few minutes or after it is filled up to a certain size, whichever happens first. When it expires, everything it has accumulated is written into the database in bulk. They call it a "buffered write scheme".
We use Storage Engine -MEMORY in mysql or maybe better solution with mysql,php.
Can anyone help me how "buffered write scheme" for view counter with php, mysql.
Thanks very much.
Well it wont go faster than MySQL.
A stored procedure for your query can speed-up the process but database-design is the other half.
Make sure you got one table to count:
user_therad_visit:
----------------------------
user_id | thread_id | count
----------------------------
Make sure there is an index on or better a two-rows unique index on columns "user_id" and "thread_id".
When a user logs in, read his entire and thread_id and count values and save them in $_SESSION array.
This way you can check by $_SESSION var if the user has already visited the page or not and simply ignore fetching the database if he was already here, this will reduce queries drastically.
Then simply dont forgot to UPDATE your database incase the user has never been on this thread and also directly update your $_SESSION array manually.
With query helper:
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
you can simply combine insert into and update, (whatever is needed) into one query also improving performance.
This way a query is only fired when the user enters the thread first time which you have no choice but to write down somewhere and a database is one of the fastest ways to do that.
Aslong as your thread_id and user_id fields are indexed you should be pretty fast with the SELECT query, even with a million rows in the table.
Hi my qouestion is how to get the first number that is not used in specific database row. The number must be betwen 1 and 9999 and must be compared with all numbers in that specific database row, so if data in my database row starts with 5, i wont to be able to get the first number that is not used ...in this case the number 1. then when I create data with number 1.. the next number I need to get is 2 and...I'm using that to create profiles, and that number is the profile number, and ewery new profile must have the first unused number in data base. How to do that. I don't know where to start. So if someone can put me on the right path for solution of this problem? Thanks.
the edit
But, I dont need the auto increment i need to user to be able choosing this number on his own, first, this first number must bee suggested to the user by placeing it in the text form. And if the user select the number that is alredy in the database my program whil let the user know that he is trying to select the number that is allredy exist. So if you understand me ...I know the basics of mysql. The problem comes when the user deletes one profil then the deleted number can't be used eny more. For that i need the functio first free unused number.
New edit
I'l try to clear up some details...Frst this is the program for human resources and the user creates the dosies of workers... when user is creating the new dosie hee needs to select the dosie number for this worker, now I need to sugest to user the first unused number for the new dosie... the dosie number is not the dosie 'id'. Dosie number must be selected manualy by user or he can let the first free number to given to the new dosie... I think this whill clear some things
You are probably talking about auto-Increment primary key of table rows. Just insert the data, without specifying this "number" and the database will automatically set it to the proper (next free) value.
Do not reuse primary keys (eg you have 1,2,3,4,5 but then delete 3 - if you reuse 3 you will not know at any future point that 3 was some other record that was actually deleted).
This, btw, is very basic database knowledge. Read some introduction tutorials on MySQL or any other SQL relational database.
You are trying to use bad the database.
May be you can look this: Finding the next available id in MySQL
First create a table with values 1 to 9999. Then, run this query once:
delete from table where id IN (select id from profiles)
This way, you get IDs that are not in the profiles table. The first one can be shown to the user. On saving the record, make sure to delete that ID from this table.
If I understood you correctly, this is what you are looking for.
If you are limited to using values 1 through 9999 I would probably setup the process as follows:
Add another table with two columns (id_tracker).
Populate id_tracker with id's 1 through 9999 defaulting is_used to 0.
Update id_tracker.is_used to 1 based on the contents of your table.
Add a delete, insert triggers to your table to update the id_tracker as necesssary.
And select empty ID's as follows SELECT id FROM id_tracker WHERE is_used = 0 ORDER BY id LIMIT 1
Here's some SQL to get you started:
create table id_tracker
(id int not null, is_used tinyint default 0, primary key (id));
delimiter |
CREATE TRIGGER your_table_delete_trigger BEFORE DELETE ON your_table
FOR EACH ROW
BEGIN
UPDATE id_tracker SET is_used = 0 WHERE id = OLD.your_table_id;
END;
|
CREATE TRIGGER your_table_insert_trigger AFTER INSERT ON your_table
FOR EACH ROW
BEGIN
UPDATE id_tracker SET is_used = 1 WHERE id = NEW.your_table_id;
END;
|
delimiter ;
** NOTE: the above is for MySQL
I have a table called 'messages' (INNODB) where the user can insert their own posts.
I want to put a limitation. In my php script when the table gets to 10 records, you can not add more. The logic of the program is more or less as follows.
Step 1. I run a query to count the lines that are in the table.
Step 2. Recovered that value, I decide whether to insert a new post.
My difficulty is in properly managing the possibility of two user who do the same thing simultaneously. If the user A is in step 1 while user B has just finished entering the tenth post, user A will include the eleventh.
How to avoid it?
You can create CHAR(1) NOT NULL field and cover it with UNIQUE INDEX. This will prevent of inserting more than 10 rows.
Other solution that could work would be to create BEFORE INSERT trigger that checks number of rows and raises error if there are more than 10 (look here for sample) (but in this case you can fail with condition races).
In order to allow you to change your threshold value for the table, you can use a trigger. Because MySQL triggers don't have a "prevent INSERT" option, you need a value in your table set to NOT NULL. The trigger can then set the inserted value for that column to NULL which will prevent the INSERT if your condition check fails.
A trigger like this:
CREATE TRIGGER block_insert
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
DECLARE count INT;
SELECT COUNT(*)
FROM table_name INTO count;
IF count >= 10
THEN
SET NEW.non_nullable_value = NULL;
END IF;
END;
would fail if you inserted an 11th row, like this:
ERROR 1048 (23000): Column 'non_nullable_value' cannot be null
You may wish to set the non-nullable column's name to something that represents its use. You could improve this by having the trigger pull the limit value from a configuration table.
Update
To avoid having to use the non-nullable columns, you could alternatively create an error procedure, and CALL it from your trigger - similar to the example in the "Emulating Check Constraints" section of this page - they're referencing Oracle databases, where a check constraint achieves what you want, but MySQL doesn't support them.
The "error procedure" in the example performs an INSERT of a duplicate row into an error table, causing a unique key error and stops the parent transaction also.
Update 2
As pointed out in the comment below, multiple simultaneous transactions may get round the checks - you'll have to use LOCK TABLES <name> WRITE in order to ensure that they can't.
2/ You can also lock the MySQL table.
execute : LOCK TABLES my_table
Then do your business rules.
execute : UNLOCK TABLES
This also ensure that each action is sequentially executed. (but you have to deal with performance overhead)
Hope this could be useful.
Updated since the comments below : transaction don't work in this case
1/ You are using InnoDB, you can also use database transaction
Open transaction
Then do your business rules.
Commit or rollback your transaction
This will ensure that each action are executed one after another.