Prevent Duplicate Records in SQL Server - c#

I have 3 tables in my Database, one for student and other for the courses and the third one to store what every student select from courses. I want to prevent the student from selecting the same course more than once. what condition should I provide in Insert statement in the third table?
Thanks

Your StudentCourse table should have a unique constraint on the (StudentId, CourseId) table.
As an alternative, you can create the Primary Key on your StudentCourse table as a composite key on (StudentId, CourseId).

While it follows that every table in your database must have a Primary key constraint, often its an auto generated value useful when carrying out most database maintenance tasks. However the primary key itself will not protect you from user generated or user captured data that may contain duplications. Enter the “Unique” constraint! This is a very powerful table-level constraint that you can apply to your table against a chosen table column, which can greatly assist to prevent duplicates in your data. For example, say you have a “Users” table and in it, you have an EmailAddress column, surely it would be strange to capture 1 or 2 users who have an identical email address.

Related

SqlBulkCopy for two tables with one-to-many association

I have used SqlBulkCopy in my previous program and have enjoyed the speed-of-light advantage of its INSERTS. But then, I was only inserting things in one table only.
I now have two tables with a one-to-many association i.e. table A has a foreign key in table B. So each record in B carries an id that is the result of an insert in A.
I am wondering if there is a solution for this?
Example:
I will give a better example on this and hope we find a good solution eventually.
We have a table called Contacts. And since each contact can have zero or more Email addresses we will store those emails in a separate table called ContactEmails. So Contacts.Id will become FK on ContactEmails (say ContactEmails.ContactId).
Let's say we would like to insert 1000 Contacts and each will have zero or more Emails. And we of course want to use SqlBulkCopy for both tables.
The problem is, it is only when we insert a new Contact that we know his/her Id. Once the Contact is inserted, we know the inserted Id is e.g. 15. So we insert 3 emails for this contact and all three will have ContactEmails.ContactId value of 15. But we have no knowledge of 15 before the contact is inserted into the database.
We can insert all contacts as bulk into the table. But when it comes to their email, the connection is lost because emails do not know their own contacts.
Disable the constraints (foreign key) before bulk insert. Then enable it again.
Make sure you do not have referential integrity violations.
You can disable FK and CHECK constraints using below query:
ALTER TABLE foo NOCHECK CONSTRAINT ALL
or
ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column
Primary keys and unique constraints can not be disabled, but this should be OK if I've understood you correctly.

Updating relations in Linq To SQL is possible?

I need some functionality in my project and I don't know if its possible.
Here is a pic with the relations:
I need to update the keys relation table LessonByFacultyMember and the same keys in Scheduling table.
I mean the keys LessonNumber,LessonCoursenumber,FacultyMemberId (LessonByFacultyMember table)
and LessonNumber,CourseNumber,FacultyMemberId (Scheduling Table).
Is it possible to update this kind of relations?
UPDATE:
I just want to be clear that i mean the possibility to change the VALUE that stored in the keys dynamically in some method.
Yes you can do so by selecting Update Cascade option in Foreign key in the database.This options automatically updates the key values in the other tables. But in your case this is not needed. The table LessonByFacultyMember should have a column LessonByFacultyMemberId as a primary key and that should be in the Scheduling table as a Reference instead of putting all the three columns in the Scheduling table. If you do so ,you don't need to worry about the updating LessonNumber,CourseNumber,FacultyMemberId in the Scheduling Table. Also in your Scheduling table there should be a column SchedulingID as a Primary Key. You can take LessonByFacultyMemberId ,SchedulingID as an auto incremented integer. Also there is no need to make LessonNumber,CourseNumber,FacultyMemberId as a Primary key in the LessonByFacultyMember table. Instead you need to make them as unique key. Similarly in Scheduling table make the current primary key as unique key and have SchedulingId as primary key. In case of showing records you need to make select statement using joins and it is better to create a view for such statement. In case if still it is not clear , create a sqlFiddle on http://sqlfiddle.com/ for your schema and share that in your question or comment to this answer. I will update the same.

SQL Server - formatted identity column

I would like to have a primary key column in a table that is formatted as FOO-BAR-[identity number], for example:
FOO-BAR-1
FOO-BAR-2
FOO-BAR-3
FOO-BAR-4
FOO-BAR-5
Can SQL Server do this? Or do I have to use C# to manage the sequence? If that's the case, how can I get the next [identity number] part using EntityFramwork?
Thanks
EDIT:
I needed to do this is because this column represents a unique identifier of a notice send out to customers.
FOO will be a constant string
BAR will be different depending on the type of the notice (either Detection, Warning or Enforcement)
So is it better to have just an int identity column and append the values in Business Logic Layer in C#?
If you want this 'composited' field in your reports, I propose you to:
Use INT IDENTITY field as PK in table
Create view for this table. In this view you can additionally generate the field that you want using your strings and types.
Use this view in your repoorts.
But I still think, that there is BIG problem with DB design. I hope you'll try to redesign using normalization.
You can set anything as the PK in a table. But in this instance I would set IDENTITY to just an auto-incrementing int and manually be appending FOO-BAR- to it in the SQL, BLL, or UI depending on why it's being used. If there is a business reason for FOO and BAR then you should also set these as values in your DB row. You can then create a key in the DB between the two three columns depending on why your actually using the values.
But IMO I really don't think there is ever a real reason to concatenate an ID in such a fashion and store it as such in the DB. But then again I really only use an int as my ID's.
Another option would be to use what an old team I used to be on called a codes and value table. We didn't use it for precisely this (we used it in lieu of auto-incrementing identities to prevent environment mismatches for some key tables), but what you could do is this:
Create a table that has a row for each of your categories. Two (or more) columns in the row - minimum of category name and next number.
When you insert a record in the other table, you'll run a stored proc to get the next available identity number for that category, increment the number in the codes and values table by 1, and concatenate the category and number together for your insert.
However, if you're main table is a high-volume table with lots of inserts, it's possible you could wind up with stuff out of sequence.
In any event, even if it's not high volume, I think you'd be better off to reexamine why you want to do this, and see if there's another, better way to do it (such as having the business layer or UI do it, as others have suggested).
It is quite possible by using computed column like this:
CREATE TABLE #test (
id INT IDENTITY UNIQUE CLUSTERED,
pk AS CONCAT('FOO-BAR-', id) PERSISTED PRIMARY KEY NONCLUSTERED,
name NVARCHAR(20)
)
INSERT INTO #test (name) VALUES (N'one'), (N'two'), (N'three')
SELECT id, pk, name FROM #test
DROP TABLE #test
Note that pk is set to NONCLUSTERED on purpose because it is of VARCHAR type, while the IDENTITY field, which will be unique anyway, is set to UNIQUE CLUSTERED.

Design Implementation SQL tables

I am new to SQL and been given a task. Following are the details:
What I have:
A C# desktop application for User login and view user status (only two options: user logs in and check status of all users that are dummy created)
A table named USER containing
id
username
datecreated
A table named LOGINSTAT containing
id
username
Logtime
logDate
What I have to implement
I have to save time and date when ever user logs in in LOGINSTAT table using SQL.
My question
My question is how can I implement that. I can do the coding part but I am interested in getting some good advice to implement it. I think of it as a formal way as I know to do it:
when user logs in insert values into the login table giving all the required values.
BUT
I think that might be a bit odd. Some of my friends said you may be able to implement it by use of foreign key and primary keys, but the problem lies that the user may log in many time in a day. How to keep track of login time and date in that case?
You don't need username in your LOGINSTAT table.
You'll probably want the LOGINSTAT to include:
id
u_id
loginDateTime
id is the unique ID of every login
u_id is a foreign key from the id in users that matches your log event to a user
loginDateTime is a datetime that will give you both your log date and log time in one column
What is unique in LOGINSTAT? Not user by itself, but ID+LogDate+LogTime should be. That would be your primary key.
The only foreign key is in LOGINSTAT: ID, which references the ID in the USER table.
Values in a PRIMARY KEY column (eg. USER.id) must be unique from one another.
Values in a FOREIGN KEY column in another table referencing that primary key (eg. LOGINSTAT.id referencing USER.id) do not need to be unique - you can have multiple records in a table have the same foreign key column reference the same primary key.

How to Update the primary key of table which is referenced as foreign key in another table?

Suppose a
Table "Person" having
"SSN",
"Name",
"Address"
and another
Table "Contacts" having
"Contact_ID",
"Contact_Type",
"SSN" (primary key of Person)
similarly
Table "Records" having
"Record_ID",
"Record_Type",
"SSN" (primary key of Person)
Now i want that when i change or update SSN in person table that accordingly changes in other 2 tables.
If anyone can help me with a trigger for that
Or how to pass foreign key constraints for tables
Just add ON UPDATE CASCADE to the foreign key constraint.
Preferably the primary key of a table should never change. If you expect the SSN to change you should use a different primary key and have the SSN as a normal data column in the person table. If it's already too late to make this change, you can add ON UPDATE CASCADE to the foreign key constraint.
If you have PKs that change, you need to look at the table design, use an surrogate PK, like an identity.
In your question you have a Person table, which could be a FK to many many tables. In that case a ON UPDATE CASCADE could have some serious problems. The database I'm working on has well over 300 references (FK) to our equivalent table, we track all the various work that a person does in each different table. If I insert a row into our Person table and then try to delete it back out again (it will not be used in any other tables, it is new) the delete will fail with a Msg 8621, Level 17, State 2, Line 1 The query processor ran out of stack space during query optimization. Please simplify the query. As a result I can't imagine an ON UPDATE CASCADE would work either when you get many FKs on your PK.
I would never make sensitive data like a SSN a PK. Health care companies used to do this and had a painful switch because of privacy. I hope you don't have a web app and have a GET or POST variable called SSN with the actual value in it!! Or display the SSN on every report, or will you shred all old printed reports and limit access to who views each report., etc.
Well, assuming the SSN is the primary key of the Person table, I would just (in a transaction of course):
create a brand new row with the new SSN, copying all other details from the old row.
update the columns in the other tables to point to the new row.
delete the old row.
Now this is actually a good example of why you shouldn't use real data as table cross-references, if that data can change. If you'd used an artificial column to tie them together (and only stored the SSN in one place), you wouldn't have the problem.
Cascade update and delete are very dangerous to use. If you have a million child records, you could end up with a serious locking problem. You should code the updates and deletes instead.
You should never use a PK with the potential to change if it can be avoided. Nor should you ever use SSN as a PK because it should never be stored unencrypted in your database. Never, unless your company likes to be sued when they are the cause of an indentity theft incident. This is not a design flaw to shrug off as this is legacy, we don't have time to fix. This is a design flaw that could bankrupt your company if someone steals your backup tapes or gets the ssns out of the sytem in another manner (most of these types of thefts are internal BTW). This is an urgent - must fix now design flaw.
SSN is also a bad candidate because it changes (people change them when they are victims of identity theft for instance.) Plus an integer PK will have faster performance than a nine-digit PK.

Categories

Resources