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
 General SQL Server Forums
 New to SQL Server Programming
 Many to Many Relationships

Author  Topic 

shapper
Constraint Violating Yak Guru

450 Posts

Posted - 2007-10-17 : 06:31:31
Hello,

I have 3 tables. Posts, PostsTags and Tags.
This is a many to many relationship.

So PostsTags has the following columns:
PostId (PK) and TagId (PK)

I always did that way in SQL 2005.

In some examples I see PostsTags have 3 columns:
PostTagId(PK), PostId (FK), TagId (FK)

Should I use it this way, instead?

Thanks,
Miguel

Kristen
Test

22859 Posts

Posted - 2007-10-17 : 06:51:36
having a PostTagId can be helpful in identifying a specific record (single part key instead of multipart), I suppose, but I doubt its a good candidate for a PK!

Kristen
Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2007-10-17 : 06:54:59
Depends if you have a need for PostTagId.
It doesn't serve any purpose apart from giving a single column to index.
It's usually because people have a design rule that every table should have an identity column.
Usually that table would have two unique indexes PostId,TagId and TagId,PostId so you wouldn't get any performance or space gain from PostTagId - if the table had other columns you might though.

==========================================
Cursors are useful if you don't know sql.
DTS can be used in a similar way.
Beer is not cold and it isn't fizzy.
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2007-10-17 : 07:08:54
I have come across the occasional tool that wants a single key, unique, column to manage scrolling grids and the like.

Full Text Search needs that, but I don't suppose you are going to be asking it to look after your LINK table
Go to Top of Page

shapper
Constraint Violating Yak Guru

450 Posts

Posted - 2007-10-17 : 07:47:35
Hi,

My problems here are the behaviors I am looking for, and LINQ integration in Many to Many relationships.

Consider the following tables:

Posts (PostId PK)
Files (FileId PK)

PostsTags (PostId PK, TagId PK)
FilesTags (FileId PK, TagId PK)

Tags (TagId PK, TagName)

The behavior I am looking, which seems logic to me, is:
(This is the example for Posts. For files is the same)

- When a tag is added to a Post, a record is added to TagsInPosts.
If the Tag (given its TagName) does not exist in Tags then it is
created in Tags table.

- When a tag is removed from a post then it is deleted from PostsTags.
If that tag, i.e., is no longer associated with other Post or File
through PostsTags and FilesTags then it is deleted from Tags.

I have Stored Procedures that do this.
But can I simulate this with constrains and maybe triggers.

To be honest I am just starting with LINQ so I am not sure where do I need to ensure this behavior: in my LINQ classes or in my SQL tables.

Thanks,
Miguel




Go to Top of Page

shapper
Constraint Violating Yak Guru

450 Posts

Posted - 2007-10-17 : 07:49:41
By the way, in terms of a GridView I don't think that the Link table needs to have its own PK. Or maybe I am not getting the full picture.

Thanks,
Miguel
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2007-10-17 : 07:55:22
"Or maybe I am not getting the full picture"

No you are probably right, its just I've come across some Grid type things that can't be bothered to handle a multi-part key!

In fairness it is a bit of a pain:

To get the next record:

SELECT TOP 1 ...
FROM ...
WHERE Key1 > @Key1 OR ((Key1 = @Key1 AND Key2 > @Key2) OR (Key3 ...
ORDER BY Key1, Key2, Key3, ...

"But can I simulate this with constrains and maybe triggers"

Constrains maybe. Cascading deleted may be OK for this, but once you get too many "circular" relationships you won't be allowed to create them.

Triggers definitely:

"Delete from MyTable, if child records exist delete them too, if I'm the last child-of-my-parent delete my parent too .... "

that type of thing is very do-able in a trigger

Kristen
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2007-10-17 : 09:02:55
quote:
Originally posted by shapper

Hi,

My problems here are the behaviors I am looking for, and LINQ integration in Many to Many relationships.

Consider the following tables:

Posts (PostId PK)
Files (FileId PK)

PostsTags (PostId PK, TagId PK)
FilesTags (FileId PK, TagId PK)

Tags (TagId PK, TagName)

The behavior I am looking, which seems logic to me, is:
(This is the example for Posts. For files is the same)

- When a tag is added to a Post, a record is added to TagsInPosts.
If the Tag (given its TagName) does not exist in Tags then it is
created in Tags table.

- When a tag is removed from a post then it is deleted from PostsTags.
If that tag, i.e., is no longer associated with other Post or File
through PostsTags and FilesTags then it is deleted from Tags.

I have Stored Procedures that do this.
But can I simulate this with constrains and maybe triggers.

To be honest I am just starting with LINQ so I am not sure where do I need to ensure this behavior: in my LINQ classes or in my SQL tables.

Thanks,
Miguel





Yes, you would use a trigger for this. I am not sure why you want to do this; what if you want to eventually apply that tag to a different post? You'd have to keep deleting and then re-creating tags. Wouldn't it be better to have a "tag maintenance" page where you can see all tags and optionally delete any not associated with any posts?

But, anyway, that has nothing to do with the need for an extra identity PK on your many-to-many table. I fail to see any advantage of having that key there. If you do have an identity as your PK on that table, you MUST add a unique constraint on the "true" key of PostID/TagID otherwise you will have no data integrity.

I write about it here:
http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx


- Jeff
http://weblogs.sqlteam.com/JeffS
Go to Top of Page

shapper
Constraint Violating Yak Guru

450 Posts

Posted - 2007-10-17 : 16:00:29
Hi Jeff,

I just read your article. Just one question:
can I use composite Primary Keys when using GUID instead of an int?

quote:

Yes, you would use a trigger for this. I am not sure why you want to do this; what if you want to eventually apply that tag to a different post? You'd have to keep deleting and then re-creating tags. Wouldn't it be better to have a "tag maintenance" page where you can see all tags and optionally delete any not associated with any posts?



But:
If at any moment I want to display all associated tags?
Or if when creating a new post some of the tags already exist?

My idea was to create a synchronization.
I have an SQL procedure that does this:


-- Create post
INSERT INTO dbo.Posts(BlogId, AuthorId, PostTitle, PostBody)
OUTPUT Inserted.PostId INTO @Posts(PostId)
SELECT @BlogId, @AuthorId, @PostTitle, @PostBody

-- Create post tags
INSERT INTO dbo.Tags(TagText)
SELECT data
FROM dbo.SplitText(@PostTags, ',') AS st
WHERE NOT EXISTS(
SELECT TagText
FROM dbo.Tags
WHERE TagText = st.data)

-- Add tags ids to @Tags
INSERT INTO @Tags(TagId)
SELECT TagId
FROM dbo.Tags AS t
JOIN dbo.SplitText(@PostTags, ',') AS st
ON t.TagText = st.data

-- Associate tag to post
INSERT INTO dbo.TagsInPosts(PostId, TagId)
SELECT p.PostId, t.TagId
FROM @Posts AS p
CROSS JOIN @Tags AS t


I started to think of triggers because of Linq.

I am rethinking my database to improve efficiency and also because of LINQ which I am starting to use.

So any feedback is welcome.

Thanks,
Miguel
Go to Top of Page
   

- Advertisement -