Sql 查找记录的值并从存储过程返回该值
我创建了一个存储过程,它从我的表中接受唯一项的值,并在该表中搜索它。如果存在,返回该行主键列的值。如果它不存在,那么现在就返回1234进行测试 我就是这样写的:Sql 查找记录的值并从存储过程返回该值,sql,sql-server,tsql,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 WHE
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的状态
我做错了什么?两件事
- 如果你的支票错了。您正在检查
而不是@ExID
,@ExIDPK
根据您的过程定义不能为空@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;
两件事
- 如果你的支票错了。您正在检查
而不是@ExID
,@ExIDPK
根据您的过程定义不能为空@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;
查看您的过程,将变量声明为
declare@ExIDPK INT
,因此默认值为NULL
。如果传递的值在表中不存在,则SP将返回NULL
,这就是您收到此消息的原因
此外,在where子句中不需要使用EXISTS()
,因为您有参数,只需进行简单的检查即可。如果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
这是错误的,您根本不需要,如果
,只需将其简化为
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;
这将确保变量永远不会为NULL
,因为您设置了默认值,如果查询不返回任何行(0行),则默认值不会更改
最后,我建议使用一个输出参数(甚至一个SELECT),而不是使用RETURN
code
返回码通常用于控制过程中的流块,以设置每个可能错误情况的返回码值
请参见查看您的过程,将变量声明为
declare@ExIDPK INT
,因此默认值为NULL
。如果传递的值在表中不存在,则SP将返回NULL
,这就是您收到此消息的原因
此外,在where子句中不需要使用EXISTS()
,因为您有参数,只需进行简单的检查即可。如果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
这是错误的,您根本不需要,如果
,只需将其简化为
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;
这将确保变量永远不会为NULL
,因为您设置了默认值,如果查询不返回任何行(0行),则默认值不会更改
最后,我建议使用一个输出参数(甚至一个SELECT),而不是使用RETURN
code
返回码通常用于控制过程中的流块,以设置每个可能错误情况的返回码值
请参见,因为这个问题是在理解返回值的机制的基础上提出的,所以我将把它作为一种更可取的机制来发布。通常,返回代码/返回值是为错误代码保留的,0表示成功,非0表示成功以外的其他内容(值得注意的例外是SQL Server代理运行状态) 下面的代码示例将允许您测试不同的场景:
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;
因为这个问题是在理解返回值的机制的基础上提出的,所以我将把它作为一种更可取的机制来发布。通常,返回代码/返回值是为错误代码保留的,0表示成功,而非0表示成功(值得注意的例外是SQL Server代理运行状态 下面的代码示例将允许您测试不同的场景:
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;
使用
EXISTS()的原因
在WHERE
子句中?为什么不选择PK或使用输出参数?我的意思是,如果@ExID不为NULL,您知道它不为NULL,因为您给它一个值。这并不意味着您给它的值在dbo.ExIDs表上有匹配项……所以@ExIDPK可能为NULL,您也有一个END;
中的分号是错误的,您根本不需要,如果
,只需简单一点,并将变量的默认值设置为1234。为什么要使用EXISTS()
在WHERE
子句中?为什么不选择PK或使用输出参数?我的意思是,如果@ExID不为NULL,您知道它不为NULL,因为您给它一个值。这并不意味着您给它的值在dbo.ExIDs表上有匹配项……所以@ExIDPK可能为NULL,您也有一个END;
中的分号是错误的,您根本不需要,如果
,只需简化并将变量的默认值设置为1234即可。