SQL Server : constraints to ensure unique value on 2 columns - sql-server

I have a table with 2 columns, Username & Email
Username | Email
-------------------------
a#a.com | a#a.com
b#b.com | c#c.com
I want the Username to be unique in both columns except the current record.
Same for the Email column.
For example, if I am trying to insert the following rows into the table, it should not be allowed.
Username | Email
e#e.com | b#b.com
c#c.com | f#f.com
Can this be done via SQL Server constraints?
Best regards

Related

How to properly store login info in database

I wanna to design an authentication database which has the following functions:
I used Bcrypt so I need to store the salted password in the dB
I only allow user login to one device at a time, so I need to check if the user is currently logged in. (is_logged_in)
I need users to verify their email/phone before adding them into the account (email_verified, phone_verified)
I want to store all the user's info (firstName, lastName, dateOfBirth, etc.)
I want users to create at most three security questions/answers before using
I want to store users' passed logged in info (Time, location, etc.)
I want to share this database between my multiple apps, i.e. use one account to log in my multiple apps
So I Designed the following tables (Primary Key is in bold):
Authentication_Info
UID | Password_salt | Is_logged_in | Email_Verified | Phone_Verified
User_Info
UID | FirstName | LastName | Email | Location | RegisterDate | PhoneNumber | DateOfBirth | isEnabled
SecurityQ/A
UID | SID | SecurityQuestion | SecurityAnswer
Passed_login_info
UID | Time | Location | IP | Device
After I changed them to 3NF, I got the following tables (Again, primary Key is in bold):
Authentication_Info
UID | Password_salt | Is_logged_in
User_Info
UID | FirstName | LastName | Email_id | Location | RegisterDate | Phone_id | DateOfBirth
SecurityQ/A
UID | SID | SecurityQuestion | SecurityAnswer
Passed_login_info
UID | PID | Time | Location | IP | Device
Token_Verification
Verification_id | UID | TempToken | Expire_Time
Is this a good design? Any mistakes I made?
Since I'm not familiar with the intended use of the application, I can't say for sure if the advice below is applicable in this situation, but regardless, here are some suggestions:
Regarding the Token_Verification table, I believe only three fields are required: UID, TempToken, Expire_Time. I don't see the need for Verification_id.
The Authentication_Info table does not need a field for Is_logged_in because we can check if a UID is logged-in by searching the Token_Verification table for a valid TempToken. Thus, this field can be removed.
The Password_salt field in the Authentication_Info table should be separated into Salt and SaltedHash_Password. When a password arrives for validation, you will have to prepend the salt, hash the (salt + password) and compare against the stored value.
In the SecurityQ/A table, you should treat SecurityAnswer as if it were a password. Each security answer should be stored with a unique random salt. Thus, the fields of the table should be UID, SID, SecurityQuestion, Salt, SaltedHash_SecurityAnswer.
The tables I haven't mentioned above look fine to me :)
(\(\
).. \
\Y_, '-.
) '.
| \/ \
\\ |\_ |_
((_/(__/_,'.
(,----'

SSIS - Insert all records with matching ID

I have following staging table and a destination table with the same data:
ID | Name | Job | Hash
1 | A | IT | XYZ1
2 | B | Driver | XYZ2
The staging table gets truncated each time and new data gets inserted. Sometimes, a person can get a second job. In that case, we have 2 records with ID 2 and Name B, but with a differentjobandhash` in the staging table.
ID | Name | Job | Hash
1 | A | IT | XYZ1
2 | B | Driver | XYZ2
2 | B | IT | XYY4
If this happens, I need to insert all records with ID 2 into the destination table. I already have a LKP that checkes for (un-)matching ID's, but how can I "tell" SSIS to take ALL records from the staging table based on the ID's I get from the no match output?
You tell ssis by link the no match output from the lookup to the destination. Assume you have already set 'Redirect rows to no match output' in lookup - general. And in your lookup, you check for matching id (not sure how you check unmatching) This way, lookup will output all non-matched rows (by Id) to the destination.

Foreign keys from 2 columns of the same table to the same primary key

I have two tables:
users
id | username
--------------
1 | James
2 | John
3 | Jack
4 | Jim
5 | Jane
6 | Jessica
juniors
senior_id | junior_id
-----------------------
1 | 4
1 | 6
2 | 3
4 | 5
Both the senior_id and junior_id refer to the users table's id column.
How do I set it up so that a) it is guaranteed that both senior_id and junior_id exist in users and b) a delete from users will cascade and remove any instances of the deleted id from juniors whether it's a senior_id or junior_id? I.e. deleting Jim in the example above will automatically remove both the first and last record from juniors.
I tried doing this with two separate constraints. But if I set up cascade on both constraints I get a 'may cause cycles or multiple cascade paths' error.
And if I set it on only one constraint then a delete fails (in a case like Jim) because it cascades to only one of the columns and thus then violates the constraint.
I have to be able to do this on SQL Server 2005.
Remove FK constraint.For FK constraint check.Create trigger on table juniors before insert/update.if id do not exists then rollback.Again now create another trigger on table User for DELETE.and in trigger write script to delete all record.since FK do not fulfill your requirement,therefore no point in keeping one extra constraint.
Most importantly I think your table design is bad.Table design should be like Employee-Manager relation table i.e. keep SeniorID in User Table itself.
so many of your problem will vanish .
Also there is no extra cost or complication for any query on this table
id | username SeniorID
--------------
1 | James
2 | John
3 | Jack 2
4 | Jim 5
5 | Jane
6 | Jessica

Relationships Between Tables in MS Access

I'm new in DataBases at all and have some difficulties with setting relationships between 3 tables in MS Access 2013.
The idea is that I have a table with accounts info, a table with calls related to this accounts and also one table with all the possible call responses. I tried different combinations between them but nothing works.
1st table - Accounts : AccountID(PK) | AccountName | Language | Country | Email
2nd table - Calls : CallID(PK) | Account | Response | Comment | Date
3rd table - Responses: ResponseID(PK) | Response
When you have a table, it usually has a Primary Key field that is the main index of the table. In order for you to connect it with other tables, you usually do that by setting Foreign Key on the other table.
Let's say you have your Accounts table, and it has AccountID field as Primary Key. This field is unique (meaning no duplicate value for this field).
Now, you have the other table called Calls and you have a Foreign Key field called AccountID there, which points to the Accounts table.
Essentially you have Accounts with the following data:
AccountID| AccountName | Language | Country | Email
1 | FirstName | EN | US | some#email.com
2 | SecondName | EN | US | some#email.com
Now you have the other table Calls with Many calls
CallID(PK) | AccountID(FK) | ResponseID(FK) | Comment | Date
1 | 1 | 1 | a comment | 26/10
2 | 1 | 1 | a comment | 26/10
3 | 2 | 3 | a comment | 26/10
4 | 2 | 3 | a comment | 26/10
You can see the One to Many relationship: One accountID (in my example AccountID=1) to Many Calls (in my example 2 rows with AccountID=1 as foreign keys, rows 1 & 2) and AccountID=2 has also 2 rows of Calls (rows 3 and 4)
Same goes for the Responses table
Using this table structure:
Accounts : AccountID(PK) | AccountName | Language | Country | Email
Calls : CallID(PK) | AccountID(FK) | ResponseID(FK) | Comment | Date
Responses: ResponseID(PK) | Response
Accounts.AccountID is referenced by Calls.AccountID. 1:n – many calls for one account possible, but each call concerns just one account.
Responses.ResponseID is referenced by Calls.ResponseID. 1:n – many calls can get the same response from the prepared set, but each call gets exactly one of them.
To actually define the Relationships in Access, open the Relationships window...
... then follow the detailed instructions here:
How to define relationships between tables in an Access database

DB Data migration

I have a database table called A and now i have create a new table called B and create some columns of A in table B.
Eg: Suppose following columns in tables
Table A // The one already exists
Id, Country Age Firstname, Middlename, Lastname
Table B // The new table I create
Id Firstname Middlename Lastname
Now the table A will be look like,
Table A // new table A after the modification
Id, Country, Age, Name
In this case it will map with table B..
So my problem is now i need to kind of maintain the reports which were generated before the table modifications and my friend told me you need to have a data migration..so may i know what is data migration and how its work please.
Thank you.
Update
I forgot to address the reporting issue raised by the OP (Thanks Mark Bannister). Here is a stab at how to deal with reporting.
In the beginning (before data migration) a report to generate the name, country and age of users would use the following SQL (more or less):
-- This query orders users by their Lastname
SELECT Lastname, Firstname, Age, Country FROM tableA order by Lastname;
The name related fields are no longer present in tableA post data migration. We will have to perform a join with tableB to get the information. The query now changes to:
SELECT b.Lastname, b.Firstname, a.Country, a.Age FROM tableA a, tableB b
WHERE a.name = b.id ORDER BY b.Lastname;
I don't know how exactly you generate your report but this is the essence of the changes you will have to make to get your reports working again.
Original Answer
Consider the situation when you had only one table (table A). A couple of rows in the table would look like this:
# Picture 1
# Table A
------------------------------------------------------
Id | Country | Age | Firstname | Middlename | Lastname
1 | US | 45 | John | Fuller | Doe
2 | UK | 32 | Jane | Margaret | Smith
After you add the second table (table B) the name related fields are moved from table A to table B. Table A will have a foreign key pointing to the table B corresponding to each row.
# Picture 2
# Table A
------------------------------------------------------
Id | Country | Age | Name
1 | US | 45 | 10
2 | UK | 32 | 11
# Table B
------------------------------------------------------
Id | Firstname | Middlename | Lastname
10 | John | Fuller | Doe
11 | Jane | Margaret | Smit
This is the final picture. The catch is that the data will not move from table A to table B on its own. Alas human intervention is required to accomplish this. If I were the said human I would follow the steps given below:
Create table B with columns Id, Firstname, Middlename and Lastname. You now have two tables A and B. A has all the existing data, B is empty .
Add a foreign key to table A. This FK will be called name and will reference the id field of table B.
For each row in table A create a new row in table B using the Firstname, Middlename and Lastname fields taken from table A.
After copying each row, update the name field of table A with the id of the newly created row in table B.
The database now looks like this:
# Table A
-------------------------------------------------------------
Id | Country | Age | Firstname | Middlename | Lastname | Name
1 | US | 45 | John | Fuller | Doe | 10
2 | UK | 32 | Jane | Margaret | Smith | 11
# Table B
------------------------------------------------------
Id | Firstname | Middlename | Lastname
10 | John | Fuller | Doe
11 | Jane | Margaret | Smith
Now you no longer need the Firstname, Middlename and Lastname columns in table A so you can drop them.
voilà, you have performed a data migration!
The process I just described above is but a specific example of a data migration. You can accomplish it in a number of ways using a number of languages/tools. The choice of mechanism will vary from case to case.
Maintenance of the existing reports will depend on the tools used to write / generate those reports. In general:
Identify the existing reports that used table A. (Possibly by searching for files that have the name of table A inside them - however, if table A has a name [eg. Username] which is commonly used elsewhere in the system, this could return a lot of false positives.)
Identify which of those reports used the columns that have been removed from table A.
Amend the existing reports to return the moved columns from table B instead of table A.
A quick way to achieve this is to create a database view that mimics the old structure of table A, and amend the affected reports to use the database view instead of table A. However, this adds an extra layer of complexity into maintaining the reports (since developers may need to maintain the database view as well as the reports) and may be deprecated or even blocked by the DBAs - consequently, I would only recommend using this approach if a lot of existing reports are affected.

Resources