I have created a MySQL database using MySQL Workbench. In there, I have created a table, the first entries of which are:
id firstName lastName
1 John Smith
2 Emma Richards
Every column contains VARCHAR characters - even the id, it is NOT an integer.
For some reason, however, MySQL seems to re-order the entries:
id firstName lastName
1 John Smith
10 Karen Hill
I don't want MySQL to re-order my entries. When I retrieve the entries from the database, I want them to appear exactly in the order that I have inserted them into the database.
Previously to creating the MySQL database, I have used a SQLite database, which does not re-order the entries.
What might be the reason for this and how can I change it?
I don't want MySQL to re-order my entries. When I retrieve the entries from the database, I want them to appear exactly in the order that I have inserted them into the database.
SQL tables represent unordered (multi)sets. Period. When you query a table in any database, the ordering is not guaranteed unless you include an order by. This is even true in SQLite, as this DB fiddle demonstrates.
In most databases, if you want to capture the insertion order, then you need some sort of column that captures the ordering. There are two common methods:
An identity or auto_increment column that captures the insertion order.
A datetime/timestamp column that captures the date time. This does not always work, because there can be ties.
Then, when you query the table, you need to use order by on the column.
If your first column represents the ordering but happens to be stored as a string, then you can simply use:
order by (id + 0)
Related
I have 2 tables clients and grades where clients has a grade column with indices from 1 to 10. Those indices correspond to the ID's in the grades table (of course). Let's say a client has the indices 1,5,8 in the clients.grade column than I want to fetch * from those rows in the grades table.
My first approach was to use a grade field of type char(20) in the client table and fill it with indices separated by commas like 1,5,8 or others numbers. Then reading those values from one client from the client table I explode (PHP) the result and getting an array with 3 (or more) single values. Then in a following query I select all those rows in the grade table .
Now one question is wether to use a char field or an enumeration field and the other (general) question is how to make a simple, clever query for the entire task.
I did not code it yet. The grades table will have max. 10 rows, where as the client table has around 2.000 rows growing up to max. 5.000 rows. I hope I could describe my approach understandable.
Any suggestions are welcome
Split the grade column into a new table (client_grade?) containing clientId and grade, and have multiple records for each client. The grades for a client can then be retrieved using a JOIN from the clients to the clients_grade table on the client field
Each field in a table should hold a single piece of information and comma-separating values will cause you extra processing. Using a separate table will also aid you if you want to find out who got a particular grade etc
I need to setup a table that will have two auto increment fields. 1 field will be a standard primary key for each record added. The other field will be used to link multiple records together.
Here is an example.
field 1 | field 2
1 1
2 1
3 1
4 2
5 2
6 3
Notice that each value in field 1 has the auto increment. Field 2 has an auto increment that increases slightly differently. records 1,2 and 3 were made at the same time. records 4 and 5 were made at the same time. record 6 was made individually.
Would it be best to read the last entry for field 2 and then increment it by one in my php program? Just looking for the best solution.
You should have two separate tables.
ItemsToBeInserted
id, batch_id, field, field, field
BatchesOfInserts
id, created_time, field, field field
You would then create a batch record, and add the insert id for that batch to all of the items that are going to be part of the batch.
You get bonus points if you add a batch_hash field to the batches table and then check that each batch is unique so that you don't accidentally submit the same batch twice.
If you are looking for a more awful way to do it that only uses one table, you could do something like:
$batch = //Code to run and get 'SELECT MAX(BATCH_ID) + 1 AS NEW_BATCH_ID FROM myTable'
and add that id to all of the inserted records. I wouldn't recommend that though. You will run into trouble down the line.
MySQL only offers one auto-increment column per table. You can't define two, nor does it make sense to do that.
Your question doesn't say what logic you want to use to control the incrementing of the second field you've called auto-increment. Presumably your PHP program will drive that logic.
Don't use PHP to query the largest ID number, then increment it and use it. If you do your system is vulnerable to race conditions. That is, if more than one instance of your PHP program tries that simultaneously, they will occasionally get the same number by mistake.
The Oracle DBMS has an object called a sequence which gives back guaranteed-unique numbers. But you're using MySQL. You can obtain unique numbers with a programming pattern like the following.
First create a table for the sequence. It has an auto-increment field and nothing else.
CREATE TABLE sequence (
sequence_id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sequence_id`)
)
Then when you need a unique number in your program, issue these three queries one after the other:
INSERT INTO sequence () VALUES ();
DELETE FROM sequence WHERE sequence_id < LAST_INSERT_ID();
SELECT LAST_INSERT_ID() AS sequence;
The third query is guaranteed to return a unique sequence number. This guarantee holds even if you have dozens of different client programs connected to your database. That's the beauty of AUTO_INCREMENT.
The second query (DELETE) keeps the table from getting big and wasting space. We don't care about any rows in the table except for the most recent one.
I want to sort mysql by latest logged in but I have to resort it everytime i log in, how do I sort and save the latest login?
You can't reliably keep the values stored in MySQL in alphabetical order. The best you can do is use the ORDER BY clause in your SELECT query.
Usually you sort things when you select by adding an "ORDER BY" clause. Why do you care what order they are actually stored in the table?
If you really care, I guess you could do an INSERT...SELECT to copy it to a new table while sorting the column, but whenever you add a new record, it will end up at the end of the list.
SQL doesn't work that way. It's not like a spreadsheet where the rows are meant to be read "as-is" and you can put them in a certain meaningful order. Nothing you do ever changes the order that SQL stores the rows in. SQL gives you data through queries, and the query tells it which rows you want to see, in what order.
So, you have to reuse the "order by" clause every time you want to see your data in a certain order. However, you shouldn't need to manually query SQL a lot. If you're writing any kind of script or application to work with it, you'll just write the query once and re-run it each time you want the data.
To get the last login from your user table, you could use a query like
SELECT user_name, login_datetime
FROM user_table
ORDER BY login_datetime DESC
LIMIT 1
Assuming that user_name is the field you are looking for and login_datetime is a timestamp you can order on. LIMIT 1 will show only the top most result and can be changed depending on your needs.
With MySQL's InnoDB engine, your rows are physically ordered according to the primary key. So, if the primary key is on the login column, then the rows will stay in physical order by the values in login.
The requirement of a primary key is that each value must be unique and NULL is not allowed. So, you may consider making the login column your primary key. If login were a datetime column, then the latest login datetime value would always be at the end of the table.
Many people make an auto-increment integer column their primary key. In this case, the last record to be inserted would always be at the end of the table.
You must know the value of having your rows in physical order (by a particular column) for certain circumstances, otherwise you wouldn't be asking.
For example, doing the following SELECT returns the rows in physical order (same as primary key) without having to specify a column to order the results by, and without forcing MySQL to later order the result set:
SELECT *
FROM test
However, if you need to order the results other than by the primary key, then you should utilize the ORDER BY clause. For example, if the rows were physically ordered by the column name, but you want the results returned in order by login, you would issue the following query:
SELECT *
FROM test
ORDER BY login ASC
The above query asks MySQL to order the rows according to the specified column. You specify ASC in the ORDER BY clause to order the values in ascending order, and DESC to order them in descending order.
I have more than 3 million rows in my table. When the user try to insert or update this table I have to check the following conditions sequentially.(Business Need)
Does any of the row has same address?
Does any of the row has same postcode?
Does any of the row has same DOB?
Obviously the newly inserted or updated row will match lot of the records from this table.
But the business need is, the matching process should end when the first match (row) found and that row has to returned.
I can easily achieve this using simple "SELECT" query . But it's taking very long time to find the match.
Please suggest some efficient way to do this.
If you're just looking for a way to return after the first match, use LIMIT 1.
You may want to maintain a table of either birth dates or postcodes and have each row link to a user, so that you can easily filter customers down to a smaller set. It would allow you to perform a much faster search on the database.
Example:
dob | userID
1/1/1980 | 235
1/1/1980 | 482
1/1/1980 | 123
2/1/1980 | 521
In that scenario, you only have to read 3 rows from the large users table if your target date is 1/1/1980. It's via a primary key index, too, so it'll be really fast.
I put a sort component to sort my data.
and the data was sorted.
but my destination table is unordered!
How can retain the Order of sorted rows while Inserting them into sql Table with ssis?
There is no inherent ordering of rows in a SQL Server table. You'll need to either add a 'sort order' column or write your queries so that they produce properly sorted result sets.
You can use an IDENTITY column as your 'sort order' columns, since it will increment as things get inserted.
Understand that repeated executions of a given query against a sql database are specifically not guaranteed to return results in the same order, so your queries need to do it each and every time.
Rows in a relational database do not have any "order" - they are like water molecules in a bucket! If you need to have an order then you must include another column that you can use to order by - e.g. an autoincrement field, a timestamp, or some column from external data. You can then use that column to order your data when you query it - otherwise you won't get ordered data.