SQL Server having a column as both PK and FK - sql-server

I have not done much database design work and I was searching around for some example.
While I know the difference from a primary and foreign key, one thing that caught be off guard was that even if a Table has a primary key and is used as a foreign key in another table, as I was used the GUI SSMS tools, I noticed that I sometime end up having this
PhoneID (PK, int, not null)
While my User table
UserId(PK,FK, int, not null)
BOTH of these tables have these ID's as primary keys in those tables, along with foreign keys in other tables, but why does one of them have "PK,FK" obviously I accidentally created it, but should it be like that?

It is Possible for a Primary key to be a Foreign Key as well at the same time.
But looking at you database design, In your case I dont think it was intentional it was done by mistake. And if it wasnt done by mistake then you need to fix it.
In your dbo.PhoneType Table the column PhoneTypeID needs to be a Primary key only not a Foreign key. My guess is this was done by mistake, you wanted to create a Foreign key in your dbo.Phone table on column PhoneTypeID referencing PhoneTypeID column in dbo.PhoneType table. But somehow you end up create a foreign key constraint on the Primary key column of the dbo.Phontype table.
This Design contradicts constraints.
In simple english : The foreign Key Constraint on your dbo.PhoneType(PhoneTypeID) enforces that you cannot have a PhoneTypeID in dbo.PhoneType table unless it exists in PhoneTypeID column of dbo.Phone table.
On the other hand Foreign Key Constraint on dbo.Phone(PhoneTypeID) enforces that you cannot have a PhoneTypeID in dbo.Phone unless it exists in dbo.PhoneType(PhoneTypeID).
and same is true for the UserID column in dbo.Users table.
Solution
You need to drop the following Constraints to make it work properly.
1) In dbo.PhoneType table Drop Foreign key constraint referencing
PhoneTypeID column in dbo.phone table.
2) In dbo.Users Table drop the Drop Foreign key constraint referencing
UserID column in dbo.phone table.

It's entirely possible, yes. A primary key of a table could also be a foreign key referencing another table.
In your case, I'm not exactly sure what you did. You can check the constraints to see which column the UserId column is referencing.
As an additional note, simply adding a foreign reference to a table does not implicitly make that column a foreign key on another table. For example, just because you add FK_PhoneTypeID to the Phone table, SQL Server does not automatically make PhoneTypeID column in the PhoneType table a FK. In your statements, somewhere, it's possible that you made assignments to other columns, or even to themselves.

Related

Primary key column with Foreign key reference to itself

I came across this T-SQL code in a client's database today:
CREATE TABLE dbo.Dates
(
MarketDate date,
PRIMARY KEY (MarketDate),
FOREIGN KEY (MarketDate) REFERENCES dbo.Dates (MarketDate)
)
It is unclear to me what purpose can be served by allowing the primary key column to have a foreign key relationship back to itself. Naturally I have deleted the relationship.
Would this foreign key have any effect at all? Is there ever a use case which would justify using it? If not then why would SQL Server permit such a relationship.
The only reason I can imagine is that the creator of the table wanted to disallow the use of TRUNCATE TABLE statements against the Dates table.

Adding column with existing table which have primary key

I need your help...., Please help me
I want to add a new primary key to an existing table which already has 3 columns as composite primary key. But, I do not want to drop the old primary key, since there are many records and the old primary key also have relationship with other table
When I am using this query:
alter table hem154
add indexNO uniqueidentifier default newid()
alter table hem154
add CONSTRAINT pk_hem154_indexNo PRIMARY KEY (PK_indexNO)
Note:
Hem154 ~ Table Name
indexNo ~ Column Name which will to added
I get this runtime error:
Msg 1779, Level 16, State 0, Line 1
Table 'hem154' already has a primary key defined on it.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
Please help me, how can I do it???
Thanks
Drop all primary keys and add Again all primary keys
ALTER TABLE hem154
DROP PRIMARY KEY,ADD PRIMARY KEY (col1,col2,indexNO);
You can only have one primary key per table. You can either add a second table that maps your new PK to the old PK, or drop the old PK and add the new one. Dropping the PK won't drop the columns, it just stops using them as the composite key. Any tables that were relying on the old key should probably be updated as well to support whatever answer you decide on.
First DROP existing PRIMARY KEY and ADD new composite PRIMARY KEY.
ALTER TABLE Table1
DROP CONSTRAINT PK_Table1_Col1
GO
and then try your code
There is no easy way of doing this. From your question, I understand that you want to add one additional column to the existing Primary Key. If they have existing relationships, then it is not possible to do this, without dropping those FK constraints first. Even if you do that, you will not be able to reestablish those FK constraints again, as you have modified the PK.
If you do not need to reestablish those FK relationships, then you can do this:
Drop all FK relationships
Drop existing PK (data will not be deleted, only the constraint will be dropped)
Add new column
Recreate PK to include the new column
However, if you cannot drop the existing FK constraints, then I am afraid this is not possible
On Microsoft SQL Server Management Studio:
Select/highlight both columns
Right click either
Press "Set primary key"

Varchar datatype as primary key in in many-to-many relationship

I have a table with a varchar datatype as the primary key. I'm trying to make a relationship to the junction table of this many-to-many relationship. I keep getting the error
The ALTER TABLE statement conflicted with the foreign key constraint
relationship name.
I don't know what the deal is here. Since I have designated the field as a primary key and it was accepted, this means there are no dupes. Both the foreign key and the primary key are of the same datatype, with the same length. Neither one allows nulls. What else could the problem be?
Most likely, you have a value in your junction table that does not exist in the primary table, which prevents you from creating the foreign key relationship.
Try to find it with something like:
SELECT j.ICD_FK
FROM ICD_Junction j
LEFT JOIN ICD_text t
ON j.ICD_FK = t.ICD_ID
WHERE t.ICD_ID IS NULL;
Just because there are no nulls or duplicates does not mean that you're not violating a foreign key relationship.
I'm guessing that the FK column has values in it that do not exist in the PK column. Check by using a LEFT OUT JOIN WHERE NULL.

Are foreign keys indexed automatically in SQL Server?

Would the following SQL statement automatically create an index on Table1.Table1Column, or must one be explicitly created?
Database engine is SQL Server 2000
CREATE TABLE [Table1] (
. . .
CONSTRAINT [FK_Table1_Table2] FOREIGN KEY
(
[Table1Column]
) REFERENCES [Table2] (
[Table2ID]
)
)
SQL Server will not automatically create an index on a foreign key. Also from MSDN:
A FOREIGN KEY constraint does not have
to be linked only to a PRIMARY KEY
constraint in another table; it can
also be defined to reference the
columns of a UNIQUE constraint in
another table. A FOREIGN KEY
constraint can contain null values;
however, if any column of a composite
FOREIGN KEY constraint contains null
values, verification of all values
that make up the FOREIGN KEY
constraint is skipped. To make sure
that all values of a composite FOREIGN
KEY constraint are verified, specify
NOT NULL on all the participating
columns.
As I read Mike's question, He is asking whether the FK Constraint will create an index on the FK column in the Table the FK is in (Table1). The answer is no, and generally. (for the purposes of the constraint), there is no need to do this The column(s) defined as the "TARGET" of the constraint, on the other hand, must be a unique index in the referenced table, either a Primary Key or an alternate key. (unique index) or the Create Constraint statment will fail.
(EDIT: Added to explicitly deal with comment below -)
Specifically, when providing the data consistency that a Foreign Key Constraint is there for. an index can affect performance of a DRI Constraint only for deletes of a Row or rows on the FK side. When using the constraint, during a insert or update the processor knows the FK value, and must check for the existence of a row in the referenced table on the PK Side. There is already an index there. When deleting a row on the PK side, it must verify that there are no rows on the FK side. An index can be marginally helpful in this case. But this is not a common scenario.
Other than that, in certain types of queries, however, where the query processor needs to find the records on the many side of a join which uses that foreign key column. join performance is increased when an index exists on that foreign key. But this condition is peculiar to the use of the FK column in a join query, not to existence of the foreign Key constraint... It doesn't matter whether the other side of the join is a PK or just some other arbitrary column. Also, if you need to filter, or order the results of a query based on that FK column, an index will help... Again, this has nothing to do with the Foreign Key constraint on that column.
No, creating a foreign key on a column does not automatically create an index on that column. Failing to index a foreign key column will cause a table scan in each of the following situations:
Each time a record is deleted from the referenced (parent) table.
Each time the two tables are joined on the foreign key.
Each time the FK column is updated.
In this example schema:
CREATE TABLE MasterOrder (
MasterOrderID INT PRIMARY KEY)
CREATE TABLE OrderDetail(
OrderDetailID INT,
MasterOrderID INT FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)
OrderDetail will be scanned each time a record is deleted in the MasterOrder table. The entire OrderDetail table will also be scanned each time you join OrderMaster and OrderDetail.
SELECT ..
FROM
MasterOrder ord
LEFT JOIN OrderDetail det
ON det.MasterOrderID = ord.MasterOrderID
WHERE ord.OrderMasterID = #OrderMasterID
In general not indexing a foreign key is much more the exception than the rule.
A case for not indexing a foreign key is where it would never be utilized. This would make the server's overhead of maintaining it unnecessary. Type tables may fall into this category from time to time, an example might be:
CREATE TABLE CarType (
CarTypeID INT PRIMARY KEY,
CarTypeName VARCHAR(25)
)
INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')
CREATE TABLE CarInventory (
CarInventoryID INT,
CarTypeID INT FOREIGN KEY REFERENCES CarType(CarTypeID)
)
Making the general assumption that the CarType.CarTypeID field is never going to be updated and deleting records would be almost never, the server overhead of maintaing an index on CarInventory.CarTypeID would be unnecessary if CarInventory was never searched by CarTypeID.
According to: https://learn.microsoft.com/en-us/sql/relational-databases/tables/primary-and-foreign-key-constraints?view=sql-server-ver16#indexes-on-foreign-key-constraints
Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index

Modifying an existing column to a foreign key

I have an oracle db which has no Foreign Keys, all table relations are handled by the software. For example, table Customer with columns Customer.customercode, Customer.Name where customercode is the primary key and table Order with columns Order.ordercode (PK), Order.customercode where customercode has no foreign key constraint. So far the application handles all transactions and takes care of all the table relations so that the data are consistent. I need to change this to a proper relational DB implementation, so I need to modify Order.customercode to be a FK from table Customer. Any sqlplus statement to do this without losing my data?
In Oracle, creating a foreign key would never lose any data, but it will fail if the data doesn't correspond to the new constraint. Assuming your data is OK, you can use an alter table statement:
ALTER TABLE order
ADD CONSTRAINT order_customer_fk FOREIGN KEY (customercode)
REFERENCES customer(customercode)

Resources