J'ai créé une procédure stockée qui accepte la valeur d'un élément unique de ma table et la recherche dans cette table. S'il existe, renvoyez la valeur de la colonne de clé primaire de cette ligne. S'il n'existe pas, renvoyez simplement 1234 pour le moment à des fins de test.
C'est ainsi que je l'ai écrit:
EXEC MyTestSP 'ewedweweewe';
et c'est pour tester comment je l'appelle :
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;
mais il renvoie toujours ceci:
La procédure a tenté de renvoyer un état NULL, ce qui n'est pas autorisé. Un statut de 0 sera renvoyé à la place.
Qu'est-ce que je fais de mal ici?
3 Réponses :
Deux choses.
Votre si la vérification était erronée. Vous étiez en train de vérifier que @ExID au lieu de @ExIDPK et que @ExID n'est pas nullable en fonction de votre définition de proc
Je vous suggère de changer la logique exist en une clause where plus simple également
voir le code ci-dessous
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;
En regardant votre procédure, vous déclarez la variable comme DECLARE @ExIDPK INT; , donc la valeur par défaut est NULL . Cela fait que votre SP renvoie NULL si la valeur transmise n'existe pas dans votre table, et c'est pourquoi vous obtenez ce message.
De plus, il n'est pas nécessaire d'utiliser EXISTS () dans la clause where, puisque vous avez le paramètre, une simple vérification fera le travail. Et vous avez un point-virgule supplémentaire dans le END du 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;
qui est faux, et vous ne le faites pas besoin d'un IF du tout, faites-le simplement comme
IF @ExID IS NOT NULL -- you are checking the wrong variable here too
BEGIN
RETURN @ExIDPK;
END;
ELSE
BEGIN
RETURN 1234;
END;--This one
Cela garantira que votre variable ne sera jamais NULL , car vous définissez la valeur par défaut qui ne changera pas si votre requête ne renvoie aucune ligne (0 ligne).
Enfin, je recommanderais d'utiliser un paramètre OUTPUT (ou même un SELECT) au lieu d'utiliser le RETURN code.
Les codes de retour sont couramment utilisés dans les blocs de contrôle de flux au sein des procédures pour définir la valeur du code de retour pour chaque situation d'erreur possible
Étant donné que la question a été posée en fonction de la compréhension du mécanisme de renvoi d'une valeur, je vais publier cela comme un mécanisme préféré. En règle générale, les codes de retour / valeurs de retour sont réservés pour les codes d'erreur avec 0 comme succès et non-0 pour autre chose que succès (avec l'exception notable étant SQL Server Agent run_status.
L'exemple de code ci-dessous vous permettra de tester différents scénarios :
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;
Pourquoi utilisez-vous
EXISTS ()dans la clauseWHERE? et pourquoi ne sélectionnez-vous pas simplement le PK ou n'utilisez pas un paramètre OUTPUT?Je veux dire, vous utilisez:
IF @ExID IS NOT NULL, et vous savez que ce n'est pas nul parce que vous lui donnez une valeur. Cela ne signifie pas que la valeur que vous lui avez donnée a une correspondance sur la table dbo.ExIDs ... donc @ExIDPK peut être un nullVous avez également un point-virgule dans
END;qui est erroné ici et vous n'avez pas du tout besoin duIF, simplifiez-vous simplement et définissez la valeur par défaut de votre variable sur 1234.