SQL存储过程参数-方法

时间:2018-11-20 14:38:26

标签: sql sql-server web-services stored-procedures architecture

我正在开发相对简单的数据库,该数据库将管理生产工厂中的用户,硬件和软件。

我不是数据库主题方面的专家。数据库附件如下:

https://i.stack.imgur.com/I0BD7.png

即使登录或特权等字段是唯一的,我也决定始终使用整数替代键。

此数据库将由许多类型的软件使用,这些软件并不总是具有不错的ORM,我决定使用StoredProcedures与DB进行交互

我的问题是关于存储过程及其参数的。例如,usp_AddUserRole可以定义如下:

IF NOT EXISTS (select * from dbo.sysobjects where id = object_id(N'[User].[usp_AddUserRole]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
EXEC
('CREATE PROCEDURE [User].[usp_AddUserRole] AS SET NOCOUNT ON')
GO

GRANT EXECUTE ON [User].[usp_AddUserRole] TO sp_executor
GO

ALTER PROCEDURE [User].[usp_AddUserRole]
    @UserID numeric(18,0), 
    @RoleID numeric(18,0) AS
SET XACT_ABORT, NOCOUNT ON

BEGIN TRY
BEGIN TRANSACTION

    INSERT INTO [User].[User_Role] (
        [UserID]
        ,[RoleID]
        )
    VALUES (
        @UserID
        ,@RoleID
        )

COMMIT TRANSACTION
END TRY

BEGIN CATCH
    IF @@trancount > 0 ROLLBACK TRANSACTION
    ;THROW
    RETURN -1
END CATCH
GO

但是在我看来这不是用户友好的。 我也可以直接通过Login和Role值执行此操作,并在存储过程中解析ID:

ALTER PROCEDURE [User].[usp_AddUserRole]
    @Login varchar(30), 
    @Role varchar(50) AS
SET XACT_ABORT, NOCOUNT ON

BEGIN TRY
BEGIN TRANSACTION

    DECLARE @UserID numeric = (SELECT UserID FROM [User].[User] WHERE [Login] = @Login)
    DECLARE @RoleID numeric = (SELECT RoleID FROM [User].[Role] WHERE [Name] = @Role)

    INSERT INTO [User].[User_Role] (
        [UserID]
        ,[RoleID]
        )
    VALUES (
        @UserID
        ,@RoleID
        )

COMMIT TRANSACTION
END TRY

BEGIN CATCH
    IF @@trancount > 0 ROLLBACK TRANSACTION
    ;THROW
    RETURN -1
END CATCH
GO

将来,将从某些Web服务中调用此存储过程。 您知道应该使用哪种方法以及为什么吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

两种方法都是可以接受的。最好有两个重构的存储过程:usp_AddUserRoleByNames,它读取ID,然后调用usp_AddUserRoleByIDs

在存储过程中按名称解析ID时:

  • 至少应将事务隔离设置为“可重复读取”,以防止修改/删除已读取的数据
  • 检查ID的NULL值
  • 检查用户角色链接是否还不存在(需要SERIALISABLE级别)
  • 不要混用返回错误代码和抛出异常方法