Truncating rows based on column value in mysql - mysql

Let's say I have have a MySQL table with many rows that I want to limit in a specific way. Each row has a column, userID, that is indexed but is not unique. Each row also has a datetime column for createDate.
I'd like for the table to never contain more than X number (say, 1000) of rows for a given userID. So, anytime a row is inserted, if that means that there are now greater than X rows where userID = Y then the DB would delete a row based on the value of createDate.
Is this possible to achieve inside the database only? What performance concerns should I have about this kind of approach?

Related

Get rows inserted after the last fetch from a Mysql table without primary key

So, I have a table which has 3 columns.
Customer_number, login_hash and some_hash
The customer_number is not the auto increment id and the table is being indexed on login_hash.
Now the table is updated every hour and new entries are being added. I have to get the new entries, use them for some calls and then store the resulting data.
My plan is to always store the last row number in some last_row environment variable and then retrieve values after that row number till the last record. Then update the last_row number.
How do I achieve this? And is there any better approach to this problem?
I know this is a bad table design but I have to deal with this and can't change it.

Auto_increment temporary gaps in MySQL?

Let's say I have a table defined by:
CREATE TABLE People (
id SERIAL,
name TEXT
);
If I first find the maximum id in the table and then run the following query:
SELECT (id, name)
FROM People
WHERE id <= [maximum id found before];
I'll get a list of people. If I run the same query again with the same maximum id:
Am I guaranteed to get the same results?
Or is it possible that the first query returned a list with gaps which were filled in before the second query was executed, causing the second query to have more rows?
Assume that no changes are made to the database except sequential insert operations from any number of concurrent connections.
EDIT:
I'll try to clarify the specific case I'm concerned about. Let's say MySQL gets five transactions at around the same time. Transactions A and B both insert a person into People. Transaction C finds the maximum id. Transactions D and E both perform the query written above.
Is it possible for this sequence of events:
A is assigned an id
B is assigned the next id
B is committed
C is committed and returns the id of B
D is committed and returns a list that does not include the row inserted by A
A is committed
E is committed and returns a list that does include the row inserted by A
EDIT:
I'm thinking this scenario is impossible due to atomicity, but I'm hoping for confirmation from someone who understands ACID a little better than I do.
I think you are guaranteed to get the same list, gaps should never be filed in unless you're manually inserting them somehow. (although, if there are gaps i assume rows can be deleted, so it may not be exactly the same list because more may have been deleted.)
from How to reset AUTO_INCREMENT in MySQL?
You can reset the counter with:
ALTER TABLE tablename AUTO_INCREMENT = 1 For InnoDB you cannot set the
auto_increment value lower or equal to the highest current index.
(quote from ViralPatel):
Note that you cannot reset the counter to a value less than or equal
to any that have already been used. For MyISAM, if the value is less
than or equal to the maximum value currently in the AUTO_INCREMENT
column, the value is reset to the current maximum plus one. For
InnoDB, if the value is less than the current maximum value in the
column, no error occurs and the current sequence value is not changed.
See How to Reset an MySQL AutoIncrement using a MAX value from another
table? on how to dynamically get an acceptable value.

Mysql - difference in auto increment and no. of row

the number of rows in my mysql TB (As shown in TB info) is 11093 where as the auto increment id (starting from 1) is 11361. Why is that so?
Deleted rows do not reset the AI index. Row count is the number of entries currently in your table, while the AI value is the number of rows you ever added to the table.

Most efficient code to set a sort order column / assign a sequential series of numbers to a column?

I've got a table that will hold a sequence of rows I want to be able to change the order in which I query and display them. So I've created a column called "sortorder" that is an integer. I'm looking for a quick SQL statement re-order these column values any time I make an adjustment (i.e. bump a column up, down, to top or bottom).
So, given a table like:
table xxx:
data varchar(x)
sortorder int(10)
..
When I want to parse rows I'll do something like this:
select * from xxx order by sortorder desc;
Would I propose doing is, setting the value of sortorder to be sequential in increments of 2, such as the first row sortorder=2, the second sortorder=4, etc.
Then if I arbitrarily want to move any row back one, I simply set sortorder=sortorder-1.
Then I run a routine to re-assign all the values of sortorder in increments of 2 (order by sortorder ASC) and reset all the numbers with the new row in its proper place.
I figure when I initially add a row to the table I will set the sortorder= max number of existing rows *2 + 2; What would be the best way to do this in SQL?
I'm looking for the most efficient statement to re-order the values of sortorder as such.
I'm also open to ideas on other ways you might maintain user-changeable sort order for an table of rows...
Thanks!

Fix following id's when a row is deleted

I have a table with some rows, each row has a unique key. When a row is deleted from the table, all rows that are below this row should be 'moved up'. Is there some built in function in MySQL that does this or should I just do it with PHP or perhaps UPDATE table SET id=id-1 WHERE id > deletedid?
Using the last one seems a bit messy.
What would be the best way to do this?
Why do you want to do this? I know it's ugly to have holes in your unique ID sequence, but the downside of invalidating any references to IDs from outside the database is normally very much greater. The normal thing is to just accept the sequence won't be contiguous. If these represent a sequence, consider just sorting by the order rather than expecting the N'th value to have value N (any sort of iteration should provide its own index somewhere for this use).
If the value is one you set yourself, and you definitely want to keep it as having values from 1 to N (N="number of rows"), and you want to keep the sequence of values even if they're not in the order the rows were inserted, then "UPDATE table SET id=id-1 WHERE id > deletedid" is probably the best answer.
If the value is an auto_increment field, and you don't care which numbers go with with rows as long as each row has a number from 1 to N, you can alternatively do ALTER TABLE DROP COLUMN 'columnname' and then ALTER TABLE again to add the column again, and the database will regenerate the ids from 0. (Not necessarily in the same order, though it often is.)
There may be a way to renumber only the rows after that point, but (according to a quick google) it doesn't look like there's anything easier than what you're already planning.
First you have to ensure that the column is not a foreign-key for any other table.
Then you can try this (I am not 100% positive it will work):
DELETE FROM
MyTable
WHERE
id = deletedid;
UPDATE
table
SET
id=id-1
WHERE
id > deletedid
ORDER BY
id
As stated in mysql docs:
If the ORDER BY clause is specified,
the rows are updated in the order that
is specified.
and in this way you ensure uniqueness of the field.