0

我需要一些有关此过程的帮助:

如果没有其他具有相同名称的用户,它应该做的是尝试插入一个新用户。

如果已经有一个用户,它应该回滚否则提交。但它不起作用,它无论如何都会提交。

有什么建议么?

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

ALTER procedure [dbo].[SP_USUARIOS_INSERT]
@usu_ds varchar(50),
@usu_dt_create datetime,
@usu_dt_lst_log datetime,
@usu_ds_senha varchar(255),
@usu_ds_email varchar(100)
as
begin
declare @varCheckUser varchar(100) = null;
set @varCheckUser = (select COUNT(usu.usu_Ds) from Usuarios usu where usu.usu_ds = @usu_ds);
begin transaction
insert into Usuarios(usu_ds,usu_dt_create,usu_dt_lst_log,usu_ds_senha,usu_ds_email) values(@usu_ds,@usu_dt_create,@usu_dt_lst_log,@usu_ds_senha,@usu_ds_email)
if (@varCheckUser <> null)
begin
 RAISERROR('User already exists',16,1)
 rollback transaction
 return
end
else
begin
commit transaction
end
end
4

5 回答 5

2

我认为@varCheckUser 永远不会为 NULL,如果没有行,它将为 0

set @varCheckUser = (select COUNT(usu.usu_Ds) 
from Usuarios usu where usu.usu_ds = @usu_ds);

这将使它成为 0

你也像这样检查NULL

if (@varCheckUser IS NOT null)

你为什么不做这样的事情

IF  EXISTS (select 1 
               from Usuarios usu 
                where usu.usu_ds = @usu_ds)
SET @varCheckUser =1

然后检查它是否不是 1

为什么需要 tran?做这样的事情

IF  EXISTS (select 1 
                   from Usuarios usu 
                    where usu.usu_ds = @usu_ds)
BEGIN
RAISERROR('User already exists',16,1)
RETURN
END
ELSE
BEGIN
insert into Usuarios(usu_ds,usu_dt_create,usu_dt_lst_log,usu_ds_senha,usu_ds_email)
values(@usu_ds,@usu_dt_create,@usu_dt_lst_log,@usu_ds_senha,@usu_ds_email)

END

制作 usu_ds aprimary key或添加unique constraint 可能是个好主意,这样没有人可以将他们的用户名更新为存在的内容,也没有人可以错误地使用 SSMS 并将用户名更改为表中已经存在的内容

于 2010-08-11T20:49:30.873 回答
1

It doesn't have to that complicated.

ALTER procedure [dbo].[SP_USUARIOS_INSERT]
   @usu_ds varchar(50),
   @usu_dt_create datetime,
   @usu_dt_lst_log datetime,
   @usu_ds_senha varchar(255),
   @usu_ds_email varchar(100)
AS

SET NOCOUNT, XACT_ABORT ON 
INSERT Usuarios(usu_ds, usu_dt_create, usu_dt_lst_log, usu_ds_senha, usu_ds_email) 
SELECT @usu_ds, @usu_dt_create, @usu_dt_lst_log, @usu_ds_senha, @usu_ds_email
WHERE
   NOT EXISTS (
      SELECT 1
      FROM Usuarios WITH (UPDLOCK, HOLDLOCK)
      WHERE usu_ds = @usu_ds
   )
IF @@RowCount = 0 BEGIN
   RAISERROR('User already exists', 16, 1)
   RETURN
END

This code completely solves any concurrency problems for you as well (see Conditional Insert/Update Race Condition).

于 2010-08-11T23:16:26.697 回答
1

您需要将支票更改为使用@varCheckUser = 0- 或者更好的是,将其更改为使用IF EXISTS,并且仅在该用户不存在时才开始交易以插入值:

IF NOT EXISTS(SELECT * FROM dbo.Usuarios usu WHERE usu.usu_ds = @usu_ds)
BEGIN
   BEGIN TRANSACTION

   INSERT INTO 
      dbo.Usuarios(usu_ds, usu_dt_create, usu_dt_lst_log, usu_ds_senha, usu_ds_email)     
   VALUES(@usu_ds, @usu_dt_create, @usu_dt_lst_log, @usu_ds_senha, @usu_ds_email)

   COMMIT TRANSACTION
END

如果您可以事先检查用户的存在,那么启动事务只是为了回滚它真的没有意义。

另外:如果列usu_ds应该是唯一的,您也应该对其施加 UNIQUE 约束!这样,如果有人设法尝试以其他方式(除了通过您的存储过程)插入用户,您将收到错误(违反约束):

ALTER TABLE dbo.Usuarios
  ADD CONSTRAINT UX_usu_ds UNIQUE(usu_ds)
于 2010-08-11T20:52:32.050 回答
0

@varCheckUser <> NULL 将始终返回 FALSE。

您必须使用 @varChechUser IS NOT NULL

于 2010-08-11T20:54:24.917 回答
0

@varCheckUser 永远不能为空。它总是有一个整数的字符串表示形式的值。

代替:

if (@varCheckUser <> null)

做:

if (@varCheckUser = 0)
于 2010-08-11T20:50:00.187 回答