MS SQL Bridge Table Constraints - sql-server-2005

Greetings -
I have a table of Articles and a table of Categories.
An Article can be used in many Categories, so I have created a table of ArticleCategories like this:
BridgeID int (PK)
ArticleID int
CategoryID int
Now, I want to create constraints/relationships such that the ArticleID-CategoryID combinations are unique AND that the IDs must exist in the respective primary key tables (Articles and Categories).
I have tried using both VS2008 Server Explorer and Enterprise Manager (SQL-2005) to create the FK relationships, but the results always prevent Duplicate ArticleIDs in the bridge table, even though the CategoryID is different.
I am pretty sure I am doing something obviously wrong, but I appear to have a mental block at this point.
Can anyone tell me please how should this be done?
Greaty appreciated!

Don't use a BridgeId column.
Make a composite primary key (aka compound key) from your ArticleId and CateogryId, that will ensure each combination is unique.
Make each column a foreign key to the corresponding table, and that completes your set of constraints.

Ok first you do a unique index on ArticleID, CategoryID.
Then you set up a foreign key constraint on articleID linking it back to the Article table. and then do the same for CategoryID and Catgory table.
Your description sounds like you are creating the PK on the Bridge table and the FK on the other table which is why it wouldn't work.

Expanding on HLGEM's solution you would have something like:
Create Table ArticleCategories
(
Id int not null Primary Key Clustered
, ArticleId int not null
, CategoryId int not null
, Constraint UK_ArticleCategories_Unique ( ArticleId, CategoryId )
, Constraint FK_ArticleCategories_Articles
Foreign Key ( ArticleId )
References Articles( Id )
, Constraint FK_ArticleCategories_Categories
Foreign Key ( CategoryId )
References Categories( Id )
)

Related

How to set two primary key in SQL Server?

I'm making my first project in SQL. A database for an hardware store. I need to make more than one relation to other table from a single table (need more than one primary key).
When I try to create two PRIMARY KEY it has no error, but when I try to make the connections to other tables, those other tables don't recognize those keys.
CREATE TABLE Product
(
IDProduct int NOT NULL,
Part nchar(16) CHECK (Part IN ('CPU', 'CPUCooler', 'Motherboard', 'Storage', 'Memory', 'GraphicCard', 'Case', 'PSU')),
Quantity tinyint,
Disponibility bit NOT NULL ,
Price smallmoney NOT NULl,
OrderID int FOREIGN KEY REFERENCES Encomenda(IDEncomenda),
PRIMARY KEY (IDProduct, Part)
)
I try to do more tables but it didn't work. I search everywhere and didn't find the solution. I saw my teacher doing it but he don't reply to our class for some time now.
I'm expecting to have two PRIMARY KEY inside a table or be able to create a relation with other table.

ORA-00904, Code Newbie I need help in identifying what's wrong

CREATE TABLE TASK_SKILL (TASK_ID INT REFERENCES PROJECT_SCHEDULE_TASK(TASK_ID),
SKILL_ID INT REFERENCES PROJECT(PROJECT_ID),
NUMBER_OF_EMPLOYEES INT,
PRIMARY KEY (TASK_ID, PROJECT_ID, SKILL_ID));
Good day, I know my questions seem to be quite newbie-ish and is common sense for most of you here, but I am still trying to learn SQL
I encountered "ORA-00904: "PROJECT_ID": invalid identifier".
I have already checked and it looks like I have a Project_ID column but still, I can't seem to run it.
You are creating a table TASK_SKILL with 3 fiels: TASK_ID, SKILL_ID and NUMBER_OF_EMPLOYEES. Also you want to create a Primary Key by TASK_ID, PROJECT_ID, SKILL_ID. Oracle is right, you do not have a PROJECT_ID field in your table.
Your field is called SKILL_ID, so the Primary key should be created using it, like this:
CREATE TABLE TASK_SKILL (TASK_ID INT REFERENCES PROJECT_SCHEDULE_TASK(TASK_ID),
SKILL_ID INT REFERENCES PROJECT(PROJECT_ID),
NUMBER_OF_EMPLOYEES INT,
PRIMARY KEY (TASK_ID, SKILL_ID));
In the PK of a table you ony include fields from the table and not field from the related table. So, no need to include te referenced PROJECT_ID.
This happens because you are trying to create a table with a column that doesn't exist, in this case, PROJECT_ID. In the TASK_SKILL Table you only have 3 Columns defined:
TASK_ID, which is a foreign key of the PROJECT_SCHEDULE_TASK table
SKILL_ID, which is a foreign key of the PROJECT table.
NUMBER_OF_EMPLOYEES which is an integer.
Try to create the table like this:
CREATE TABLE TASK_SKILL (TASK_ID INT REFERENCES PROJECT_SCHEDULE_TASK(TASK_ID),
SKILL_ID INT REFERENCES PROJECT(PROJECT_ID),
NUMBER_OF_EMPLOYEES INT,
PRIMARY KEY (TASK_ID, SKILL_ID));
Lastly, if you're just starting out learning SQL, you can first lay the foundations of database design before going hands-on.
oracle documentation of foreign keys

Database - Am i doing this right?

I'm trying to make a simple database for a personal project, and I'm not sure whether i'm using Primary Keys properly.
Basically, the database contains users who have votes yes/no on many different items.
Example :
User "JOHN" voted YES on item_1 and item_2, but voted FALSE on item_3.
User "BOB" voted YES on item_1 and item_6.
User "PAUL" votes NO on item_55 and item_76 and item_45.
I want to use the following 3 tables (PK means Primary Key) :
1) table_users, which contains the columns "PK_userID" and "name"
2) table_items, which contains the columns "PK_itemID" and "item_name"
3) table_votes, which contains the columns "PK_userID", "PK_itemID", and "vote"
and the columns with the same name will be linked
Does it look like a proper way to use primary keys ? (so the table_votes will have two Primary Keys, being linked to the two other tables)
Thanks :)
Since user can vote for multiple items and multiple users can vote for a single item, you should not create following two primary keys in third table table_votes. Just create them as fields otherwise it will restrict you add only a userId or itemId only once. Yep, you should make them NOT NULL
"PK_userID", "PK_itemID",
No, that's not correct.
There can only be one primary key per table. You can have other columns with unique indexes that could have been candidate keys, but that's not the primary.
I think you'd have three tables:
create table PERSON (
PERSON_ID int not null identity,
primary key(PERSON_ID)
);
create table ITEM (
ITEM_ID int not null identity,
primary key(ITEM_ID)
);
create table VOTE (
PERSON_ID int,
ITEM_ID int,
primary key(PERSON_ID, ITEM_ID),
foreign key(PERSON_ID) references PERSON(PERSON_ID),
foreign key(ITEM_ID) references ITEM(ITEM_ID)
);
It's a matter of cardinality. A person can vote on many items; an item can be voted on by many persons.
select p.PERSON_ID, i.ITEM_ID, COUNT(*) as vote_count
from PERSON as p
join VOTE as v
on p.PERSON_ID = v.PERSON_ID
join ITEM as i
on i.ITEM_ID = v.PERSON_ID
group by p.PERSON_ID, i.ITEM_ID
This looks reasonable. However, I would not advise you to name your primary keys with a "PK_" prefix. This can be confusing, especially because I advise giving foreign keys and primary keys the same name (the relationship is then obvious). Instead, just name it after the table with Id as a suffix. I would recommend a table structure such as this:
create table Users (
UserId int not null auto_increment primary key,
Name varchar(255) -- Note: you probably want this to be unique
);
create table Items (
ItemId int not null auto_increment primary key,
ItemName varchar(255) -- Note: you probably want this to be unique
);
create table Votes (
UserId int not null references Users(UserId),
ItemId int not null references Items(ItemId),
Votes int,
constraint pk_UserId_ItemId primary key (UserId, ItemId)
);
Actually, I would be inclined to have an auto-incremented primary key in Votes, with UserId, ItemId declared as unique. However, there are good arguments for doing this either way, so that is more a matter of preference.

How to add a unique constraint using a column from another table?

I have 3 tables in SQL Server 2008 R2 that look like these:
A COMPANY may have many LSPs. An LSP may have many SERVICEs.
And I need to make sure that SERVICE_CODE uniquely identifies a SERVICE record within a COMPANY. In other words, COMPANY_ID + SERVICE_CODE should uniquely identify a SERVICE record in the entire system.
For example: COMPANY-A may NOT have 2 services (with 2 different SERVICE_IDs) with the same SERVICE_CODE. But COMPANY-A and COMPANY-B may both have 2 separate SERVICES (again, with different SERVICE_IDs) with SERVICE_CODE = "PREMIUM".
I need something like this:
alter table "SERVICE"
add constraint "SERVICE_Index01"
unique ("COMPANY_ID", "SERVICE_CODE")
But (obviously) this fails because the COMPANY_ID column is not in the SERVICE table.
Thanks in advance for any help.
You could use an indexed view as an external constraint:
CREATE VIEW dbo.CompanyServices
WITH SCHEMABINDING
AS
SELECT
c.COMPANY_ID,
s.SERVICE_CODE
FROM dbo.COMPANY c
INNER JOIN dbo.LSP l ON c.COMPANY_ID = l.COMPANY_ID
INNER JOIN dbo.SERVICE s ON l.LSP_ID = s.LSP_ID
GO
CREATE UNIQUE CLUSTERED INDEX UQ_CompanyServices
ON dbo.CompanyServices (COMPANY_ID, SERVICE_CODE);
The index will make sure there's no duplicates of (COMPANY_ID, SERVICE_CODE) in your data.
Is each company limited to a single LSP? Is Service_Code unique (or could there be two service codes "PREMIUM" with different Service_IDs)?
CREATE TABLE dbo.Company
(
CompanyID INT PRIMARY KEY
-- , ...
);
CREATE TABLE dbo.LSP
(
LSPID INT PRIMARY KEY,
CompanyID INT FOREIGN KEY REFERENCES dbo.Company(CompanyID) -- UNIQUE?
-- , ...
);
CREATE TABLE dbo.Service
(
ServiceID INT PRIMARY KEY
-- , ...
);
CREATE TABLE dbo.LSP_Service
(
LSPID INT FOREIGN KEY REFERENCES dbo.LSP(LSPID),
ServiceID INT FOREIGN KEY REFERENCES dbo.Service(ServiceID),
PRIMARY KEY (LSPID, ServiceID)
);
Add COMPANY_ID to service table.
If you need rows in Service table to be unique by this id it makes sense to keep a foreign key reference in this table.

MySQL Lookup table and id/keys

Hoping someone can shed some light on this: Do lookup tables need their own ID?
For example, say I have:
Table users: user_id, username
Table categories: category_id, category_name
Table users_categories: user_id, category_id
Would each row in "users_categories" need an additional ID field? What would the primary key of said table be? Thanks.
You have a choice. The primary key can be either:
A new, otherwise meaningless INTEGER column.
A key made up of both user_id and category_id.
I prefer the first solution but I think you'll find a majority of programmers here prefer the second.
You could create a composite key that uses the both keys
Normally if there is no suitable key to be found in a table you want to create a either a composite key, made up of 2 or more fields,
ex:
Code below found here
CREATE TABLE topic_replies (
topic_id int unsigned not null,
id int unsigned not null auto_increment,
user_id int unsigned not null,
message text not null,
PRIMARY KEY(topic_id, id));
therefor in your case you could add code that does the following:
ALTER TABLE users_categories ADD PRIMARY KEY (user_id, category_id);
therefor once you want to reference a certain field all you would need is to pass the two PKs from your other table, however to link them they need to each be coded as a foreign key.
ALTER TABLE users_categories ADD CONSTRAINT fk_1 FOREIGN KEY (category_id) REFERENCES categories (category_id);
but if you want to create a new primary key in your users_categories table that is an option. Just know that its not always neccessary.
If your users_categories table has a unique primary key over (user_id, category_id), then - no, not necessarily.
Only if you
want to refer to single rows of that table from someplace else easily
have more than one equal user_id, category_id combination
you could benefit from a separate ID field.
Every table needs a primary key and unique ID in SQL no matter what. Just make it users_categories_id, you technically never have to use it but it has to be there.