我需要一些帮助来完成这个程序:
如果没有其他人使用相同的NAME,它应该尝试插入一个新用户。
如果已有用户,则应该回滚其他提交。但它不起作用,无论如何都会提交。
有什么建议吗?
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
答案 0 :(得分: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设为primary key
或添加unique constrain
t可能是个好主意,这样任何人都无法将用户名更新为存在的内容,没有人可以错误地使用SSMS并更改用户名到表格中已有的东西
答案 1 :(得分:1)
您需要更改支票以使用@varCheckUser = 0
- 或者更好的是,将其更改为使用IF EXISTS
,并且只有在该用户尚不存在时才开始插入值的事务:< / p>
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约束!这样,如果有人设法尝试以其他方式插入用户(除了通过存储的proc),你就会收到错误(违反约束):
ALTER TABLE dbo.Usuarios
ADD CONSTRAINT UX_usu_ds UNIQUE(usu_ds)
答案 2 :(得分: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
此代码也完全解决了您的任何并发问题(请参阅Conditional Insert/Update Race Condition)。
答案 3 :(得分:0)
@varCheckUser永远不能为空。它将始终具有一个整数的字符串表示形式的值。
而不是:
if (@varCheckUser <> null)
执行:
if (@varCheckUser = 0)
答案 4 :(得分:0)
@varCheckUser&lt;&gt; NULL将始终返回FALSE。
您必须使用@varChechUser IS NOT NULL