让我们假设只有在数据库中不存在用户名的情况下我才想在用户注册期间插入记录的基本场景。
我的问题是你是否会创建2个单独的存储过程并对数据库进行2次调用,一次用于检查用户名是否存在,第二次用于实际插入数据库,还是创建一个存储过程并写入两个查询只在里面?
如果你创建了一个存储过程,那么我的第二个问题你应该从存储过程中实际返回什么?我通常从存储过程返回硬编码数字,然后检查内部代码。这是一个好习惯吗?
答案 0 :(得分:4)
此操作最终需要“原子” - 检查不能脱离实际创建,否则可能会遇到并发问题。虽然您可以使用事务处理其中一些并锁定两个或更多SP,但最好的方法是使用一个SP并在插入时同时执行检查(在同一语句中)。
我将返回一个记录集,其中包含插入用户的完整记录,如果存在名称冲突,则会引发错误。
答案 1 :(得分:3)
我将执行一个将返回新插入用户的ID的存储过程,如果没有插入,则返回-1
答案 2 :(得分:1)
您可以执行以下操作:
CREATE PROCEDURE AddNewUser
(
@Username VARCHAR(30)
, @Password VARCHAR(30)
, @UserExists BIT OUTPUT
)
AS
-- CHECK IF THE USER EXISTS:
DECLARE @RowCount INT
SELECT @RowCount = COUNT(*)
FROM Users
WHERE Username = @Username
IF (@RowCount > 0)
BEGIN
SET @UserExists = 1
END
ELSE
BEGIN
SET @UserExists = 0
INSERT INTO Users
(Username, [Password])
VALUES
(@Username, @Password)
END
GO
然后在应用程序中你可以使用@UserExists参数,1表示用户已经存在,0表示用户不存在并且已经创建。
对于良好实践,您应该使用存储过程而不是内联SQL,因为您将容易受到SQL注入攻击。
答案 3 :(得分:0)
MERGE
声明可能会有所帮助。我们说MERGE
是有条件的INSERT
/ UPDATE
。在单一语句中,如果新用户不存在,则可以INSERT
新用户,如果存在则只有UPDATE
。
正如其他人所写:存储过程比动态SQL好得多。将MERGE
换行到CREATE PROCEDURE
。
在现实世界中,app / webapp中的用户交互/工作流程会告诉您是否需要一个或两个程序。
情景A)
在方案A中,对条件MERGE
/ INSERT
执行UPDATE
。
情景B)
在方案B中,您可以检查登录是否存在,然后在INSERT
阻止中INSERT
或(更好)执行TRY .. CATCH
。您可以在RAISERROR
块中使用有用的消息/状态执行CATCH
- 这样您就可以通过从SQL(而不是返回参数)抛出“异常”并在应用程序代码中捕获它来报告创建帐户的问题。这种逻辑在编码中可能更有用。