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ではないことを確認します

なぜトランが必要なのですか?このようなことをするだけです

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をaにするprimary keyか、tを追加することをお勧めします。そうすれunique constrainば、ユーザー名を既存のものに更新したり、誤ってSSMSを使用してユーザー名を既にテーブルにあるものに変更したりすることはできません。

于 2010-08-11T20:49:30.873 に答える
1

それほど複雑にする必要はありません。

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

このコードは、同時実行の問題も完全に解決します(条件付き挿入/更新の競合状態を参照)。

于 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にすることはできません。常に整数の文字列表現である値を持ちます。

それ以外の:

if (@varCheckUser <> null)

行う:

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

@varCheckUser<>NULLは常にFALSEを返します。

@varChechUser ISNOTNULLを使用する必要があります

于 2010-08-11T20:54:24.917 に答える