Set max rows in mySQL and auto truncate - mysql

I'm wondering if MySQL supports the ability to set max rows in a table and auto truncate old entries. Let's say I have the following table and I want max rows of 5.
| ID | VALUE |
| 0 | value |
| 1 | value |
| 2 | value |
| 3 | value |
| 4 | value |
Then, another row is added, with ID 5, so I'd want ID 4 to drop and ID 5 to be added to the top of the stack.

Use a trigger. Check the count of values each time you get an insert.
You may have to map the table out to a temp folder and copy it back in with the rotated list but 5 values would make this a pretty cheap operation.

Related

Can I insert ("squeeze in") a row in a table and increase remaining values after the inserted row with one query in MySQL?

I wonder if I can insert a row in a table and increase all remaining values after the inserted row?
Take look at the sample table below:
+----+----------+-----------+
| id | position | data |
+----+----------+-----------+
| 1 | 1 | Paris |
| 2 | 2 | London |
| 3 | 3 | Berlin |
| 4 | 4 | Madrid |
+----+----------+-----------+
The id column is the primary key. The position column is used to sort the data in custom order. I now wonder if it's possible to create an INSERT/UPDATE-query in MySQL to "sqeeze in" a new city in the table, i.e. the position values need to be increased after the insert, like this:
+----+----------+-----------+
| id | position | data |
+----+----------+-----------+
| 1 | 1 | Paris |
| 2 | 2 | London |
| 5 | 3 | New York | <-- inserted row... positions after are increased
| 3 | 4 | Berlin | <-- position +1
| 4 | 5 | Madrid | <-- position +1
+----+----------+-----------+
I first thought that I solve this in PHP by modifying each row in a loop. But I hope I can solve this with one single INSERT-query. Is that possible?
INSERT INTO table SET position=3, data="New York" {AND INCREASE THE REST of postion}
Rows in tables are not physically stored in-order of their primary-key values (the real answer, as ever, is "it's complicated" - I'll be happy to go into detail on this point if you like).
But w.r.t. your question, the solution is straightforward:
SET #insertAtPosition = 3;
SET #insertData = 'New York';
BEGIN TRANSACTION;
UPDATE tbl SET Position = Position + 1 WHERE Position >= #insertAtPosition;
INSERT INTO tbl ( Position, Data ) VALUES ( #insertAtPosition, #insertData );
COMMIT TRANSACTION;
Note that the use of BEGIN TRANSACTION and COMMIT TRANSACTION is important so that the Position values won't be updated without a new row being successfully inserted - if the INSERT (or the UPDATE) fails for whatever reason, then the Position values will be unchanged, as though the attempt was never made.

TRUNCATE-INSERT vs SELECT-UPDATE-INSERT

I have a table that I am using as a temporary table. A cron runs every hour to set a certain value for each row.
| id | item_id | value |
+====+=========+=======+
| 1 | 5 | 52 |
| 2 | 34 | 314 |
| 3 | 27 | 189 |
| 4 | 19 | 200 |
+====+=========+=======+
What I would like to know is if it is better to first TRUNCATE and then refill this table or that I could rather SELECT the existing row, UPDATE it or INSERT it if it doesn't exist.
Insert the record if it doesn't exist in your temporary table and if it has already in your temporary table but you need to update it's value then update the specific record by only target it.
It would be more wise, because it will be reduce the operation execution time.

mysql table field values are hidden - why?

I am seeing this behavior on Windows 7 - mysql v5.6.17. When I try to view table records, the field with auto incrementing primary key (here it is the column with 'id') do not show values in all rows, but those values actually were populated after loading them from a data file. My initial thought was some of the values in ID column were missing, but they are not!
If I query individual row, then it shows the value in id column. Is this a normal behavior? Is there a better way to display table records?
Please see the image enclosed below.
The data certainly appears corrupted.
An 'uncorrupted' result might look like this...
+----+-------------+-----+-----+-------+
| id | PlateNumber | Row | Col | Orf |
+----+-------------+-----+-----+-------+
| 1 | 1 | A | 1 | Empty |
| 2 | etc... | | | |

Sort table records in special order

I have table:
+----+--------+----------+
| id | doc_id | next_req |
+----+--------+----------+
| 1 | 1 | 4 |
| 2 | 1 | 3 |
| 3 | 1 | 0 |
| 4 | 1 | 2 |
+----+--------+----------+
id - auto incerement primary key.
nex_req - represent an order of records. (next_req = id of record)
How can I build a SQL query get records in this order:
+----+--------+----------+
| id | doc_id | next_req |
+----+--------+----------+
| 1 | 1 | 4 |
| 4 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 0 |
+----+--------+----------+
Explains:
record1 with id=1 and next_req=4 means: next must be record4 with id=4 and next_req=2
record4 with id=5 and next_req=2 means: next must be record2 with id=2 and next_req=3
record2 with id=2 and next_req=3 means: next must be record3 with id=1 and next_req=0
record3 with id=3 and next_req=0: means that this is a last record
I need to store an order of records in table. It's important fo me.
If you can, change your table format. Rather than naming the next record, mark the records in order so you can use a natural SQL sort:
+----+--------+------+
| id | doc_id | sort |
+----+--------+------+
| 1 | 1 | 1 |
| 4 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 4 |
+----+--------+------+
Then you can even cluster-index on doc_id,sort for if you need to for performance issues. And honestly, if you need to re-order rows, it is not any more work than a linked-list like you were working with.
Am able to give you a solution in Oracle,
select id,doc_id,next_req from table2
start with id =
(select id from table2 where rowid=(select min(rowid) from table2))
connect by prior next_req=id
fiddle_demo
I'd suggest to modify your table and add another column OrderNumber, so eventually it would be easy to order by this column.
Though there may be problems with this approach:
1) You have existing table and need to set OrderNumber column values. I guess this part is easy. You can simply set initial zero values and add a CURSOR for example moving through your records and incrementing your order number value.
2) When new row appears in your table, you have to modify your OrderNumber, but here it depends on your particular situation. If you only need to add items to the end of the list then you can set your new value as MAX + 1. In another situation you may try writing TRIGGER on inserting new items and calling similar steps to point 1). This may cause very bad hit on performance, so you have to carefully investigate your architecture and maybe modify this unusual construction.

Set cumulative value when faced with overflowing Int16

I have cumulative input values that start life as smallints.
I read these values from a Access database, and aggregate them into a MySQL database.
Now I'm faced with input values of type smallint that are cumulative, thus always increasing.
Input Required output
---------------------------------
0 0
10000 10000
32000 32000
-31536 34000 //overflow in the input
-11536 54000
8464 74000
I process these values by inserting the raw data into a blackhole table and in the trigger to the blackhole I upgrade the data before inserting it into the actual table.
I know how to store the previous input and output, or if there is none, how to select the latest (and highest) inserted value.
But what's the easiest/fastest way to deal with the overflow, so I get the correct output.
Given you have a table named test with a primary key called id and the column is named value Then just do this:
SELECT
id,
test.value,
(SELECT SUM(value) FROM test AS a WHERE a.id <= test.id) as output
FROM test;
This would be the output:
------------------------
| id | value | output |
------------------------
| 1 | 10000 | 10000 |
| 2 | 32000 | 42000 |
| 3 | -31536 | 10464 |
| 4 | -11536 | -1072 |
| 5 | 8464 | 7392 |
------------------------
Hope this helps.
If it doesn't work, just convert your data to INT (or BIGINT for lots of data). It does not hurt and memory is cheap this days.