I have an SQL table with basically the following structure:
PK (int, primary key), userID (int), data (varchar 64)
Basically, any user as defined by userID is allowed to store any number of short strings. However, no user is allowed to store two identical strings (although user 1 and user 2 can both store the same string separately). I would, if at all possible, like to implement this restriction at the database level because IMHO structural constraints should always be in the tables, as well as in the programs inserting/reading data from the tables.
The only thing I can think of is adding a third column in which I concatenate userID and data upon every insert, and call that column unique, but that seems too "hacky" to me. I am open to completely restructuring my tables if one of you guys has a better way of doing this that will allow me to put this constraint on the fields :)
Thanks!
Mala
Sounds like you need a composite unique constraint on the userID and data columns.
like this:
CONSTRAINT my_contraint_name UNIQUE ([userID], [data])
What if we have a unique constraint on UserId and Data. I hope it should solve your issue.
You want a composite key, which you can add to your table tablename like this in MySQL:
ALTER TABLE `tablename` ADD UNIQUE KEY (`userID`, `data`);
I think the simplest solution would be to create an index
create unique index ui on table (userID, data)
though there may be an overhead with this.
This kind of looks like it should be your primary key as well, though that really depends on the role PK and userId play in tables throughout the rest of the schema.
I think a composite key will do the task. Create a composite key with UserId and data columns. In this case, when a user tries to insert same data morethan once, it will throw error, which you can catch in your application and show the user an appropriate error message.
Hope it helps...
Thanks.
Related
I have a table which represents users connected to a game room. It looks like this:
id | gameRoomId | userId
------------------------
0 abc bob
1 xyz joe
2 xyz frank
...
Is there a way I can remove the auto-increment primary-key id column? I'm not using it for any queries, and don't plan to.
The gameRoomId and userId have a generic index on them individually.
I'm using mysql now, might switch to postgres eventually, if it matters.
It is not obligatory for a table to have a primary key constraint. Where a table does have a primary key, it is not obligatory for that key to be automatically generated. In some cases, there is no meaningful sense in which a given primary key even could be automatically generated.
You should be able to remove your existing primary key column from the database like so:
alter table my_table drop column id;
or perhaps you can avoid creating it in the first place.
Whether this is a wise thing to do depends on your circumstances.
Your table looks like a relationship table. It represents the many-to-many relationship between gamerooms and users. Assuming that a given combination of the two can occur only once (which seems reasonable), you could declare a composite primary key of those two columns, and do without the id field.
Some design tools require a simple primary key, but that's not part of relational modeling as such.
At the physical level, declaring a primary key would have a variety of consequences. The index created for you would be a compound one. It would be slightly more efificient if you used integers for userids and gemeroomids, instead of the character strings you have shown.
As far as not declaring any primary key goes, I don't recommend that. Sooner or later, you'll have a bug in your application that lets duplicate rows in there, and you'll start to get unexpected results from your queries. It's far better to let the DBMS help you manage your data.
No.
A primary key must be unique and that has to be 100% guaranteed, and NON NULL
A primary key should be stable if ever possible and not change.
So you don't have to, but it's a good choice since there is no other naturally unique data and you don't want to have enormous primary keys.
To answer your sub-question, you wouldn't really want to, it's not taking that much data and it's unique.
I have a small table "ImgViews" that only contains two columns, an ID column called "imgID" + a count column called "viewed", both set up as int.
The idea is to use this table only as a counter so that I can track how often an image with a certain ID is viewed / clicked.
The table has no primary or foreign keys and no relationships.
However, when I enter some data for testing and try entering the same imgID multiple times it always appears greyed out and with a red error icon.
Usually this makes sense as you don't want duplicate records but as the purpose is different here it does make sense for me.
Can someone tell me how I can achieve this or work around it ? What would be a common way to do this ?
Many thanks in advance, Tim.
To address your requirement to store non-unique values, simply remove primary keys, unique constraints, and unique indexes. I expect you may still want a non-unique clustered index on ImgID to improve performance of aggregate queries that would otherwise require a scan the entire table and sort. I suggest you store an insert timestamp, not to provide uniqueness, but to facilitate purging data by date, should the need arise in the future.
You must have some unique index on that table. Make sure there is no unique index and no unique or primary key constraint.
Or, SSMS simply doesn't know how to identify the row that was just inserted because it has no key.
It is generally not best practice to have a table without a (logical) primary key. In your case, I'd make the image id the primary key and increment the counter. The MERGE statement is well-suited for performing and insert or update at the same time. Alternatives exist.
If you don't like that, create a surrogate primary key (an identity column set as the primary key).
At the moment you have no way of addressing a specific row. That makes the table a little unwieldy.
If you allow multiple rows being absolutely identical, how would you update/delete one of those rows?
How would you expect the database being able to "know" what row you referred to??
At the very least add a separate identity column (preferred being the clustered index, too).
As a side note: It's weird that you "like to avoid unneeded data" but at the same time insert duplicates over and over again instead of simply add up the click count per single image...
Use SQL statements, not GUI, if the table has not primary key or unique constraint.
How do I store custom values in place of data types for the column.
I have a Table named as 'Orders' in which a column named as 'OrderStatus' and it's purpose will be to store the Status of the Order. For example R=Rejected, S=Sent, T=Returned.
I am very new to databases and design...
The 'correct' answer is to use Standard SQL-92's CREATE DOMAIN. Sadly, SQL Server doesn't support it yet. If you would like to see support you can vote for it here.
SQL Server has its own CREATE TYPE syntax but when I last looked I declared them not fit for purpose. If anyone disagrees, please post an answer to my question :)
This leaves two viable choices: a table with a foreign keys or CHECK constraints. The rule of thumb is that if the set of domain values is small and stable (e.g. the ISO 5218 sex codes) then use CHECK constraints, otherwise prefer a table with foreign keys.
In this case you don't really need a custom data type, you just need a foreign key to a table with all of your statuses in it.
Your OrderStatus table would look like:
id int PK NOT NULL, IDENTITY
code char(1) NOT NULL
description varchar(100) NOT NULL
(edit: note, as Martin pointed out in a comment on another answer, the surrogate id key isn't entirely necessary, but it allows flexibility for easily changing the code without having to update the data that refers to it)
Your Order table would then have a foreign key to this table:
order_status_id int FK NOT NULL
You can do that.
OrderStatus OrderStatusCode
----------- ---------------
Rejected R
Sent S
Returned T
Later, when you've got more 'design' under your belt, you go with a lookup table.
Best practice is to normalize, which means creating a table called ORDER_STATUS with the approved values in there, minimally with a schema like:
ORDER_STATUS(id number auto increment, code character, meaning varchar)
and then relate ORDERS to that table in a column called order_status_id, which would be a foreign key that would not be null.
i want to ask a small question here but i really don't know what is the answer of this question.
i have a accounts table which has
Username | Password
the username is a primary key so its unique
so is it necessary to put an ID column to the table ? if Yes, what is the benefit of that ?
Thanks
Search by a numeric key is slightly faster (varies from one DB to another). Also, if you have a lot of references to the user table, you save some database space by having the numeric ID as the foreign key, as opposed to a string name.
It will make everything else easier, mainly foreign key relationships from other tables. And it allows you to change the username if you want - primary keys are not easy to change.
Faster in indexes
Consumes less disk space (and is again faster) when used as a foreign key
And, as mentioned a number of times, you can change the username without modifying a host of other tables.
I have a table with sets of settings for users, it has the following columns:
UserID INT
Set VARCHAR(50)
Key VARCHAR(50)
Value NVARCHAR(MAX)
TimeStamp DATETIME
UserID together with Set and Key are unique. So a specific user cannot have two of the same keys in a particular set of settings. The settings are retrieved by set, so if a user requests a certain key from a certain set, the whole set is downloaded, so that the next time a key from the same set is needed, it doesn't have to go to the database.
Should I create a primary key on all three columns (userid, set, and key) or should I create an extra field that has a primary key (for example an autoincrement integer called SettingID, bad idea i guess), or not create a primary key, and just create a unique index?
----- UPDATE -----
Just to clear things up: This is an end of the line table, it is not joined in anyway. UserID is a FK to the Users table. Set is not a FK. It is pretty much a helper table for my GUI.
Just as an example: users get the first time they visit parts of the website, a help balloon, which they can close if they want. Once they click it away, I will add some setting to the "GettingStarted" set that will state they helpballoon X has been disabled. Next time when the user comes to the same page, the setting will state that help balloon X should not be shown anymore.
Having composite unique keys is mostly not a good idea.
Having any business relevant data as primary key can also make you troubles. For instance, if you need to change the value. If it is not possible in the application to change the value, it could be in the future, or it must be changed in an upgrade script.
It's best to create a surrogate key, a automatic number which does not have any business meaning.
Edit after your update:
In this case, you can think of having conceptually no primary key, and make this three columns either the primary key of a composite unique key (to make it changeable).
Should I create a primary key on all three columns (userid, set, and key)
Make this one.
Using surrogate primary key will result in an extra column which is not used for other purposes.
Creating a UNIQUE INDEX along with surrogate primary key is same as creating a non-clustered PRIMARY KEY, and will result in an extra KEY lookup which is worse for performance.
Creating a UNIQUE INDEX without a PRIMARY KEY will result in a HEAP-organized table which will need an extra RID lookup to access the values: also not very good.
How many Key's and Set's do you have? Do these need to be varchar(50) or can they point to a lookup table? If you can convert this Set and Key into SetId and KeyId then you can create your primary key on the 3 integer values which will be much faster.
I would probably try to make sure that UserID was a unique identifier, rather than having duplicates of UserID throughout the code. Composite keys tend to get confusing later on in your code's life.
I'm assuming this is a lookup field for config values of some kind, so you could probably go with the composite key if this is the case. The data is already there. You can guarantee it's uniqueness using the primary key. If you change your mind and decide later that it isn't appropriate for you, you can easily add a SettingId and make the original composite key a unique index.
Create one, separate primary key. No matter what how bussines logic will change, what new rules will have to be applied to your Key VARCHAR(50) field - having one primary key will make you completly independent of bussines logic.
In my experience it all depends how many tables will be using this table as FK information. Do you want 3 extra columns in your other tables just to carry over a FK?
Personally I would create another FK column and put a unique constraint over the other three columns. This makes foreign keys to this table a lot easier to swallow.
I'm not a proponent of composite keys, but in this case as an end of the line table, it might make sense. However, if you allow nulls in any of these three fields becasue one or more of the values is not known at the time of the insert, there can be difficulty and a unique index might be better.
Better have UserID as 32 bit newid() or unique identifier because UserID as int gives a hint to the User of the probable UserID. This will also solve your issue of composite key.