My table has four columns city, zipcode, number and extra. I created unique group for city, zipcode and number called unique1 and another group for city,zipcode,number and extra called unique2. Those groups need to be unique but the problem is that I can have non unique values when extra if different or is null. For example:
city | zipcode | number | extra
A 123 123 null
A 123 123 10 (I cant add this row because of the unique groups)
How can I solve this problem? (I`m using Mysql)
In another words, what I need is a way to:
1) The grouping of city, zipcode and number must be unique if extra is null
2) If extra isn't null I'd like to insert that information even if the new row collides with the unique rule on '1'.
In MySQL, using unique indexes to handle data constraints beyond simple ones is not a great idea. Other, more expensive, table servers have more elaborate ways to describe constraints.
Your first unique index (you called it a "group") -- unique1 -- prevents the second row in your example from being INSERTed to your table.
Edit: Your example shows that you require non-unique values for your first three columns.
I'm guessing a bit, but I think you should drop unique1 and just use unique2.
Drop unique1, unique2 should take care of it.
Related
I would like to create a unique index on two columns, one of which always has a value but another where the value is often 0 by default.
In the following example, userid 22 liked 2 TV shows and 3 movies. I want to prevent a case where the user would like the same tv show or movie twice. However, I can't make it UNIQUE to userid and movieid or userid and tvshowid, as there are numerous cases where the userid is paired with 0 when the like is for a TV show.
Likes
id|userid|movieid|tvshowid
1|22|0|33
2|22|0|34
3|22|66|0
4|22|67|0
5|22|68|0
I could change all the 0s to NULLs but NULLS tend to create problems on the client.
What is the best way to handle creating a unique index on two columns when one has multiple empty values in it?
If it requires changing all the 0s to NULLs, is there an efficient MYSQL statement to do this?
Change zeroes to NULLs:
UPDATE Likes SET movieid = NULL WHERE movieid = 0;
UPDATE Likes SET tvshowid = NULL WHERE tvshowid = 0;
Create two unique keys, one for movies and one for tvshows.
ALTER TABLE Likes
ADD UNIQUE KEY (userid, movieid),
ADD UNIQUE KEY (userid, tvshowid);
I don't know what you mean by NULLs causing problems on the client. Any client that can use SQL should be able to handle NULLs.
Plan B: 2 tables, each with 3 columns. One talks about TV shows; one for movies.
I have a child table named case_parties, that consists of the name and address of each plaintiff and defendant to court cases.
The table columns include:
case_id, which is a foreign key to the parent table
party_type, which has coded field values of either 1 or 2 (1 indicating a plaintiff and 2 indicating a defendant). The caveat is that there is not always just 1 plaintiff and 1 defendant in every court case. Often, there are multiple plaintiffs and or multiple defendants in a single case. There can be anywhere from 1 to 1,000 + plaintiffs and or defendants on any given case. I created a new column, lets call it party_id and SET it with a CONCAT on the case_id and party_type columns. Therefore, matching rows in this column include either all the plaintiffs or all the defendants to a given case_id.
To create a simple unique key for each row, I want to run a script that adds an auto generated incremental number or letter to the end of the matching party_id field. For example, if there are 4 plaintiffs in the same court case, there are now 4 columns with matching party_id field values, with the last character being 1, representing the party is a plaintiff;
I want to add an increment on so each column is unique and the last two digits of the 4 rows would reflect something like this: "1A", "1B", "1C", "1D" or "1-1", "1-2", "1-3", "1-4",...etc. I'm thinking adding incremental numbers might be easier than adding incremental letters. No other column values individually or collectively make for an efficient composite index in this case. I'm seeking assistance with auto incrementing the matching column values and would greatly appreciate any assistance. Thank you.
I would suggest creating a separate table to represent the defendant/plaintiffs and have a type column in there. Then have a primary key on that table with a regular auto-increment.
You can then use that as your ID in the case_parties table (a foreign key) and it will address your issue with uniquely identifying each one.
I have a table like this:
uuid | username | first_seen | last_seen | score
Before, the table used the primary key of a "player_id" column that ascended. I removed this player_id as I no longer needed it. I want to make the 'uuid' the primary key, but there's a lot of duplicates. I want to remove all these duplicates from the table, but keep the first one (based off the row number, the first row stays).
How can I do this? I've searched up everywhere, but they all show how to do it if you have a row ID column...
I highly advocate having auto-incremented integer primary keys. So, I would encourage you to go back. These are useful for several reasons, such as:
They tell you the insert order of rows.
They are more efficient for primary keys.
Because primary keys are clustered in MySQL, they always go at the end.
But, you don't have to follow that advice. My recommendation would be to insert the data into a new table and reload into your desired table:
create temporary table tt as
select t.*
from tt
group by tt.uuid;
truncate table t;
alter table t add constraint pk_uuid primary key (uuid);
insert into t
select * from tt;
Note: I am using a (mis)feature of MySQL that allows you to group by one column while pulling columns not in the group by. I don't like this extension, but you do not specify how to choose the particular row you want. This will give values for the other columns from matching rows. There are other ways to get one row per uuid.
There are four regions with more than one million records total. Should I create a table with a region column or a table for each region and combine them to get the top ranks?
If I combine all four regions, none of my columns will be unique so I will need to also add an id column for my primary key. Otherwise, name, accountId & characterId would be candidate keys or should I just add an id column anyways.
Table:
----------------------------------------------------------------
| name | accountId | iconId | level | characterId | updateDate |
----------------------------------------------------------------
Edit:
Should I look into partitioning the table by region_id?
Because all records are related to a particular region, a single database table in 3NF(e.g All-Regions) containing a regionId along with other attributes should work.
The correct answer, as usually with database design, is "It depends".
First of all, (IMHO) a good primary key should belong to the database, not to the users :)
So, if accountId and characterId are user-editable or prominently displayed to the user, they should not be used for the primary key of the table(s) anyway. And using name (or any other user-generated string) for a key is just asking for trouble.
As for the regions, try to divine how the records will be used.
Whether most of the queries will use only a single region, or most of them will use data across regions?
Is there a possibility that the schemas for different regions might diverge?
Will there be different usage scenarios for similar data? (e.g. different phone number patterns for different regions)
Bottom line, both approaches will work, let your data tell you which approach will be more manageable.
How can I enforce constraint checks to ensure that a given combination of values are unique, but can be entered any number of times?
Example: I have two columns: Group_ID and Group_Name. So all data with Group_ID = 1 will always have Group_Name as 'Test1'. What I want to prevent is someone entering 'Test2' into Group_Name where Group_ID=1. This should fail the insert. All this data is loaded directly into the DB without any UI, hence I cannot enforce these checks in application. So what I need is:
A unique constraint over multiple columns, but only for the given combination without checking how many times they have been entered.
Is there anything built in Mysql to do this?
You should normalize your table a little bit. The group_id,group_name pair should be in a separate table that defines your groups and then the table you're working with should only have group_id. Then you could add a foreign key from your table to the group table to ensure that your group_id values reference real groups.
If you can't normalize your tables then you'll probably have to use a before insert and before update trigger to ensure that Group_ID and Group_Name always come together as required.