1
votes

Rechercher la valeur d'un enregistrement et le renvoyer à partir d'une procédure stockée

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 commentaires

Pourquoi utilisez-vous EXISTS () dans la clause WHERE ? 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 null


Vous avez également un point-virgule dans END; qui est erroné ici et vous n'avez pas du tout besoin du IF , simplifiez-vous simplement et définissez la valeur par défaut de votre variable sur 1234.


3 Réponses :


2
votes

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

    li>
  • 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;


0 commentaires

2
votes

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

Voir Renvoyer les données d'une procédure stockée


0 commentaires

0
votes

É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; 


0 commentaires