From: Meir on
Hello,
I have a Users table with 2 fields, UserName and Visible. The same UserName
can exist many times with Visible = 0 but just one record can exist for the
same UserName with visible = 1.

In my Stored Procedure before inserting a new visible user I check the user
doesn't exist in the table with visible = 1, but that is not enough, there
are cases when the Stored Procedure is called in the same moment with the
same parameters and there is duplicated data.

I can't define a Unique constraint because UserName with visible = 0 is not
unique, what would be the best way to approach this problem.

Thanks
Meir


CREATE TABLE [dbo].[Users](
[UserId] [int] NOT NULL,
[UserName] [nchar](10) NOT NULL,
[Visible] [bit] NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[UserId] ASC
)
From: Sylvain Lafontaine on
Personally, I would use a XLOCK along a SERIALIAZABLE hints in order to
exclusively lock but I'm not really sure of what you're doing exactly. To
avoid any deadlock, you must be careful to make all your selections at the
beginning of the SP and in exactly the same order. (Not only for this SP
but also for other SP that could use the same locks on the same table(s).
Something like:

Begin Transaction

If Not Exists (Select * from Users with (xlock, serializable) where UserName
= @UserName
And Visible = 1)
Begin
Insert into User (UserName, Visible) Values (@UserName, 1)
End
Else
Begin
-- Don't know what you want to do here. --
End

Commit


Even if you test for Visible=1, both the records with Visible=0 and
Visible=1 will be locked. Finally, if you have other transactions with
ReadCommitted and that you would want to block them too, see:

http://support.microsoft.com/kb/324417

http://sqlblog.com/blogs/louis_davidson/archive/2006/12/13/does-xlock-always-prevent-reads-by-others.aspx

--
Sylvain Lafontaine, ing.
MVP - Windows Live Platform
Blog/web site: http://coding-paparazzi.sylvainlafontaine.com
Independent consultant and remote programming for Access and SQL-Server
(French)


"Meir" <Meir(a)discussions.microsoft.com> wrote in message
news:BBB87B74-5D12-4BC9-8B29-FCC9D560A129(a)microsoft.com...
> Hello,
> I have a Users table with 2 fields, UserName and Visible. The same
> UserName
> can exist many times with Visible = 0 but just one record can exist for
> the
> same UserName with visible = 1.
>
> In my Stored Procedure before inserting a new visible user I check the
> user
> doesn't exist in the table with visible = 1, but that is not enough, there
> are cases when the Stored Procedure is called in the same moment with the
> same parameters and there is duplicated data.
>
> I can't define a Unique constraint because UserName with visible = 0 is
> not
> unique, what would be the best way to approach this problem.
>
> Thanks
> Meir
>
>
> CREATE TABLE [dbo].[Users](
> [UserId] [int] NOT NULL,
> [UserName] [nchar](10) NOT NULL,
> [Visible] [bit] NOT NULL,
> CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
> (
> [UserId] ASC
> )


From: --CELKO-- on
Do this in the DDL and not in code.

CREATE TABLE Users
(user_id INTEGER NOT NULL,
user_version INTEGER DEFAULT 1 NOT NULL
CHECK (user_version > 0),
PRIMARY KEY (user_id, user_version)
user_name NCHAR(10) NOT NULL,
etc.);

Now use this VIEW for the most recent row in the Users table. Much
easier than assembly language style bit flags.

CREATE VIEW CurrentUsers -- updatable!
AS
SELECT U1.user_id, etc.
FROM Users AS U1
WHERE user_version
= (SELECT MAX(U2.user_version)
FROM Users AS U2
WHERE U1.user_id = U2.user_id);

The procedures to maintain this model are easy and you should not have
any trouble writing them.