Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Multiple Categories

Author  Topic 

X-Factor
Constraint Violating Yak Guru

392 Posts

Posted - 2003-12-14 : 16:35:32
Hi there,

I have a table of products and each product has a field which references a category ID.

I want to give my products the option to belong to multiple categories so I figure I can add a table of secondary categories and have each record reference a product and a category.

In addition, I would like to fix it so that a category ID cannot be specified twice for a product. Its simple enough to add a unique constraint to the secondary categories table but how do I stop the primary category being referenced inline in the actual product record from appearing in the secondary category table for that same product?

I figure I could move the primary category out of the main product record and into the SC table but then how do I enforce the requirement that every product is of at least one category?

Any thoughts,

XF.

SamC
White Water Yakist

3467 Posts

Posted - 2003-12-14 : 17:42:15
I'd get rid of the category id in the table of products and rely on a secondary table

CREATE TABLE dbo.ProductCategory (
ProductID INT NOT NULL ,
CategoryID INT NOT NULL
)
CREATE UNIQUE CLUSTERED INDEX IDX_ProductCategory ON dbo.ProductCategory (ProductID, CategoryID)
Go to Top of Page

X-Factor
Constraint Violating Yak Guru

392 Posts

Posted - 2003-12-14 : 19:05:39
Thanks for your reply.

That's cool, but how do I force a product to have at least one reference in the new table? To get the database to do this I think would require a trigger.

Also, how do I mark a record in the new table as a primary category?

I think maybe a bit field would suffice and then maybe another unique constraint on the prodID and the bit field?

Any thoughts?
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2003-12-14 : 19:27:54
One way is to add a column called "PrimaryCategory" to your products table, and make it required.

Then use a table similiar to what Sam posted but call it "AdditionalCategories" or something like that. In that table, you save lists of the the non-primary categories for each product.

To get ALL of a product's categories, then, use a union:

SELECT Product, PrimaryCategory as Category
FROM Products
UNION ALL
SELECT Product, Category
FROM AdditionalCategories

something like that, anyway ... though you might like to make sure that a product's primary category isn't also listed in the additional categories table...

- Jeff
Go to Top of Page

SamC
White Water Yakist

3467 Posts

Posted - 2003-12-14 : 20:13:38
quote:
Originally posted by X-Factor


That's cool, but how do I force a product to have at least one reference in the new table? To get the database to do this I think would require a trigger.


Depends, on how the code is written to do the insert. Write code to refuse the insert if there's no primary catagory ?

IF @Catagory IS NOT NULL BEGIN
INSERT INTO dbo.MyTable ( , , , ) ... etc
END ELSE BEGIN
-- Error handling here
END


Are you writing stored procedures to do the INSERTs and SELECTs ?




Go to Top of Page

X-Factor
Constraint Violating Yak Guru

392 Posts

Posted - 2003-12-15 : 08:46:10
Yes I am writing stored procedures.
quote:

you might like to make sure that a product's primary category isn't also listed in the additional categories table


What I would like to know is whether there is a way of doing this with some standard database mechanism.

For example, if you want unique values in a field, you add a unique constraint to the field. You might also do checks on data before even sending it to the database, but once its there, the database is ultimately going to rely on its self to maintain the integrity of the data it holds.

Similarly, I could quite easily write some code to make sure that the product's primary category is not also in the additional categories table, but I would like to know whether there is a standard or intrinsic way of enforcing this using internal databse features.

Hope this makes sense!

Go to Top of Page

SamC
White Water Yakist

3467 Posts

Posted - 2003-12-15 : 09:26:27
I get your drift, but I think the answer in this case may be no, unless a trigger is used as a final resort to confirm the CategoryID exists for each product in the ProductCategoryID table.

One possability is that the Product table doesn't hold a value of the Primary CategoryID but instead keeps a pointer to the row in the ProductCategory table which describes the Primary Category. All Categorys in one table, primary is described and constrained.

The design goal of having a primary key kept in one table and the secondary keys in another could be a subject of some db design criticism, but it could be the proper design, depending on how the data will be retrieved and manipulated later on.

I like Jeff's idea of using a primary category flag in the category table because I can see future query writing simplified by this flag.

For example: select a recordset of all catagories for a product, including the primary catagory (perhaps as the first row)....

SELECT ProductName, CategoryID
FROM Products P
INNER JOIN ProductCategory PC ON PC.ProductID = P.ProductID
ORDER BY ProductName, PC.Primary, CategoryID

This is about as simple as it can get to return a recordset ordered by product, with the primary category listed first, and the secondary category in alphabetic order.

If the Primary Category is kept in the Product table, the equivalent SELECT statement isn't as clear and would look something like this:

SELECT ProductName, CategoryID
FROM (
SELECT Productname, CategoryID, 1 as CatOrder -- The 1 is for positioning in the final recordset
FROM Products P
UNION ALL
Select Productname, PC.CategoryID, 2
FROM Products P
INNER JOIN ProductCategory PC ON PC.ProductID = P.ProductID
)

ORDER BY ProductCategory, CatOrder, CategoryID

So there could be a big difference in the difficulty of building recordsets depending on the chosen table structure.
Go to Top of Page
   

- Advertisement -