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
 a few questions on locking in sql server 2005

Author  Topic 

nikb
Starting Member

5 Posts

Posted - 2008-01-29 : 19:24:08
Hi pardon my ignorance but I wonder if someone could answer a few questions for me.

I am writing a program which will be used by perhaps upto 100 users at a time. The program sits on any number of PCs and loads user specific data to a given PC according to who has logged on to windows on that PC.

A number of data items loaded from the user table have to be unique as they are usernames for other systems that my program simplifies access to.

So when a user logs on to my program for the first time a row is created for them in the user table (indexed by a GUID and their unique network name). The other unique fields are left blank and the user is given an opportunity to fill these details in.

Before writing these details to the user's row in the 'users table' the program loads the whole user table down and checks that these items are unique before committing them to that user's row in the table.

The problem of course is that if between the program downloading the user table into a local datatable, checking the values are unique and then actually writing them someone else writes the same data into their row then 2 users end up with the same data - which shouldn't be allowed. i.e. 2 users can't have the same user name for the other software.

How can I solve this problem with locking? Once the user table is downloaded and in a locel datatable presumably the table is no longer locked so another user could write data to the table.

I acutally think this is going to be a pretty rare occourance but I still want to try to cover all eventualities.

I suspect the problem is the way my program is going about the checking.

Should I use an SQL insert statement like??

If exists(SELECT username from users where username=@username)
BEGIN
RAISEERROR("Username already exists")
END
ELSE
BEGIN
INSERT etc

If so I guess this will simplify my code. Is this the correct thing to do? And then just trap the errors that arise if a duplicate does arise?

Also some more general questions.

1)I presume 2 users simultaneously looking up data from 2 different rows in a table doesn't lock the table so one search fails? I use the code below having set up a command to run a stored procedure to search for a user by their network name.

Dim lclRowRet As SqlDataReader

lclRowRet = LoadUserCommand.ExecuteReader(CommandBehavior.SingleRow)

lclRowRet.Read()

2) I presume writing data to my user table a row at a time will also not cause a lock. I create a command object with all the row values in and then do a command.executenonquery()

As a rule I close all my connections as soon as I'm done with them.

Many thanks for your help in advance.

nik

Ifor
Aged Yak Warrior

700 Posts

Posted - 2008-01-30 : 09:45:02
quote:
Before writing these details to the user's row in the 'users table' the program loads the whole user table down and checks that these items are unique before committing them to that user's row in the table.


Ouch!
You need to do the duplicate check on the server with something like:
INSERT INTO YourTable
SELECT @UserName ...
WHERE NOT EXISTS
(
SELECT *
FROM YourTable WITH (UPDLOCK)
WHERE UserName = @UserName
)

If no rows are inserted, then you know there was a duplicate.

An alternative is to make sure there is an unique constraint on the username column and just trap any exceptions in your program.
Go to Top of Page

Hommer
Aged Yak Warrior

808 Posts

Posted - 2008-01-30 : 10:04:12
Two things you described need more thoughts.

First of, this is not a locking issue, which has to do with concurrent control of more than one users access/modify same row of data. In your case, each user works on his/her own row. You sound like just to implement a feature that will warn user "that user name has been taken, try gain".

You do not or should not "downloading the user table into a local datatable".

Go to Top of Page

nikb
Starting Member

5 Posts

Posted - 2008-01-30 : 15:36:54
Thanks for your help - actually Hommer you are correct I do want to issue a warning like 'that user name has been taken' because the usernames should be unique and effectively if another user has that username then they're using it when they shouldn't be.
Also I missed a really vital bit of info out which is that I've encrypted the username column using a bit of encryption I wrote myself. Mostly to increase security so that anyone who gains access to the user table can't match network user names to usernames from the other program. Maybe by doing that I've over complicated things as I have to download the table to decrypt each username to compare it to the new one. I think if they weren't duplicated then Ifor's way of doing it would be better.

A unique constraint sounds the way to go acutally if I choose not to encrypt the usernames.

Thanks very much.

Go to Top of Page

nikb
Starting Member

5 Posts

Posted - 2008-01-30 : 17:56:15
I realised that using contraints to ensure unqiue column entries means that you can't have multiple nulls - so I'll use the SQL method as suggested I think.

Thanks

Nik
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2008-01-30 : 18:09:30
you can have unique values with multiple nulls by using a view on the table
http://weblogs.sqlteam.com/mladenp/archive/2007/05/17/60209.aspx

_______________________________________________
Causing trouble since 1980
blog: http://weblogs.sqlteam.com/mladenp
SSMS Add-in that does a few things: www.ssmstoolspack.com <- new version out
Go to Top of Page
   

- Advertisement -