让我们以基本场景为例,只有在数据库中不存在用户名的情况下,我才想在用户注册期间插入一条记录。
我的问题是,您将创建 2 个单独的存储过程并对数据库进行 2 次调用,一次检查用户名是否存在,第二次调用实际插入数据库,还是创建一个存储过程并在其中编写两个查询?
如果您创建一个存储过程,那么我的第二个问题应该从存储过程中实际返回什么?我通常从存储过程中返回硬编码数字,然后检查内部代码。这是一个好习惯吗?
让我们以基本场景为例,只有在数据库中不存在用户名的情况下,我才想在用户注册期间插入一条记录。
我的问题是,您将创建 2 个单独的存储过程并对数据库进行 2 次调用,一次检查用户名是否存在,第二次调用实际插入数据库,还是创建一个存储过程并在其中编写两个查询?
如果您创建一个存储过程,那么我的第二个问题应该从存储过程中实际返回什么?我通常从存储过程中返回硬编码数字,然后检查内部代码。这是一个好习惯吗?
此操作最终需要是“原子的” - 检查不能与实际创建分离,否则您可能会遇到并发问题。虽然您可以通过两个或多个 SP 的事务和锁定来处理其中的一些问题,但恕我直言,最好的方法是使用一个 SP 并在插入发生的同时(在同一条语句中)执行检查。
我将返回一个包含插入用户的完整记录的记录集,如果存在名称冲突,则会引发错误。
我将执行一个存储过程,该过程将返回新插入用户的 ID,如果没有插入则返回 -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 注入攻击。
MERGE
声明可能会有所帮助。假设MERGE
是有条件的INSERT
/ UPDATE
。在单个语句中,INSERT
如果它不存在,您可以新用户,或者UPDATE
如果存在,您可以新用户。
正如其他人所写:存储过程比动态SQL要好得多。裹MERGE
成CREATE PROCEDURE
.
在现实世界中,您的应用程序/网络应用程序中的用户交互/工作流程会告诉您是否需要一两个程序。
情景一)
在场景 A 中,MERGE
为条件INSERT
/做UPDATE
。
场景 B)
在场景 B 中,您可以检查登录是否存在,然后在块中执行INSERT
或(更好)执行。您可以在块中使用有用的消息/状态 - 因此您可以通过从 SQL 中抛出“异常”(而不是返回参数)并在应用程序代码中捕获它来报告创建帐户的问题。这种逻辑在编码中可能更有用。INSERT
TRY .. CATCH
RAISERROR
CATCH