| Author |
Topic |
|
Cowski
Starting Member
30 Posts |
Posted - 2009-12-10 : 15:34:04
|
| My project is this. We have 2 table "HR" and "AgentLogin". Both have a field called "username". What we want to do is prevent any duplicate usernames from being inserted into either table. We would like an error thrown.We're thinking of using a constraint. I can get it to work on a single table but having issues with checking both tables before the insert statement activates.Suggestions?Thanks!! |
|
|
DP978
Constraint Violating Yak Guru
269 Posts |
Posted - 2009-12-10 : 16:10:38
|
| can you set 2 variables to True/False and then do a check, if both are TRUE then continue the insert.Declare @Table1OK intDeclare @Table2OK intSet @Table1OK = 0Set @Table2OK = 0...Use your code to see if the record exists on table 'HR'...if it doesnt and your code returns a null record set...then...Set @Table1OK = 1...Use your code to see if the record exists on table 'AgentLogin'...if it doesnt and your code returns a null record set...then...Set @Table2OK = 1If @Table1OK = 1 and @Table2OK = 1Then...Insert the User into whichever table...ELSEPrint 'Failed due to duplicate'EDIT: Or UNION the distinct UserName's from your 2 tables and if it exists in there then throwback an error, if it doesn't then proceed. |
 |
|
|
Cowski
Starting Member
30 Posts |
Posted - 2009-12-10 : 16:20:29
|
This sounds very doable, DP. Will run with something like this & see what happens. I'm thinking something along the lines of a stored proc with the username as a parameter. Will keep you posted. Thanks! |
 |
|
|
russell
Pyro-ma-ni-yak
5072 Posts |
Posted - 2009-12-10 : 16:38:16
|
I'd probably do this with a trigger on each table.Create Trigger AgentLogin_Usename on agentloginfor insert, updateasIF Exists( select hr.username from hr join inserted i on i.username = hr.username)BEGIN RaisError('username exists in hr table', 16, 1) rollbackEND |
 |
|
|
DP978
Constraint Violating Yak Guru
269 Posts |
Posted - 2009-12-11 : 08:28:42
|
| He needs to check both tables to see if the User ID is there, will that check both? Or will it only check the first and then insert if ok, and then the second and insert if ok. Would there be a chance that it catches the duplicate on the second table and at that point has already inserted the ID into table 1? |
 |
|
|
Cowski
Starting Member
30 Posts |
Posted - 2009-12-11 : 08:53:37
|
quote: Originally posted by russell I'd probably do this with a trigger on each table.
We considered a trigger but doesn't a trigger react to an event that has already taken place? We need this to happen before anything happens.I've got a stored procedure in the making that will be called that can check for the username & react accordingly. |
 |
|
|
DP978
Constraint Violating Yak Guru
269 Posts |
Posted - 2009-12-11 : 09:57:37
|
| The rollback will undo whatever activated the trigger. So I do not believe that part is a problem. |
 |
|
|
russell
Pyro-ma-ni-yak
5072 Posts |
Posted - 2009-12-11 : 10:11:44
|
| Put a unique constraint on the username field of each table. Put a trigger on each table that checks the other. No dupes this way. And as DP978 said, the trigger will prevent the insert if the username exists in the other table. |
 |
|
|
russell
Pyro-ma-ni-yak
5072 Posts |
Posted - 2009-12-11 : 10:14:36
|
| [code]create table hr (username varchar(32) unique);GOcreate table AgentLogin (username varchar(32) unique);GOCreate Trigger AgentLogin_Usename on agentloginfor insert, updateasIF Exists( select hr.username from hr join inserted i on i.username = hr.username)BEGIN RaisError('username exists in hr table', 16, 1) rollbackENDGOCreate Trigger Hr_Usename on hrfor insert, updateasIF Exists( select a.username from agentlogin a join inserted i on i.username = a.username)BEGIN RaisError('username exists in agentlogin table', 16, 1) rollbackENDGOinsert AgentLogin values('cowski'); -- succeedsinsert hr values('cowski') -- failsselect * from AgentLogin;select * from hrdrop table hrdrop table AgentLogin[/code] |
 |
|
|
RyanRandall
Master Smack Fu Yak Hacker
1074 Posts |
Posted - 2009-12-11 : 10:47:42
|
Here's another option (using a function and a check constraint on each table)...drop table t1drop table t2drop function dbo.username_countgocreate table dbo.t1 (username varchar(9))create table dbo.t2 (username varchar(9))gocreate function dbo.username_count(@username varchar(9)) returns tinyint asbeginreturn (select count(*) from (select * from t1 union all select * from t2) a where username = @username)endgoalter table dbo.t1 with nocheck add constraint t1_unique_username check (dbo.username_count(username) <= 1)alter table dbo.t2 with nocheck add constraint t2_unique_username check (dbo.username_count(username) <= 1)select dbo.username_count('a') as Countinsert t1 select 'a'insert t2 select 'b'insert t2 select 'a'insert t1 select 'c'insert t1 select 'b'select dbo.username_count('a') as Countselect dbo.username_count('d') as Countselect * from t1select * from t2Ryan Randall - Yak of all tradesSolutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
Cowski
Starting Member
30 Posts |
Posted - 2009-12-11 : 11:10:27
|
Here's what I worked up for a stored procedure. This seems to be working so far:USE [master]GO/****** Object: StoredProcedure [dbo].[ausp_UserNameCheck] Script Date: 12/11/2009 11:07:17 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO ALTER PROCEDURE [dbo].[ausp_UserNameCheck] -- Add the parameters for the stored procedure here @varUserName varchar(20)ASBEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; Declare @varUser varchar(20) Declare @varCountHR int Declare @varcountAgentLogin int Select @varCountHR = count(*) from [AdventureWorks].[dbo].[JohnsHR] where [AdventureWorks].[dbo].[JohnsHR].[UserName] = @varUserName Select @varCountAgentLogin = count(*) from [AdventureWorks].[dbo].[JohnsAgentLogin] where [AdventureWorks].[dbo].[JohnsAgentLogin].[UserId] = @varUserName if @varCountHR >= 1 --Print 'ERROR!! Duplicate username exists within the HR table.' RaisError('Error. Duplicate Username exists with the HR table.', 16, 1) Else Print 'Username confirmed. Inserting into HR table...' if @varCountAgentLogin >= 1 --Print 'Error! Duplicate username exists within the AgentLogin table.' RaisError('Error. Duplicate Username exists with the AgentLogin table.', 16, 1) Else Print 'Username confirmed. Inserting into AgentLogin table...' --Insert record into the AgentLogins table. END |
 |
|
|
russell
Pyro-ma-ni-yak
5072 Posts |
Posted - 2009-12-11 : 11:16:55
|
| If someone inserts without your SP your data is corrupt. Should either use triggers as I showed, or Check constraint as Ryan showed. |
 |
|
|
Cowski
Starting Member
30 Posts |
Posted - 2009-12-11 : 12:31:14
|
Russell,Thanks for the code you wrote up. 95% of it makes sense & I'm going to tweak it now to run with my 2 big test tables. (well lunch first! ).I do have a question though. The code:select a.username from agentlogin a join inserted i <-- on i.username = a.username What does the inserted i function as? Thanks again & will report back. |
 |
|
|
russell
Pyro-ma-ni-yak
5072 Posts |
Posted - 2009-12-11 : 12:39:35
|
| inserted is a logical table available inside of triggers that contains the record about to be inserted, or the record as it would look after an update. in other words, the "after" state of the update/insert.deleted is another logical table that contains the "before" state.check out BOL for full details: http://msdn.microsoft.com/en-us/library/ms189799.aspx |
 |
|
|
|