Rearranging primary keys - php

I have a PHP page which interacts with this small MySQL database table with a simple structure. ID, Name, Address are the fields. ID is the primary key.
+------+------------+-------------+
| ID | Name | Country |
|______|____________|_____________|
| E001 | Stephen | America |
| E002 | John | Britain |
| E003 | Kate | Canada |
| E004 | Carlos | Spain |
| E005 | James | Australia |
|______|____________|_____________|
If I remove the record at E003, it looks like this.
+------+------------+-------------+
| ID | Name | Country |
|______|____________|_____________|
| E001 | Stephen | America |
| E002 | John | Britain |
| E004 | Carlos | Spain |
| E005 | James | Australia |
|______|____________|_____________|
A gap appears between E002 and E004.
Is there a way to fill in that gap? Like this
+------+------------+-------------+
| ID | Name | Country |
|______|____________|_____________|
| E001 | Stephen | America |
| E002 | John | Britain |
| E003 | Carlos | Spain |
| E004 | James | Australia |
|______|____________|_____________|
Earlier record which had E004, fall into the place of E003. Former E005 gets the number E004 and so on. Like the records take a step back.
Is there a way to do this programmatically?

Is there a reason you need to renumber them? The key values shouldn't really matter. If they do (i.e., they are used for outside purposes), consider having the external key be a regular column in the table and let the primary key be an auto-increment integer field. Even if you do this, you still probably shouldn't be renumbering keys. That would mean that all external dependencies would need to be updated as well. There's just not much value in doing it.
But, if you have to...
If the key is auto-increment (which it should be), you can do this:
ALTER TABLE MyTable DROP ID;
ALTER TABLE MyTable ADD COLUMN ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST;
If it's not, then you can do several things, but the easiest might be to use variables to act as a counter. To make this easier, please don't use a string primary key, but instead use a plain numeric primary key.
SET #id = 0;
UPDATE MyTable
SET ID = (#id := #id + 1)
ORDER BY ID;

In your database table ID is primary key and it is alphanumeric.
I don't think so it is a good way for rearranging primary key in table. All its relation with other table will be messed up.
Try to use numeric primary key instead of string.
If you use numeric primary key, you can rearrange them by dropping and recreating primary key column with auto increment.

Since your ID field is not an integer field you can't do it with just one query and you need to do a loop over all records after the gap and update the ID field.
But a better way might be to change the ID filed type to auto increment unsigned integer and then by knowing the last ID before the gap equals to gID you can do a query like this :
UPDATE table_name SET `ID` = (`ID` - 1) WHERE `ID` > gID;
Then you just need to update your auto_increment value:
ALTER TABLE `table_name` AUTO_INCREMENT = (SELEC `ID` FROM `table_name` ORDER BY `ID` DESC LIMIT 1);
Since all the records in your ID field have the letter 'E' in common, it might be possible to get rid of this letter and change the field type to an AUTO INCREMENT UNSIGNED INTEGER

Related

Know the last modified row or id's row in a mysql table

I'm using Mysql 5.5 and by example I have a table like this
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| idgroups | int(11) | NO | PRI | NULL | auto_increment |
| group_id | int(11) | YES | | NULL | |
| group_name | varchar(45) | YES | | NULL |
Where some people are allowed to do inserts,update and delete but I want to know which is the last modified row or row's id in a given time
Any ideas?
Thanks in advance
My suggestion would be to create a second table. something like edit_history for recording modifications. You can put triggers on your groups table above that says "Any time a record is inserted, deleted, or updated, create a record in my edit_history table".
A trigger can be created as follows:
CREATE TRIGGER trigger_name
AFTER INSERT
ON table_name FOR EACH ROW
BEGIN
-- For each row inserted
-- do something...
END;
Since your field is auto_increment, you can just select the maximum value of idgroups to get the most recently inserted value:
select max(idgroups) from tbl
to get last modified in general will require additional structure to your table. In particular, if you are deleting, you will need to store what you have most recently deleted somewhere.

How to use insert and update with no primary key

I have the following Mysql-table:
+-------+--------+------------+----+-------+
| Name | Number | Department | id | JobID |
+-------+--------+------------+----+-------+
| Sven | 2204 | Marketing | 10 | 111 |
| Peter | 2304 | IT | 20 | 222 |
| Bjorn | 4409 | IT | 30 | 333 |
+-------+--------+------------+----+-------+
I get the three columns: Name, Number, Department from a system where I don't have the id and need to perform something in my php script.
Now I would like to performa an insert if there is a new record. If there is an existing record I would like to perform an update, if something changed like Name, Number or Department.
For example, if Number changes it should compare Name and Department and then change number. If Departmend changes it should compare Name and Number and then change Department and so on.
The problem is, that I can not use insert...on duplicate key, because I don't get the primary key.
If I use Replace Into it deletes me also the entry for JobID. Is there a solution how to perform a sql that it will insert and also update if there is now entry? Or something that can do the trick?
Thanks for your help!

Do the fields (structure) of MySQL tables get unique ids?

I'm not talking about unique keys or auto_increments, suppose I have this structure:
mysql> describe email_notifications;
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| email_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| email_address | varchar(100) | NO | | | |
| course_id | int(11) unsigned | NO | MUL | NULL | |
+---------------+------------------+------+-----+---------+----------------+
I'm building (for fun, practice, and hopefully some practical use) a tool in PHP that will analyze the structure of each table in a database and then compare it to a newer one (to assist in Dev -> Live updates), and then spit out some MySQL queries (Such as ALTER TABLE...) that I can run on the live database in order to bring it up to speed.
The question - does each field get a unique id of some sort?
If I change email_address from varchar(100) to text (for example) or the name course_id to cr_id, is there any way for me to tell that it's still technically the same dataset? I don't want to run a Delete and Add, but instead rename it give it a new type.
Or if there's a better way to do it without some sort of MySQL ID, that would be great :)
Thanks!
I think you can use information_schema.columns. The following are both unique keys in this table (even if they are not so defined):
TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION
When you change the name or type of a column, I do not believe that ORDINAL_POSITION is affected. So, the second version may be what you are looking for.
This may then lead to the question "what if I change the name of a table?" The information_schema tables can't help there, unfortunately.

Speed Up MySQL (MyISAM) COUNTs with WHERE Clauses

We are implementing a system that analyses books. The system is written in PHP, and for each book loops through the words and analyses each of them, setting certain flags (that translate to database fields) from various regular expressions and other tests.
This results in a matches table, similar to the example below:
+------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| regex | varchar(250) | YES | | NULL | |
| description | varchar(250) | NO | | NULL | |
| phonic_description | varchar(255) | NO | | NULL | |
| is_high_frequency | tinyint(1) | NO | | NULL | |
| is_readable | tinyint(1) | NO | | NULL | |
| book_id | bigint(20) | YES | | NULL | |
| matched_regex | varchar(255) | YES | | NULL | |
| [...] | | | | | |
+------------------------+--------------+------+-----+---------+----------------+
Most of the omitted fields are tinyint, either 0 or 1. There are currently 25 fields in the matches table.
There are ~2,000,000 rows in the matches table, the output of analyzing ~500 books.
Currently, there is a "reports" area of the site which queries the matches table like this:
SELECT COUNT(*)
FROM matches
WHERE is_readable = 1
AND other_flag = 0
AND another_flag = 1
However, at present it takes over a minute to fetch the main index report as each query takes about 0.7 seconds. I am caching this at a query level, but it still takes too long for the initial page load.
As I am not very experienced in how to manage datasets such as this, can anyone advise me of a better way to store or query this data? Are there any optimisations I can use with MySQL to improve the performance of these COUNTs, or am I better off using another database or data structure?
We are currently using MySQL with MyISAM tables and a VPS for this, so switching to a new database system altogether isn't out of the question.
You need to use indexes, create them on the columns you do a WHERE on most frequently.
ALTER TABLE `matches` ADD INDEX ( `is_readable` )
etc..
You can also create indexes based on multiple columns, if your doing the same type of query over and over its useful. phpMyAdmin has the index option on the structure page of the table at the bottom.
Add multi index to this table as you are selecting by more than one field. Below index should help a lot. Those type of indexes are very good for boolean / int columns. For indexes with varchar values read more here: http://dev.mysql.com/doc/refman/5.0/en/create-index.html
ALTER TABLE `matches` ADD INDEX ( `is_readable`, `other_flag`, `another_flag` )
One more thing is to check your queries by using EXPLAIN {YOUR WHOLE SQL STATEMENT} to check which index is used by DB. So in this example you should run query:
EXPLAIN ALTER TABLE `matches` ADD INDEX ( `is_readable`, `other_flag`, `another_flag` )
More info on EXPLAIN: http://dev.mysql.com/doc/refman/5.0/en/explain.html

Get rowid from Mysql

i develop a project, in that i display the values from mysql database using PHP , in that i need to set a unique id[Not manually] for each row that i fetched from database.Can anyone help me please. Thanks in Advance.
Take a look at this article for how to create an auto incremented field to generate unique ID for the record:
http://www.plus2net.com/sql_tutorial/mysql_auto_increment.php
Basicly you use AUTO_INCREMENT attribute on the column.
This
CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');
SELECT * FROM animals;
Will create this output:
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
+----+---------+
How to automatically generate ids has already been answered. Additional info: If you want to see which id was inserted for a row, use mysql_insert_id()
Alternatively, you should already have a primary key or compound key, get a hash of these using the md5 function and store in memory. However, creating an auto incrementing field or a UUID field in the database would be the most preferable option.
HI, Even i have come across the same situation, where I need to display the row id. To implement this, i have created a separated table, where I Control the table with Stored Procedure, before it refills, I will delete all the records and reinserts with the latest Ranking systems. I am successful in this and implemented in
http://cricandcric.com/C&Guess/login.php

Categories