存储过程参数类型验证

时间:2017-07-11 14:28:47

标签: sql-server vb.net stored-procedures

执行存储过程的网络代码

        Dim cmd As New SqlCommand("get_list_of_users", connection)
        Dim table As New DataTable
        Dim adapter As New SqlDataAdapter
        Dim param As New SqlParameter("@TypeID", SqlDbType.Int)

        param.Direction = ParameterDirection.Input
        param.Value = typeID
        cmd.Parameters.Add(param)

        cmd.CommandType = CommandType.StoredProcedure
        adapter.SelectCommand = cmd
        adapter.Fill(table)

不幸的是,存储过程中的 @TypeID 参数未配置为整数而是,您可以想象后果和我们不得不浪费调试它的时间。

有没有办法配置“更严格”模式将参数传递给存储过程,以便在定义的数据类型与存储过程定义不匹配时引发异常?

全部谢谢

2 个答案:

答案 0 :(得分:1)

我不是说这很好,但是,如果你真的想检查,你可以在存储过程中完成。 下面是一个快速示例,如果您愿意,可以为您提供一些可以实现的功能。在C#中将int转换为string,并将其作为参数传递,然后将其转换回来,以确保两者匹配。在下面,我已经添加了BIT,因此引发了错误。

CREATE PROCEDURE dbo.pTypeTest

    @int BIT            ,
    @str NVARCHAR(10)
AS
BEGIN

    SET NOCOUNT ON;

    DECLARE @bitTheSame     BIT             ,
            @intBaseType    NVARCHAR(20)    ,   
            @strBaseType    NVARCHAR(20);

    SELECT @intBaseType = CAST(SQL_VARIANT_PROPERTY(@int,'BaseType') AS NVARCHAR(20));
    SELECT @strBaseType = CAST(SQL_VARIANT_PROPERTY(@str,'BaseType') AS NVARCHAR(20));

    SELECT @bitTheSame = CASE WHEN CAST(@int AS NVARCHAR(10)) <> @str THEN 0 ELSE 1 END;

    IF(@bitTheSame = 0)
        BEGIN
            DECLARE @message NVARCHAR(200);
            SELECT @message = 'Something went wrong, @str: ' + @str + ' does not match @int: '+CAST(@int AS NVARCHAR(10))+' when it has been converted. @str is a '+@strBaseType+' and @int is a '+@intBaseType;
            RAISERROR(@message,16,1);
        END
    IF(@bitTheSame = 1)
        BEGIN
            PRINT 'Ok';
        END

END

示例:

EXEC dbo.pTypeTest @int = 1000,@str = '1000';

引发错误:

  

Msg 50000,Level 16,State 1,Procedure pTypeTest,Line 24 Something   出错了,@ str:1000与@int:1不匹配   转换。 @str是一个nvarchar而@int是有点

答案 1 :(得分:0)

使用对参数类型进行隐式转换的参数值调用过程是完全合法的。

但是你可以(而且应该)远离手写存储过程调用。而是使用例如T4模板生成基于SQL Server元数据的代码。

EG为您提供过程和参数类型的查询将如下所示:

select object_name(m.object_id) ObjectName, 
       SCHEMA_NAME(o.schema_id) SchemaName,
       o.type_desc ObjectTypeDesc,
       p.name ParameterName,
       t.name TypeName,
       p.precision,
       p.scale,
       p.max_length,
       p.default_value,
       p.is_output     
from 
sys.sql_modules m
join sys.objects o
  on o.object_id = m.object_id
join sys.parameters p
  on m.object_id = p.object_id
join sys.types t
  on p.system_type_id = t.system_type_id
order by o.object_id, p.parameter_id