Is alternate key indicated while creating a table but this alternate key isn't posted from any other table - sql

The question is that if I have relation R(A,B,C,D) where A is PK and C if Alternate key for that relation, would I, while creating table based on that relation, need to indicate that C is an unique key? What I mean is:
create table R (
A A's domain,
B B's domain,
C C's domain,
D D's domain,
primary key A,
unique C
)
Do I have to specify that C is an unique key for that table even though this key isn't posted from any other table (it is just a canditate key which hasn't been selected to be a primary key?

Unique Key is a constraint, which means if you declare C as unique , then no duplicates values will be allowed for that column. If you do not specify it , it can have duplicate values, thus failed as a candidate key

If specifying it will prevent incorrect data from being inserted into the table (such that there are two rows with the same value in C), then the only reason not to do so is if it has proven to be a performance issue, and if you've demonstrated that incorrect data is prevented through some other mechanism.

Related

SQL Composite Key

I am a SQL newbie and here is a question that I cannot find a solution yet.
Say I have tables User and Partner. I want to have a composite key for Partner, which is a pair of User's. So I can have keys (A,B) and (B,A) where A and B are both users. I want to have that (A,B) and (B,A) refer to the same Partner entity. This seems to be a common problem but I could not find an answer.
Ok, more concretely,
CREATE TABLE User
(
ID int,
....
)
PRIMARY KEY (ID);
CREATE TABLE Partner
(
User1 UserID,
User2 UserID
...
)
PRIMARY KEY (User1, User2)
What I want is that (User1, User2) and (User2, User1) represent the same partnership.
Instead of trying to to make (A,B) and (B,A) considered as the same, you can take an arbitrary decision to always have A have the lower ID (*), and back it up with constraints;
CREATE TABLE partner (
a INT NOT NULL,
b INT NOT NULL,
PRIMARY KEY (a, b),
CHECK (a < b),
FOREIGN KEY (a) REFERENCES user(id),
FOREIGN KEY (b) REFERENCES user(id)
)
(*) Or the larger one - it doesn't really matter, as long as you're consistent.
You have two options. One is to ensure that both (a, b) and (b, a) are in the table. You can do this using a trigger when you insert a row.
The second is to include only one of the pair -- normally as an ordered pair.
Basically, it depends on how you are going to use the table. The first method requires twice as much storage, but it is simpler to get all the partners of a given user.
If you want to ensure that both pairs must be included in the table then just add another constraint:
ALTER TABLE Partner ADD FOREIGN KEY (User2,User1) REFERENCES Partner (User1,User2);

Foreign and Primary Key Conceptual Questions

I am a newbie at SQL/PostgreSQL, and I had a conceptual question about foreign keys and keys in general:
Let's say I have two tables: Table A and Table B.
A has a bunch of columns, two of which are A.id, A.seq. The primary key is btree(A.id, A.seq) and it has a foreign key constraint that A.id references B.id. Note that A.seq is a sequential column (first row has value 1, second has 2, etc).
Now say B has a bunch of columns, one of which is the above mentioned B.id. The primary key is btree(B.id).
I have the following questions:
What exactly does btree do? What is the significance of having two column names in the btree rather than just one (as in btree(B.id)).
Why is it important that A references B instead of B referencing A? Why does order matter when it comes to foreign keys??
Thanks so much! Please correct me if I used incorrect terminology for anything.
EDIT: I am using postgres
A btree index stored values in sorted order, which means you can not only search for a single primary key value, but you can also efficiently search for a range of values:
SELECT ... WHERE id between 6060842 AND 8675309
PostgreSQL also supports other index types, but only btree is supported for a unique index (for example, the primary key).
In your B table, the primary key being a single column id means that only one row can exist for each value in id. In other words, it is unique, and if you search for a value by primary key, it will find at most one row (it may also find zero rows if you don't have a row with that value).
The primary key in your A table is for (id, seq). This means you can have multiple rows for each value of id. You can also have multiple rows for each value of seq as long as they are for different id values. The combination must be unique though. You can't have more than one row with the same pair of values.
When a foreign key in A references B, it means that the row must exist in B before you are allowed to store the row in A with the same id value. But the reverse is not necessary.
Example:
Suppose B is for users and A is for phones. You must store a user before you can store a phone record for that user. You can store one or more phones for that user, one per row in the A table. We say that a row in A therefore references the user row in B, meaning, "this phone belongs to user #1234."
But the reverse is not restricted. A user might have no phones (at least not known to this database), so there is no requirement for B to reference A. In other words, it is not required for a user to have a phone. You can store a row in B (the user) even if there is no row in A (the phones) for that user.
The reference also means you are not allowed to DELETE FROM B WHERE id = ? if there are rows in another table that reference that given row in B. Deleting that user would cause those other rows to become orphaned. No one would be able to know who those phones belonged to, if the user row they reference is deleted.
To your questions:
There are several strategies to implement unique keys. The most common one is to use an index that is "unique" using a "b-tree" strategy. That's what "btree" means in PostgreSQL.
Having two columns in a key just depends on how you want to design your table. When you have a key with more than one column that is called a "composite key".
When A references B, the columns in B must represent a "key". The columns in A do not represent a key, but just a reference to one. In fact the values in A for that column can be repeated; that is, multiple rows in A can point to the same row in B.
Your data structure makes no sense. Why would the primary key of A haver both id and name? Normally it would just be id. In some data models, you might have a version or timestamp added. I can't think of a reasonable data model where name would also be included.
In addition, B's foreign key would have to be to both id and name.
But, your question is what is btree for? Most databases don't have such an option. A primary key would typically be expressed as:
id int primary key;
constraint unq_t_id primary key (id);
btree is a type of index -- in fact the default type of index in all databases that I'm aware of. Databases that have a plethora of available types of indexes -- such as Postgres -- you can specify the index type associated with the primary key.

Composite primary keys and link table rules

I have a many to many relationship with a link table and I need to formalise a rule set. Following is my problem:
Left (L) and Right (R) (L&R) Table: both have composite (thanks stakx for correcting me) primary keys. Link table has its own primary key but obviously, because the L&R tables have each composite primaries the link table must contain multiple foreign keys. No problem. i.e.
L Table:
LID (int) PK1
LSomeDate (DateTime) PK2
Other Fields...
R Table:
RID (int) PK1
RSomeDate (DateTime) PK2
Other Fields...
Link Table:
ID (int) PK
LID (int) FK1
LSomeDate (DateTime) FK1
RID (int) FK2
RSomeDate (DateTime) FK2
Requirement 1: An entity in either table can exist without the other. So instead of a 1:M we should have a 0:M on both sides of the M:M. I am guessing (perhaps wrongly) that this means I must leave the link table foreign keys null. But if I do this, I can enter say LID and leave the LSomeDate field null. or vice versa. Likewise with the RID and RSomeDate.
My first question is, what is the standard way to create some "whatever (rule, constraint, default, trigger etc)" that will force the user to enter an LID if a LSomeDate was entered or enter an LSomeDate if an LID was entered. I can then apply the same to the R FK. This will prevent leaving nulls in part of the FK.
Essentially...Either the whole L side of the FK is null, or both fields are filled (a valid ref). Likewise for the R but this would be separate.
My other question is...When creating link tables, should the L table contain a FKID of the right table and vice versa, for example...Should the L Table above also contain RID and RSomeDate as foreign keys, and vice versa on the R Table, or is the fact that these are specified in the link table enough.
Thanks in advance.
The only reason for having an entry in the link table is to link one L record to another R record. If one L exists without being linked to any R, then there is an recird in L, but there will be no entry for this particular combination of L and R in the link table.
That is, an entry in the N:N link table exists only if an L and an R are associated. That is, if two records L and R are not linked ("one exists without the other"), then there simply won't be an entry in the link table. And therefore, there is never even the need for NULL values in the link table.
Meaning, ideally, all your link table columns are declared NOT NULL; and suddenly your problem goes away!
(This btw. has nothing to do with your primary keys being composite; the same fact would hold for non-composite keys.)
If you, despite this fact, still wanted to declare these columns NULLable, and you wanted to ensure, at the database level, that e.g. all L foreign keys in your link table are not partially NULL, you could add a CHECK constraint:
ALTER TABLE LinkTable
ADD CONSTRAINT CK_LinkTable_LID_LSomeDate
CHECK ((LID IS NULL AND LSomeDate IS NULL )
OR (LID IS NOT NULL AND LSomeDate IS NOT NULL))
But again, it would be infinitely better if all of these foreign key columns were NOT NULLable in the first place, because that's how a N:N link table should be designed.

Database design queries regarding inheritance and foreign key references

I have a query regarding a design problem that I faced …
There is a table A with subtypes B and C. Table A has an attribute type which tells whether the type is B or C. The common attributes of B and C are in A .
The problem is that there are no extra attributes for B .. all attributes required for B are in A already. However , there are extra attributes for C.
Is it an acceptable solution if I make tables A and C only ??… to extract entities of B I will query through the type attribute from table A
Can you refer any material ?
I also had a another confusion where table A has subtypes B,C,D . Table Z has a column that requires a value of primary id of either B or C but NOT D.
I thought of adding the primary id column of A as a foreign key reference to Z’s column and then making a trigger to ensure that the id isn't D ...
Can anyone please comment ?
Thank you !
Many people just enforce all these rules in application code. That is, they "simply" don't insert wrong data. Of course this is very fragile and depends on writing perfect application code at all times. So we want the database to enforce the constraints instead, so that wrong data can never be inserted.
CREATE TABLE A (
id INT PRIMARY KEY,
type CHAR(1) NOT NULL,
unique key (id, type)
);
CREATE TABLE B (
id INT PRIMARY KEY,
type CHAR(1) NOT NULL DEFAULT 'B',
FOREIGN KEY (id, type) REFERENCES A(id, type)
);
If you can force B.type to always be 'B' (CHECK constraint, trigger, or reference a one-row lookup table) then it can of course reference parent rows in A where type='B'. And do something similar in tables C and D, so then each row of A can be referenced by a row from only one sub-type table.
That is, if A.type is 'B' on a given row, and C.type can only be 'C', then no row of C can reference any row where A.type is 'B'.
Now if you want table Z to reference B or C but not D, you can reference by id and type, so Z also has its own type column. You can restrict Z.type by using a lookup table:
CREATE TABLE Ztypes (
type CHAR(1) PRIMARY KEY
);
INSERT INTO Ztypes VALUES ('B'), ('C');
CREATE TABLE Z (
id INT PRIMARY KEY,
Aid INT NOT NULL,
type CHAR(1) NOT NULL,
FOREIGN KEY (Aid, type) REFERENCES A(id, type),
FOREIGN KEY (type) REFERENCES Ztypes(type)
);
You've already got the answer you were looking for. But for other who run across this, it's worth researching two techniques: Class Table Inheritance and Shared Primary Key.
These two techniques used together make it fast, simple and easy to join A's data with either B's or C's data. And in this pattern, B contains only the key, but still contains usefull informaton.
Both of these techiques have their own tags.

SQL Server 2008: The columns in table do not match an existing primary key or unique constraint

I need to make some changes to a SQL Server 2008 database.
This requires the creation of a new table, and inserting a foreign key in the new table that references the Primary key of an already existing table. So I want to set up a relationship between my new tblTwo, which references the primary key of tblOne.
However when I tried to do this (through SQL Server Management Studio) I got the following error:
The columns in table 'tblOne' do not
match an existing primary key or
UNIQUE constraint
I'm not really sure what this means, and I was wondering if there was any way around it?
It means that the primary key in tblOne hasn't been properly declared - you need to go to tblOne and add the PRIMARY KEY constraint back onto it.
If you're sure that tblOne does have a PRIMARY KEY constraint, then maybe there are multiple tblOne tables in your DB, belonging to different schemas, and your references clause in your FK constraint is picking the wrong one.
If there's a composite key (which your comment would indicate), then you have to include both columns in your foreign key reference also. Note that a table can't have multiple primary keys - but if it has a composite key, you'll see a key symbol next to each column that is part of the primary key.
If you have a composite key the order is important when creating a FK, and sometimes the order is not how it is displayed.
What I do is go to the Keys section of the table1 and select script primary key as create to clipboard and then create FK using the order as shown in script
I've had this situation that led me to this topic. Same error but another cause. Maybe it will help someone.
Table1
ColA (PK)
ColB (PK)
ColC
Table2
ID (PK)
ColA
COLB
When trying to create foreign key in Table2 I've choose values from combobox in reverse order
Table1.ColB = Table2.ColB
Table1.ColA = Table2.ColA
This was throwing me an error like in topic name. Creating FK keeping order of columns in Primary key table as they are, made error disappear.
Stupid, but.. :)
If you still get that error after you have followed all advice from the above answers and everything looks right.
One way to fix it is by Removing your Primary keys for both tables, Save, Refresh, and add them again.
Then try to add your relationship again.
This Error happened with me When I tried to add foreign key constraint starting from PrimaryKey Table
Simpy go to other table and and create this foreign key constraint from there (foreign key Table)
This issue caught me out, I was adding the relationship on the wrong table. So if you're trying to add a relationship in table A to table B, try adding the relationship in table B to table A.
That looks like you are trying to create a foreign key in tblTwo that does not match (or participate) with any primary key or unique index in tblOne.
Check this link on MSDN regarding it. Here you have another link with a practical case.
EDIT:
Answwering to your comment, I understand you mean there are 2 fields in the primary key (which makes it a composite). In SQL it is not possible to have 2 primary keys on the same table.
IMHO, a foreign key field should always refer to a single register in the referenced table (i.e. the whole primary key in your case). That means you need to put both fields of the tblOne primary key in tblTwo before creating the foreign key.
Anyway, I have investigated a bit over the Internet and it seems SQL Server 2008 (as some prior versions and other RDBMS) gives you the possibility to reference only part of the primary key as long as this part is a candidate key (Not Null and Unique) and you create an unique constraint on it.
I am not sure you can use that in your case, but check this link for more information on it.
I have found that the column names must match.
Example:
So if tblOne has id called categoryId a reference in tblTwo must also be called categoryId.
_tblname, primary key name, foreign key_
tblOne, "categoryId", none
tblTwo, "exampleId", "categoryId"
I noticed this when trying to create foreign key between 2 tables that both had the column name "id" as primary key.
If nothing helps, then this could be the reason:
Considering this case:
Table A:
Column 1 (Primary Key)
Column 2 (Primary Key)
Column 3
Column 4
Table B:
Column a (Primary Key)
Column b
Column c
when you are defining a dependency B to A, then you are forced to respect the order in which the primaries are defined.
That's mean your dependency should look like this:
Table A Table B
Column 1 Column b
Column 2 Column c
AND NOT:
Table A Table B
Column 2 Column c
Column 1 Column b
then this will lead to the error you are encountering.
I've found another way to get this error. This can also happen if you are trying to make a recursive foreign key (a foreign key to the primary key in the same table) in design view in SQL Management Studio. If you haven't yet saved the table with the primary key it will return this message. Simply save the table then it will allow you to create the foreign key.
If you have data in your tables this could be the issue.
In my case I had some data in the Account table that I loaded at 3 pm, and some data in Contact table that I loaded at 3:10 pm, so Contact table had some values that weren't in my Account table yet.
I ended up deleting these values from the contact table and then managed to add a key without any problems.
Kindly also see that there are no existing data inside the table where the primary key is defined while setting the foreign key with another table column.
this was the cause of the error in my case.
I had to take backup empty the table set the relationship and then upload the data back.
sharing my experience
Was using ms sql smss