Yes, one column can identify a row and point to a parent row, and foreign-key columns can also sit inside a composite ID.
A primary key can be a foreign key. The same column can do two jobs at once: mark one row as that table’s own ID and tie that row to a parent row in another table. You’ll see this most often in one-to-one table splits, subtype tables, and bridge tables where one or more foreign-key columns make up the full row ID.
The rule is simple. The primary-key side says the value must be present and must not repeat inside the table. The foreign-key side says the value must already exist in the parent table. If both statements are true, the design is valid.
The catch is fit. A shared key is tidy when the child row cannot stand on its own. It gets messy when the child row has its own timing or many links in and out.
Can Primary Key Be A Foreign Key? Cases That Fit
There are two common ways the answer becomes “yes.” They solve different problems.
- Shared primary key: the child table uses the same single column as both its row ID and its link to the parent table. This is a classic one-to-one setup.
- Composite primary key with foreign keys inside it: one or more columns in the table’s full row ID point to parent tables. This is common in join tables such as
student_courseororder_item.
In the first pattern, each child row belongs to one parent row and cannot exist without it. In the second, the whole row ID is built from parent IDs, often to block duplicate pairings. Both are normal relational design.
What Each Constraint Is Doing
Primary key job
A primary key gives each row one stable identity inside its own table. That identity cannot be null, and it cannot repeat.
Foreign key job
A foreign key ties one table to another. It stops orphan rows by making sure the referenced parent value already exists.
Where the overlap happens
Nothing in relational design says one column may wear only one badge. If a child table’s ID should always match the parent table’s ID, one column can satisfy both rules at once. The same logic applies to composite IDs. A row in enrollment may use student_id and course_id as its full ID, with both columns pointing outward.
Vendor docs line up on this. Microsoft Learn’s primary and foreign key constraints page lays out the two rules, and PostgreSQL’s constraints section notes that a foreign key may point to a primary key or another duplicate-free column set.
When A Primary Key Also Acts As A Foreign Key
This pattern shines in a child table that adds detail to a parent row. Say you keep core account data in users, then place optional profile data in user_profiles. The child row should never exist before the user exists, and there should never be two profile rows for one user.
CREATE TABLE users (
user_id INT PRIMARY KEY
);
CREATE TABLE user_profiles (
user_id INT PRIMARY KEY
REFERENCES users(user_id),
bio TEXT,
avatar_url TEXT
);
Here, user_profiles.user_id does both jobs. It identifies the row in user_profiles, and it points back to users.user_id. If you use an ORM, Microsoft’s EF Core one-to-one relationship docs show this PK-to-PK shape directly.
This setup blocks duplicate child rows, keeps the link simple, and tells every reader of the schema that the child row is fully dependent on the parent row.
| Pattern | How The Key Works | When It Fits |
|---|---|---|
| User And Profile | Child ID equals parent ID and points to the parent | Extra user details live apart from the main row |
| Employee And Badge | Badge row reuses employee ID | The badge row should never outlive the employee row |
| Product And Detail Sheet | Detail row uses product ID as both PK and FK | Large or optional fields are split from the base table |
| Order Item | order_id is an FK and part of a composite PK |
Each row belongs to one order and needs its own line ID |
| Student Course | student_id and course_id are both FKs and together form the PK |
You need one row per student-course pair |
| Post And SEO Row | SEO row reuses post ID | Side data is optional but capped at one row |
| Subtype Table | Child type row shares parent ID | One base entity branches into narrow child tables |
Common Schema Patterns
Table split for optional columns
Some tables grow fat over time. A shared key lets you peel off bulky or sparse columns into a second table without losing a strict one-to-one link.
Subtype tables
A base table may hold all rows in a broad category, then child tables hold type-specific fields. A person row may have one matching employee row or one matching contractor row.
Bridge tables
Join tables are the other big place where this idea shows up. The table’s primary key may be made from two foreign keys together. That does not mean one single column is both PK and FK by itself. It means the row’s full identity includes columns that point to parent tables. That is still a clear “yes” to the wider question.
Use a simple gut check. If the child row can never have two rows for one parent and should not exist alone, shared PK is a strong bet. If the row needs its own identity apart from the parent, add a separate primary key and keep the foreign key separate.
| Common Mistake | Why It Hurts | Better Move |
|---|---|---|
| Using shared PK for a one-to-many link | You cap the child table at one row per parent | Use a separate child PK plus a plain FK |
| Forcing a child row before it is needed | Insert order gets awkward and null workarounds creep in | Use a nullable FK or split the timing |
| Skipping an index on busy FK columns | Joins and deletes can slow down badly | Add an index where query load calls for it |
| Using shared PK when the child may move | Changing the parent link means changing the row ID | Give the child its own PK |
| Hiding the rule from the team | Later edits break the data model | Name constraints clearly and note the intent in schema docs |
Rules That Keep The Design Clean
If you choose a primary-key-and-foreign-key combo, keep the schema tight. Clean DDL saves headaches later.
- Pick a clear parent table. The child should depend on it, not the other way around.
- Use shared PK for one-to-one, not one-to-many.
- Set delete and update actions on purpose. Blind cascades can bite.
- Name constraints so the link is easy to read in logs and migrations.
- Index foreign-key columns in hot join paths when your engine does not do that for you.
- Keep insert order in mind. Parent row first, child row next is the usual path.
If you are building a bridge table, make the composite primary key match the duplicate rule you want. If one student should appear only once per course, (student_id, course_id) is a clean row ID. If the row needs repeat attempts, terms, or versions, fold that extra column into the key or move to a surrogate ID.
When This Setup Is A Bad Bet
Do not reach for a shared key just because it feels neat. Skip it when the child table may need multiple rows per parent, when the child can switch parents, or when the child row arrives long before the parent row is known. In those cases, a separate child ID keeps life simpler.
Also watch for over-splitting. If two tables are joined on every read and never managed apart, the split may add more friction than value.
The Practical Rule
Yes, a primary key can be a foreign key. Use that pattern when the child row is bound tightly to one parent row and should share the same identity. Use composite keys with foreign-key columns in bridge tables when the row itself is defined by a pair or set of parent IDs. If the child needs room to grow on its own, give it its own primary key and keep the foreign key as just a link.
References & Sources
- Microsoft Learn.“Primary and foreign key constraints.”Sets out how primary keys identify rows and how foreign keys enforce parent-child links.
- PostgreSQL Global Development Group.“Constraints.”States that a foreign key may reference a primary key or another duplicate-free referenced column set.
- Microsoft Learn.“One-to-one relationships.”Shows the PK-to-PK pattern where the dependent row uses its primary key as the foreign key.
