So, I have a table A that each time a user sends an image, a record is created storing the time it was uploaded, the username of the user and the image number out of all the images uploaded over time.
I need to make a second table B that will store the amount of images uploaded per user and the user name. I need this table B to be updated when a new entry is generated in A.
I found that a trigger function can be created, nevertheless I'm having a rough time finding an example that will suit my needs.
Does anyone know a way of doin what I want?
Just update b table with a select count of total inserted records on a from current user NEW.userid (userid is your column name or whatever name you have there, and NEW is a fixed mySql reference for the current values to be inserted):
CREATE TRIGGER img_sum AFTER INSERT ON a
FOR EACH ROW SET b.total = (SELECT COUNT(*) FROM a WHERE a.userid=NEW.userid)
WHERE b.userid = NEW.userid;
From what you have described i don't think you need a second table. You can just count the number of time a user name has occurred, and you will get the number of images that user has uploaded.
You can get the count doing something like that
SELECT COUNT(DISTINCT username) FROM table_name;
If you still need to create 2 tables, you might want to take a look at procedures and how they work.
Let's say we have 3 tables for this case:
- users(id, username, email ....),
- user_images(id, userId, image_num, date_uploaded)
- user_images_count(id, user_name, images_count)
The user_images_count is initially empty. We have to fill it up by such query:
INSERT into user_images_count(user_name, images_count)
SELECT (select username from users where ui.userId = id) as username, count(userId) as counter FROM `user_images` ui group by ui.userId;
Then, we must immediately create the trigger that will process every INSERT operation into user_images table.
CREATE TRIGGER `count_user_images` AFTER INSERT ON `user_images`
FOR EACH ROW begin
declare u_name tinytext default "";
set u_name = (select username from users where id = NEW.userId limit 1);
if(u_name != "") then
update user_images_count set images_count = images_count + 1 where user_name = u_name;
end if;
end
This two queries (user_images_count fulfillment and trigger creation must be performed in one transaction, one by one).
I've created similar triggers on my local databases. They work pretty good. )))
Related
I have the database where i save my records. The records was saved as
ID, name
example
Nick
Name
Username
Now when i delete the record with id 2. in my database it remains as
1. Nick
3. Username
I want that when i delete one record from database other id's automatic decrement for one value so i get.
1. Nick
2. Username
Do you understand my question. Sry for bad english
Button delete code
if(isset($_POST['tipkaobrisi'])) // pritisnuta tipka obrisi
{
$obrisankorisnik = $_POST['obrisi'];
if ( $obrisankorisnik == '' )echo "<div align='center'>Unesite korisnika kojeg zelite obrisati!</div>";
else
{
mysql_query("DELETE FROM Korisnici WHERE Korisnik ='$obrisankorisnik'");
echo "<div align='center'>Korisnik obrisan<br><br></div>";
}
}
That is not the intention of most ID columns. However, you can mimick this functionality by modifying the statement you use to access those records.
E.g. rather than using the ID value, use the following
select #rownum:=#rownum+1 as ID, name from users, (SELECT #rownum:=0) r order by id;
It will give each record returned a number, with no gaps. Depending on what you want this for, that may be enough. If you would like to treat this new ID value as the ID value, create a view and access your elements based on that, like so:
CREATE VIEW users_view as select #rownum:=#rownum+1 as ID, name from users, (SELECT #rownum:=0) r order by id;
at which point you can SELECT * FROM users_view WHERE ID = $id and have it work as usual. So long as you never insert a new record that is not auto incremented, this scheme should work.
Keep in mind that deleting anybody changes a bunch of IDs, so it's not recommended.
After listening other programer's advice's. I decide that i don't want to edit my ID's.
Thanks to all for participating.
So I have this script that needs to Update total uploads per user and store into the users table.
I have a function that can count the number of uploads made by each user but not stored into database, my site is already live and a busy site that I can't update this manually since the posts are non-stop.
Below is my function to count the uploads...
function get_row_count($table, $suffix = "") {
$res = SQL_Query_exec("SELECT COUNT(*) FROM $table $suffix");
$row = mysql_fetch_row($res);
return $row[0];
}
The users table looks like this
[users table]
id username numuploads numcomments
the uploads table looks like this
[uploads table]
fileid userid added enabled
So how can I run an SQL query to count the number of uploads per user from the uploads table and update it into each user's numuploads at once without doing it manually.
Thanks..
EDIT
UPDATE users SET numuploads = (SELECT COUNT(id) as numuploads FROM uploads WHERE owner = users.id)
Problem is solved now
Instead of selecting the the count as a separate query, then adding 1 and updating some DB column, You could do directly the update only:
UPDATE table SET number = number + 1 WHERE id = <ID>
This query should be run each time when a new comment/upload is done by that user and requires the number column to be of numeric type with default value set to 0 (zero). The above query is just an example that You should change to meet Your DB scheme.
I have events each with 50 maximum participants.
Every time a user signs up for an event, his name, email, and mobile no. gets saved in the database. So I am inserting these values whenever a sign up is made: ID, p_name, p_mobile, p_email, p_event the last column is the name of the event.
I need to add a new column called p_max wherein it will automatically increase by 1 for each unique event. A sort of counter.
So I can then check if the maximum is reached by getting the p_max column of the last row with the event name.
I hope I explained the question clearly. Feel free to ask questions for clarification.
Thanks in advance!
If I understand the question correctly, you would need to check for the number of users for a specific event before you confirm the sign-up.
So you would not need a new column (or it would be a column in the events table where you can specify the maximum number of participants per event), you need to check how many users there already are for that specific event.
You could use something like this to query the database:
SELECT COUNT(*) as number_of_participants FROM users WHERE p_event = YOUR_EVENT_ID
First, you want an events table, that has the maximum number of participants.
Then you need a before insert trigger on the participants table. This trigger would fail if the following is true:
select (count(*) >= max(e.maxparticipants))
from participants p join
events e
on p.event = e.event
where event = new.event;
These will limit the number of participants in an event.
You can also implement this in a stored procedure rather than a trigger, if you wrap your insert logic in stored procedures.
Or, you can implement this logic directly in your application, although I think it is safer to implement it in the database. If you do so, consider this statement:
insert into participants(<columns go here>)
select <column values go here>
from dual
where (select max(e.maxparticipants) - COUNT(*))
from participants p join
events e
on p.event = e.event
where event = THEEVENT
) > 0;
This insert will not insert any rows once the maximum has been reached.
I have a web application that stores points in a table, and total points in the user table as below:
User Table
user_id | total_points
Points Table
id | date | user_id | points
Every time a user earns a point, the following steps occur:
1. Enter points value to points table
2. Calculate SUM of the points for that user
3. Update the user table with the new SUM of points (total_points)
The values in the user table might get out of sync with the sum in the points table, and I want to be able to recalculate the SUM of all points for every user once in a while (eg. once a month). I could write a PHP script that could loop through each user in the user table and find the sum for that user and update the total_points, but that would be a lot of SQL queries.
Is there a better(efficient) way of doing what I am trying to do?
Thanks...
A more efficient way to do this would be the following:
User Table
user_id
Points Table
id | date | user_id | points
Total Points View
user_id | total_points
A view is effectively a select statement disguised as a table. The select statement would be: SELECT "user_id", SUM("points") AS "total_points" FROM "Points Table" GROUP BY "user_id". To create a view, execute CREATE VIEW "Total Points View" AS <SELECT STATEMENT> where SELECT STATEMENT is the previous select statement.
Once the view has been created, you can treat it as you would any regular table.
P.S.: I don't know that the quotes are necessary unless your table names actually contain spaces, but it's been a while since I worked with MySQL, so I don't remember it's idiosyncrasies.
You have to user Triggers for this, to make the users total points in sync with the user_points table. Something like:
Create Trigger UpdateUserTotalPoints AFTER INSERT ON points
FOR EACH ROW Begin
UPDATE users u
INNER JOIN
(
SELECT user_id, SUM(points) totalPoints
FROM points
GROUP BY user_id
) p ON u.user_id = p.user_id
SET u.total_points = p.totalPoints;
END;
SQL Fiddle Demo
Note that: As noted by #FireLizzard, if these records in the second table, are frequently updated or delted, you have to have other AFTER UPDATE and AFTER DELETE triggers as well, to keep the two tables in sync. And in this case the solution that #FireLizzard will be better in this case.
If you want it once a month, you can’t deal with just MySQL. You have too « logic » code here, and put too logic in database is not the correct way to go. The trigger of Karan Punamiya could be nice, but it will update the user_table on every insert in points table, and it’s not what you seem to want.
For the fact you want to be able to remove points, just add bsarv new negated rows in points, don’t remove any row (it will break the history trace).
If you really want it periodically, you can run a cron script that does that, or even call your PHP script ;)
I run points system on my site so I need to keep logs of different action of my users into database. The problem is that I have too many users and keeping all the records permanently may cause server overload... I there a way to keep only 10 records per user and automatically delete older entries? Does mysql have some function for this?
Thanks in advance
You can add a trigger that takes care of removing old entries.
For instance,
DELIMITER //
CREATE definer='root'#'localhost' TRIGGER afterMytableInsert AFTER INSERT ON MyTable
FOR EACH ROW
BEGIN
DELETE FROM MyTable WHERE user_id = NEW.user_id AND id NOT IN
(SELECT id FROM MyTable WHERE user_id = NEW.user_id ORDER BY action_time DESC LIMIT 10);
END//
Just run an hourly cron job that deletes the 11th - n records.
Before insert a record you could check how many the user has first. If they have >=10 delete the oldest one. Then insert the new one.
If your goal is to have the database ensure that for a given table there are never more than N rows per a given subkey (user) then the correct way to solve this will be either:
Use stored procedures to manage inserts in the table.
Use a trigger to delete older rows after an insert.
If you're already using stored procedures for data access, then modifying the insert procedure would make the most sense, otherwise a trigger will be the easiest solution.
Alternately if your goal is to periodically remove old data, then using a cron job to start a stored procedure to prune old data would make the most sense.
When you are inserting a new record for a user. Just do a query like this before (Don't forget the where-condition):
DELETE FROM tablename WHERE userID = 'currentUserId' LIMIT 9, 999999
After that you can insert new data. This keeps the data always to ten records for each user.
INSERT INTO tablename VALUES(....)
DELETE FROM Table WHERE ID NOT IN (SELECT TOP 10 ID FROM Table WHERE USER_ID = 1) AND USER_ID = 1
Clearer Version
DELETE FROM Table
WHERE ID NOT IN
(
SELECT TOP 10 ID FROM Table WHERE USER_ID = 1
)
AND USER_ID = 1