I have a table that does not require a primary key. It consists of 4 columns which are email,date,time,message. Each time a user logs in, logs out, or does any particular action that is important, I log the email, date, time and action (message). Currently the table is setup with email as the Primary Key but I am unable to insert more than one record with the same email. I suppose I could use time as the PK but there is the possibility that two actions fall on the same time. How can I just use the table without a PK? I have tried turning it off for the email column but it does not allow me to.
Yes as you have defined email field as your primary, it can hold unique data only and no duplication allowed.
So you have two options:
1: Remove email field as a primary key
2: Add new integer field as a Primary key with auto increment (I would prefer this one)
You could use a natural primary key that would be a combination of Email + Date + Time + Action. That combination would be unique. It is impossible for the same user to do 2 different actions at the same time. That will help you to keep integrity of your information.
Hope this helps you.
To make a decision on a table' primary key one may start with considering these points (applicable to innodb):
How the data is going to be accessed after it is written (if you don't query it, why store it?). If you care about read performance you should query your data by the primary key, since for innodb primary key is the only possible clustered index.
The data is stored ordered by the primary key, so if you care about write performance, you should write data ideally ordered by your primary key, which always happens automatically if you have an auto_increment. Also table for which you don't explicitly specify a primary key are going to have a hidden auto_increment field which you won't be able to access, i.e. you get less for the same cost.
Related
During the creation of tables using mysql on phpmyadmin, I always find an issue when it comes to primary keys and their auto-increments. When I insert lines into my table. The auto_increment works perfectly adding a value of 1 to each primary key on each new line. But when I delete a line for example a line where the primary key is 'id = 4' and I add a new line to the table. The primary key in the new line gets a value of 'id = 5' instead of 'id = 4'. It acts like the old line was never deleted.
Here is an example of the SQL statement:
CREATE TABLE employe(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30) NOT NULL
)
ENGINE = INNODB;
How do I find a solution to this problem ?
Thank you.
I'm pretty sure this is by design. If you had IDs up to 6 in your table and you deleted ID 2, would you want the next input to be an ID of 2? That doesn't seem to follow the ACID properties. Also, if there was a dependence on that data, for example, if it was user data, and the ID determined user IDs, it would invalidate pre-existing information, since if user X was deleted and the same ID was assigned to user Y, that could cause integrity issues in dependent systems.
Also, imagine a table with 50 billion rows. Should the table run an O(n) search for the smallest missing ID every time you're trying to insert a new record? I can see that getting out of hand really quickly.
Some links you might like to read:
Principles of Transaction-Oriented Database Recovery (1983)
How can we re-use the deleted id from any MySQL-DB table?
Why do you care?
Primary keys are internal row identifiers that are not supposed to be sexy or good looking. As long as they are able identify each row uniquely, they serve their purpose.
Now, if you care about its value, then you probably want to expose the primary key value somewhere, and that's a big red flag. If you need an external, visible identifier, you can create a secondary column with any formatting sequence and values you want.
As a side note, the term AUTO_INCREMENT is a bit misleading. It doesn't really mean they increase one by one all the time. It just mean it will try to produce sequential numbers, as long as it is possible. In multi-threaded apps that's usually not possible since batches or numbers are reserved per thread so the row insertion sequence may end actually not following the natural numbering. Row deletions have a similar effect, as well as INSERT with roll backs.
Primary keys are meant to be used for joining tables together and
indexing, they are not meant to be used for human usage. Reordering
primary key columns could orphan data and wreck havoc to your queries.
Tips: Add another column to your table and reorder that column to your will if needed (show that column to your user instead of the primary key).
I was wondering if there is a way for a form to not generate a Primary Key as soon as I start typing on a field (this is just in case I don't really want to insert)? Can it show what Primary Key will be generated when I do/only generate and insert in the table?
There is a difference between a Primary Key and a automatically generated number. It is true that Access proposes an autonumber field as a PK, but you can definitely switch it to a number or character field. Then, you will have to find a way to enter manually the PK value, or generate it through code(*), before inserting the record in the table.
(*) In case you are using numbers as PKs, the logic could be here to check the higher PK value already in the table (max()) and add 1 to it.
I'm creating a table to track income and outcome. I have the following rows
type [can assume 3 values]
date [date of the transaction]
incomeAmout
incomeDescription
outcomeAmount
outcomeDescription
If I have date as primary then I won't be able to have multiple transaction in the same date. I could make all the rows as primary key but I'm not sure this is the best way to proceed. What would you suggest me to do? I read some topics about creating an auto incremental index but I'm wondering if I can make it without adding another attribute.
Thanks
Make an id column as a primary key. This will be your immutable record identifier.
You'll probably want to have some kind of randomized transaction identifier as well, something like a UUID or a value derived from the SHA256 hash of something. That way you can share these identifiers without revealing too much about your database structure or how many records there are in the database.
Then, if you need another key, add it as a UNIQUE index, or define whatever unique constraints you want to enforce as a compound key.
Your question should be: Surrogate Key vs. Natural Key
In your case, you have no choice but to use Surrogate Key: create a new field named "ID" and set it as Integer, Autoincrement, Primary Key.
BTW, Microsoft recommends use of Surrogate key as a good practice.
is it possible to create a primary key in a existing table on a column that have repeated value? I want is previous record not validate but new record will validate with this.Is it possible in mysql. I know it is possible in Oracle (here is an example) but don't have idea about mysql.
The link you posted as a comment to Nerd-Herd's answer uses deferred constraints. Those constraints are checked at the end of the transaction rather than at the time the statement is executed.
MySQL does not support deferred constraints
If you absolutely need deferred constraints and want to stick with an open source database you will need to migrate to PostgreSQL.
No it can not be. It violates what Primary Key means. But if you want to have a composite primary key, it may be possible
A primary key is always a unique identifier, if you make it non unique it stops being an identifier, why do you want to repeat it? If you have multiple entries that have a field that repeats, that field is not your primary key, however, you can combine it with another field that will give you a primary key (not very recommendable, but you can make this field plus a timestamp field your combined primary key).
In this case what I would recommend is make an autoincrement key and just use this field that repeats as a normal field, maybe ad an index to it to improve searches. You can still look for records on any field, just because it's not your primary key it doesn't mean you are not going to be able to search and get it. The idea of a primary key is that it will get you 1 and only 1 record, not 1 or more.
Assume a table that may look like this:
userId INT (foreign key to a users table)
profileId INT (foreign key to a profiles table)
value INT
Say that in this table preferences for users are saved. The preference should be loaded according to the current user and the profile that the current user has selected. That means that the combination of userId and profileId is unique and can be used as a composite primary key.
But then I want to add the ability to also save a default value that should be used if no value for a specific profileId is save in the database. My first idea would be to set the profileId column to nullable and say that the row that has null as profileId contains the default value. But then I can't use a composite primary key that involves this table, because nullable columns can't be part of a primary key.
So what's the "best" way to work around this? Just drop the primary key completely and go without primary key? Generate an identity column as primary key that I never need? Create a dummy profile to link to in the profile table? Create a separate table for default values (which is the only option that guarantees that no userId has multiple default values??)?
Update: I thought about Dmitry's answer but after all it has the drawback that I can't even create a unique constraint on the two columns userId and profileId (MySQL will allow duplicate values if profileId is null and DB2 will refuse to even create a unique constraint on a nullable column). So with Dmitry's solution I will have to live without this consistency check of the DB. Is that acceptable? Or is that not acceptable (after all consistency checks are a major feature of relational DBs). What is your reasoning?
Create ID autoincrement field for your primary key.
AND
Create unique index for (userId, profileId) pair. If necessary create dummy profile instead of null.
Dmitry's answer is a good one, but since your case involves what is essentially an intersection table, there is another good way to solve this. For your situation I also like the idea of creating a default user profile that you can use in your code to establish default settings. This is good because it keeps your data model clean without introducing extra candidate keys. You would need to be clear in this dummy/default profile that this is what it is. You can give it a clear name like "Default User" and make sure that nobody but the administrator has access to the user credentials.
One other advantage of this solution is that you can sign on as the default user and use your system's GUI to modify the defaults rather than having to fiddle with the data through DB access tools. Depending on the policies in your shop, direct access to the data tables by programmers may be hard or impossible. Using the tested/approved GUIs for modifying defaults removes a lot of red tape and prevents some kinds of accidental damage to the data.
Bottom Line: Primary keys are important. In a transactional system every table should have a at least one unique index one of which should be the primary key. You can always enforce this by adding a surrogate (auto increment) key to every table. Even if you do, you still generally want a natural unique index whenever possible. This is how you will generally find what you're looking for in a table.
Creating a Default User entry in your user table isn't a cheat or a hack, it's using your table structure the way it's meant to be used and it allows you to put a usable unique contraint on the combination of user ID and profile ID, regardless of whether you invent an additional, arbitrary unique constraint with a surrogate key.
This is the normal behaviour of UNIQUE constrain on a NULL column. It allows one row of data with NULL values. However, that is not the behaviour we want for this column. We want the column to accept unique values and also accept multiple NULL values.
This can be achieved using a computed column and adding a contraint to the computed column instead default null value.
Refer below article will help you more in this matter:
UNIQUE Column with multiple NULL values
I always always always use a primary auto_increment key on a table, even if its redundant; it just gives me a fantastically simple way to identify a record I want to access later or refer to elsewhere. I know it doesn't directly answer your question, but it does make the primary key situation simpler.
create table UserProfile ( int UserProfileID auto_increment primary key etc.,
UserID int not null, ProfileID int );
Then create a secondary index UserProfileIDX(UserID, ProfileID) that's unique, but not the primary key.