找到记录的值,然后将其从存储过程中返回

时间:2019-01-09 20:08:34

标签: sql sql-server tsql

我创建了一个存储过程,该存储过程从表中接受唯一项的值并在该表中搜索它。如果存在,则返回该行的主键列的值。如果它不存在,请立即返回1234进行测试。

这就是我写的方式:

CREATE PROCEDURE dbo.MyTestSP
    @ExID VARCHAR(64)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @ExIDPK INT;

    SELECT  @ExIDPK = ExPK
    FROM 
        dbo.EXIDs
    WHERE 
        EXISTS(SELECT 1 FROM dbo.EXIDs WHERE ExID = @ExID);

    IF @ExID IS NOT NULL
    BEGIN
        RETURN @ExIDPK;
    END;
    ELSE
    BEGIN
        RETURN 1234;
    END;
END;

这是为了测试我的称呼方式:

EXEC MyTestSP 'ewedweweewe';

但它总是返回此:

  

过程试图返回状态NULL,这是不允许的。而是返回状态0。

我在这里做什么错了?

3 个答案:

答案 0 :(得分:2)

事物的结合。

  • 您的检查是否错误。您正在检查@ExID而不是@ExIDPK,并且根据您的proc定义,@ExID不能为空

  • 我建议您也将exist逻辑也更改为更简单的where子句

请参见下面的代码

CREATE PROCEDURE dbo.MyTestSP
    @ExID VARCHAR(64)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @ExIDPK INT;

    SELECT  @ExIDPK = ExPK
    FROM 
        dbo.EXIDs
    WHERE ExID = @ExID;

        RETURN ISNULL(@ExIDPK,1234);

END;

答案 1 :(得分:2)

根据您的过程,将变量声明为DECLARE @ExIDPK INT;,因此默认值为NULL。如果传递的值在表中不存在,则SP将返回NULL,这就是为什么收到此消息的原因。

此外,由于您有参数,因此无需在where子句中使用EXISTS(),只需执行简单的检查即可。并且END的{​​{1}}中有一个多余的分号

IF

这是错误的,您根本不需要IF @ExID IS NOT NULL -- you are checking the wrong variable here too BEGIN RETURN @ExIDPK; END; ELSE BEGIN RETURN 1234; END;--This one ,只需简单一点即可

IF

这将确保您的变量永远不会为CREATE PROCEDURE dbo.MyTestSP @ExID VARCHAR(64) AS BEGIN SET NOCOUNT ON; DECLARE @ExIDPK INT = 1234; --Will ensure your variable never be NULL SELECT @ExIDPK = ExPK FROM dbo.EXIDs WHERE ExID = @ExID; RETURN @ExIDPK; END; ,因为您设置了默认值,如果查询不返回任何行(0行),该默认值将保持不变。

最后,我建议不要使用NULL代码,而是使用OUTPUT参数(甚至是SELECT)。

  

程序中的流程控制块中通常使用返回码来为每种可能的错误情况设置返回码值

请参见 Return Data from a Stored Procedure

答案 2 :(得分:0)

由于这个问题是基于对返回值的机制的理解而提出的,因此,我将其更多地发布为首选的机制。通常,返回码/返回值是为错误代码保留的,错误代码为0,成功代码为非0(非0表示成功)(值得注意的例外是SQL Server代理run_status。

下面的代码示例将允许您测试不同的情况:

if object_id(N'[test].[table_01]', N'U') is not null
  drop table [test].[table_01];

go

create table [test].[table_01]
  (
     [id]      [int] identity(1, 1) not null,
          constraint [test__table_01__id__pk] primary key clustered([id])
     , [value] varchar(64)
  );

go

insert into [test].[table_01]
            ([value])
values      ('red'),
            ('green'),
            ('blue');

go

if object_id(N'[test].[get__name__id]', N'P') is not null
  drop procedure [test].[get__name__id];

go

create procedure [test].[get__name__id] @value varchar(64)
                                        , @id  [int] = null output
as
  begin
      set transaction isolation level read uncommitted;
      set NOCOUNT on;

      select @id = [id]
      from   [test].[table_01]
      where  [value] = @value;
  end;

go

--
declare @pk      [int]= null
        , @value [varchar](64)='test';

execute [test].[get__name__id]
  @value=@value
  , @id=@pk output;

if @pk is not null
  begin
      select @pk      as [primary_key__for__value]
             , @value as [value];
  end;
else
  begin
      select 'No primary key found for value ' + @value;
  end;