confusion over relationships - c#

Hey guys I have a confusing question, I have a user table and it stores all the usual data for a user that you would expect but im trying to figure out how a user could add another user?
Sounds strange but each user in the User table has his own UI which is UserID how could I add another table where UserID can have a relationship with another UserID?
I will give the answer to those that could take the time to upload a table diagram and who can help with some examples for sqlsyntax related to this question, i.e how would I right the syntax for the above question if I wanted to display all the UserIDs friends on a page. How would I add a friend.

You just need another table similar to the Pictures and wallposting table. You just need to be able to record many friend id's for one user id (one to many)
eg:
The query to then get friends would be:
DECLARE #UserID AS BIGINT
SET #UserID = 123
SELECT [friends].*
FROM [friends]
where [parentuserid]=#UserID#
to Insert a Friend:
DECLARE #UserID AS BIGINT
DECLARE #FriendID AS BIGINT
SET #UserID = 123
SET #FriendID = 321
INSERT INTO [Friends]
(
[ParentUserID],
[ChildUserID]
)
VALUES
(
#UserID,
#FriendID
)
Code to insert it example:
private void Test()
{
string Query =
#"INSERT INTO [Friends]
(
[ParentUserID],
[ChildUserID]
)
VALUES
(
#UserID,
#FriendID
)";
using ( SqlConnection oSqlConnection = new SqlConnection( "connect string" ) )
{
oSqlConnection.Open();
using (SqlCommand oSqlCommand = new SqlCommand(Query,oSqlConnection))
{
oSqlCommand.Parameters.AddWithValue("#UserID", Session["UserID"]);
oSqlCommand.Parameters.AddWithValue("#FriendID", Session["FriendID"]);
oSqlCommand.ExecuteNonQuery();
}
}
}
Where would you get your friend ID from? what is the process for adding friends? do you search for them and select them from a list?

You just need a many to many relationship.
Create Table Friend(
UserId int,
FriendId int,
Constraint pk_friends Primary Key (UserId, FriendId),
Constraint fk_friend_user Foreign Key (UserId) References User(UserId),
Constraint fk_friend_friend Foreign Key (FriendId) References User(UserId)
)

Your asking a bit much with the diagrams etc.... for me at least.
It depends on the kind of relationship, one to one, it will be another Column in your user table. If it is many to many you'll need a junction table, with two columns UserIDA, UserIDB. Depending why you need the relationship.

I think you have a simple requirement of a User Referring Other user to join. If that is the case then you can simply have one more column ReferenceUserID in User Table and whenever a new user refers another user then simply add him with a UserID of referring user. If he isn't a referred user then by default it will be NULL.
Later for retrieval you can use a Self Join.
Update:
For Friend (many to many relationship) you should look at following Question at StackOverflow
Database design: Best table structure for capturing the User/Friend relationship?
UserRelationship
====
RelatingUserID
RelatedUserID
Type[friend, block, etc]
A similar approach is used by Facebook where they have a kind of Cross join Table for relation between Friends.

Related

Connecting Three SQL Server Tables Together to Display Images

I am trying to create a Photo Album/Collection for each student in my ASP.NET website, using SQL Server tables.
Here are my table structure:
I want to store the image name within the Student_Images folder. Then each image will be linked to a Photo Collection. Each Photo Collection is linked to a group.
Then I want to display each group, any photo collections which are associated with that group, and then any images associated with that collection.
I have been able to display images related to each student, but I don't know how to add the 'Photo Collection' table between the Students and Images tables.
Here is how I would like it to display:
Here is how the tables would look populated:
Can anyone advise me as to how to go about making this connection?
There's an idea of a foreign key - where a row in a table refers to a row in another table. You definitely want to do this for a number of reasons, to ensure data integrity and to document your relationships for whoever works on the site.
You don't quite have enough information to get where you want to get. You don't have any linkage between photo albums and the images they contain. You'll need another table for that.
I kinda recommend that you use column names that don't repeat the table name. You'll find you can then see patterns more clearly in your schema. For example Photo_Collection.Photo_Collection_Id should probably be just Photo_Collection.Id. It's more concise, and it's obvious which Id you're talking about because you always use the table name when referring to that column.
So, to get you nearer to where you need to be, I'd recommend something like this:
create table dbo.Students
(
ID
int not null identity( 1, 1 )
constraint [Students.ID.PrimaryKey]
primary key clustered,
Name
nvarchar( 50 ) --> not very generous :-)
)
go
create index [Students.Name.Index] on dbo.Students( Name ) --> maybe unique?
go
create table dbo.Student_Images
(
ID
int not null identity( 1, 1 )
constraint [Student_Images.ID.PrimaryKey]
primary key clustered,
Student_ID
int not null
constraint [Student_Images.to.Student]
foreign key references dbo.Students( ID )
Filename
nvarchar( 250 ) null, --> null? really? each image should have a unique file name, dont you think?
Description
nvarchar( 250 ) null
)
go
create index [Student_Images.to.Students.Index] on dbo.Student_Images( Student_ID )
go
create table dbo.Photo_Collection
(
ID
int not null identity( 1, 1 )
constraint [Photo_Collection.ID.PrimaryKey]
primary key clustered,
Name
nvarchar( 250 ) null --> null? hmmm...could be hard to use
)
go
create index [Photo_Collection.Name.Index] on dbo.Photo_Collection( Name ) --> consider unique??
go
create table dbo.Photo_Collection_Images
(
Photo_Collection_ID
int not null
constraint [Photo_Collection_Images.to.Photo_Collection]
foreign key references dbo.Photo_Collection( ID ),
Student_Image_ID
int not null
constraint [Photo_Collection_Images.to.Student_Images]
foreign key references dbo.Student_Images( ID )
)
You didn't really describe your groups...and there are lots of questions still unanswered. For example, are Photo_Collections something that a student makes? If so, there should probably be a Student_ID in Photo_Collection with a foreign key to Students.
The table I added called Photo_Collection_Images relates your photo collections to the images. You'd include this table in any query that needs to display all the images in a given photo collection. I think that's the main missing bit for you. You'd do something similar for groups.
Also - FYI, pasting images of your text is kinda aggravating. Consider just pasting the text in and indenting it 4 spaces to get it to format correctly.
Edit:
To select, for example, all the images in a photo collection by student, you could do:
select
pc.Name PhotoCollectionName,
si.FileName FileName,
si.Description FileDescription,
s.Name StudentName
from
dbo.Photo_Collection pc
inner join
dbo.Photo_Collection_Images pci
on
pc.Id = pci.Photo_Collection_ID
inner join
dbo.Student_Image si
on
pci.Student_Image_ID = si.ID
inner join
dbo.Students s
on
si.Student_Id = s.ID
This is pretty much the base query for everything.
Make some changes in your Photo_Collection table, create an FK within your Photo_Collection of Student_ID, then you'll be able to show the photo collection of all the students because through Student_ID, you can have access to student table as well as Student_Images.
Hope it helps.

How would I create "multiple choice" columns in Local Database?

I am using local database for first time with my WPF project. I have the database setup, and I am connecting fine ETC. Ther eare some columns which I want to be multiple choice, either between a few values or a whole bunch of values. Problem is obviously human error will make typos now and then when inputting the data.
How would I go about making the data entry give the user a multiple choice? So for example, I have a column called "Category", and at the moment (this will be expanded later) I only want to allow the following options:
Bronze
Misc
I have the columns set to nvarchar(50) at present, but typing the same string manually constantly... not what I would like to be doing TBH... so... Could I set it so that there are a list of predefined values it will accept? :)
thanks :D
You can use CHECK constraint of any complexity on your table column(s). Check MSDN here
So your table definition would be as:
CREATE TABLE T
(
Category nvarchar(50) CHECK (Category in ('Bronze','Misc'))
)
If you expect your list of possible values to change in the future and you do not want to change a table definition, you can create a separate table with the list of values and use the foreign key.
CREATE TABLE Categories
(
Id int PRIMARY KEY,
CategoryName nvarchar(50)
)
INSERT INTO Categories VALUES (1, 'Bronze'), (2, 'Silver'), (3, 'Misc')
CREATE TABLE T
(
CategoryId int REFERENCES Categories
)

Relational SQL Server Databases

I just registered here and this is my very first question. I hope I can explain myself clearly 'cause being a self-taught developer I don't quite speak the jargon.
My question: my project database holds employee information and has things like firstName, lastName, jobTitle, etc.. (static things).
My problem begins when I want to also start collecting all the clockIn & clockOut events of each employee. I can't think of an elegant way of adding these to my current database.
I don't know too much about databases but I think such things should either go in a totally different database or perhaps in a different table within the same database.
No idea which is the right answer.
The other thing is that these 2 databases or 2 tables need to somehow relate to each other somehow. When I select an employee from the list [data coming from the 1st DB or Tbl] and choose to view that specific employee's clock event history [data coming from the 2nd DB or Tbl] I should see that employee's clock in's & out's and NOT some other employee's clock events history.
A step-by-step tutorial is not necessary, but appreciated. Can you give me a quick explanation/outline of how this can be done ? If needed, I can add more details about
the project.
Thanks.
Like so:
CREATE TABLE Employees (
EmployeeId bigint IDENTITY(1,1) PRIMARY KEY,
FirstName nvarchar(50),
LastName nvarchar(50),
etc
)
CREATE TABLE EmployeeClocks ( -- rename as appropriate
EmployeeId bigint, -- foreign key
DateTime datetimeoffset(7),
ClockInType tinyint, -- values defined by an enum inside your program code
CONSTRAINT FK_EmployeeClocks_Employees FOREIGN KEY (EmployeeId) REFERENCES Employees (EmployeeId) ON DELETE CASCADE ON UPDATE CASCADE
)
Now for some queries:
Getting all of the clock-ins for an employee (assuming ClockInType = 1 for clock-ins, and 2 for clock-outs):
SELECT
DateTime
FROM
EmployeeClocks
INNER JOIN Employees ON EmployeeClocks.EmployeeId = Employees.EmployeeId
WHERE
Employees.FirstName = "Dick" AND
Employees.LastName = "Butt"
Read about database schema
You have to use two tables in a single database, Dai's answer showed the tables. just adding a few word if you re new to database then first read about it make a design idea than make database. because it very difficult to change in database when project is done.
Read some articles from here
database architecture
sql server database

Sql Group by for rows with all columns the same except one

I have a table with a number of columns that will be used to save searches stored by a user.
Every day an email needs to be sent out containing the latest search results.
There could be thousands of saved searches.
My columns in my saved search table are similar to as follows:
Id
userEmail
SearchParam1
SearchParam2
SearchParam3
As there will be so many searches I anticipate there will be many that are the same so I would like to get every row where param1,2 and 3 are the same but still have access to the users email so I can send the same results to each without having to run the same search multiple times.
Ideally I'd like something like this back:
SearchParam1, SearchParam2, SearchParam3
|
|____Email1
|
|____Email2
|
|____Email3
Kind of grouped by the search params but linked to the emails some how.
I don't even know where to start, hence why I have not added any code.
Can anyone give me some suggestions?
EDIT
Just to clarify. One email would not exist more than once in the table. So technically they are only allowed to save 1 search each.
There are no users as such, just email addresses.
Bex
What you really should consider is data normalization. This looks like a many-to-many relationship, so a structure like this would be idea:
create table yourUsersTable
(
id int identity(1, 1) primary key clustered not null,
name varchar(1000) not null,
email varchar(1000) not null
)
go
create table searchParams
(
id int identity(1, 1) primary key clustered not null,
searchText varchar(1000) not null
)
go
create table userSearchParams
(
fkYourUsersTable int not null references yourUsersTable(id),
fkSearchParams int not null references searchParams(id)
)
go
This way, if you wanted to get all the email addresses for users subscribed to a search parameters, it'd be a simple query:
select u.email
from yourUsersTable u
inner join userSearchParams up
on u.id = up.fkYourUsersTable
inner join searchParams p
on p.id = up.fkSearchParams
where p.searchText = 'your search parameter here'
This is a basic example of implementing data normalization with a many-to-many relationship. It utilizes a join table to create the relationship between users and search parameters. Data retrieval has become much simpler with the above design, and you aren't constricted by your original denormalized data (with columns like searchParam1, searchParam2, etc.).
Please let me know if that made sense.
In SQL, a starting point would be:
select SearchParam1, SearchParam2, SearchParam3, userEmail, count(*) query_count
from MyTable
group by SearchParam1, SearchParam2, SearchParam3, userEmail
order by 1,2,3,4
(If you don't want to see how many times the same user ran the same query, you can omit the group by clause and the count(*) item, and just include select distinct instead.)
This will repeat the search parameters next to each user's e-mail.
If you want to only include the search parameters as a heading each time one of them changes, I suggest using the above query in a reporting tool (such as SQLServer reporting services) - group on the search parameters, include the parameter fields in the group header only and include the user eMail in the detail line only.
EDIT: if userEmail uniquely identifies a record, the query can be simplified to:
select SearchParam1, SearchParam2, SearchParam3, userEmail
from MyTable
order by 1,2,3,4

How can I Insert/Update into two related tables in one command?

A database exists with two tables
Data_t : DataID Primary Key that is
Identity 1,1. Also has another field
'LEFT' TINYINT
Data_Link_t : DataID PK and FK where
DataID MUST exist in Data_t. Also has another field 'RIGHT' SMALLINT
Coming from a microsoft access environment into C# and sql server I'm looking for a good method of importing a record into this relationship.
The record contains information that belongs on both sides of this join (Possibly inserting/updating upwards 5000 records at once). Bonus to process the entire batch in some kind of LINQ list type command but even if this is done record by record the key goal is that BOTH sides of this record should be processed in the same step.
There are countless approaches and I'm looking at too many to determine which way I should go so I thought faster to ask the general public. Is LINQ an option for inserting/updating a big list like this with LINQ to SQL? Should I go record by record? What approach should I use to add a record to normalized tables that when joined create the full record?
Sounds like a case where I'd write a small stored proc and call that from C# - e.g. as a function on my Linq-to-SQL data context object.
Something like:
CREATE PROCEDURE dbo.InsertData(#Left TINYINT, #Right SMALLINT)
AS BEGIN
DECLARE #DataID INT
INSERT INTO dbo.Data_t(Left) VALUES(#Left)
SELECT #DataID = SCOPE_IDENTITY();
INSERT INTO dbo.Data_Link_T(DataID, Right) VALUES(#DataID, #Right)
END
If you import that into your data context, you could call this something like:
using(YourDataContext ctx = new YourDataContext)
{
foreach(YourObjectType obj in YourListOfObjects)
{
ctx.InsertData(obj.Left, obj.Right)
}
}
and let the stored proc handle all the rest (all the details, like determining and using the IDENTITY from the first table in the second one) for you.
I have never tried it myself, but you might be able to do exactly what you are asking for by creating an updateable view and then inserting records into the view.
UPDATE
I just tried it, and it doesn't look like it will work.
Msg 4405, Level 16, State 1, Line 1
View or function 'Data_t_and_Data_Link_t' is not updatable because the modification affects multiple base tables.
I guess this is just one more thing for all the Relational Database Theory purists to hate about SQL Server.
ANOTHER UPDATE
Further research has found a way to do it. It can be done with a view and an "instead of" trigger.
create table Data_t
(
DataID int not null identity primary key,
[LEFT] tinyint,
)
GO
create table Data_Link_t
(
DataID int not null primary key foreign key references Data_T (DataID),
[RIGHT] smallint,
)
GO
create view Data_t_and_Data_Link_t
as
select
d.DataID,
d.[LEFT],
dl.[RIGHT]
from
Data_t d
inner join Data_Link_t dl on dl.DataID = d.DataID
GO
create trigger trgInsData_t_and_Data_Link_t on Data_t_and_Data_Link_T
instead of insert
as
insert into Data_t ([LEFT]) select [LEFT] from inserted
insert into Data_Link_t (DataID, [RIGHT]) select ##IDENTITY, [RIGHT] from inserted
go
insert into Data_t_and_Data_Link_t ([LEFT],[RIGHT]) values (1, 2)

Categories