web-dev-qa-db-fra.com

Renvoyer les jeux d'enregistrements de la procédure stockée uniquement s'ils contiennent des lignes

J'ai une procédure stockée qui renvoie plusieurs jeux d'enregistrements à utiliser dans une application. Parfois, certains de ces jeux d'enregistrements sont vides.

Je voudrais réduire les frais généraux et ne renvoyer que ceux qui ont 1 ou plusieurs lignes.

Ma question est - Comment puis-je renvoyer uniquement les jeux d'enregistrements qui ont des lignes?

L'application attend simplement 0 ou plusieurs jeux d'enregistrements, passe en boucle dans chacun d'eux et les imprime.

Je sais que je peux les ignorer dans le code d'application, mais j'essaie de les empêcher d'être retournés, s'ils sont vides.

La procédure est aussi simple que cela:

CREATE PROCEDURE bfsp_PROC_NM
AS 

    BEGIN

        SELECT * FROM TABLE_1

        SELECT * FROM TABLE_2

        SELECT * FROM TABLE_3

        RETURN  

    END
GO

Dans la procédure actuelle, certaines requêtes sont coûteuses, donc je ne veux pas avoir à tester la requête, puis si elle retourne une ligne ou plus, exécutez-la à nouveau ... car ce serait trop cher.

3
GWR

J'ai une procédure stockée qui renvoie plusieurs jeux d'enregistrements à utiliser dans une application. Parfois, certains de ces jeux d'enregistrements sont vides.

Je voudrais réduire les frais généraux et ne renvoyer que ceux qui ont 1 ou plusieurs lignes.

C'est une terrible idée. Comment l'application va-t-elle savoir quel jeu de résultats elle traite? Les procédures stockées doivent avoir un ensemble fixe de formes d'ensemble de résultats.

Cela étant dit, pour ce faire, chargez les résultats dans les tables temporaires, puis sélectionnez-les à partir de ceux s'ils ne sont pas vides.

par exemple

CREATE PROCEDURE bfsp_PROC_NM
AS 

    BEGIN
        SELECT * 
        into #result1
        FROM TABLE_1
        if @@rowcount > 0
          select * from #result1

        SELECT * 
        into #result2
        FROM TABLE_2
        if @@rowcount > 0
          select * from #result2

        SELECT * 
        into #result3
        FROM TABLE_3
        if @@rowcount > 0
          select * from #result3

    END
GO

J'aime que mon code soit prévisible, si vous retournez toujours X ensembles de données, vous pouvez programmer cela dans votre application et vous savez toujours à quoi vous attendre. Ce n'est peut-être pas la meilleure idée de filtrer les ensembles.

Cependant, une option pourrait être de vérifier si la table/sélection que vous exécutez renvoie des lignes, si elles renvoient l'ensemble, sinon vous l'ignorez. Cela a évidemment un peu de surcharge car vous devez le spécifier pour chaque jeu de résultats que vous retournez.

Exemple comme vu dans ce code:

CREATE TABLE dbo.ReturnSet1( Id INT IDENTITY,NickName VARCHAR(256) )
CREATE TABLE dbo.ReturnSet2 (Id INT IDENTITY,NickName VARCHAR(256) )

INSERT INTO ReturnSet1
VALUES('TestRecord')

GO
CREATE PROCEDURE dbo.TestReturnSet
AS
BEGIN

    IF EXISTS ( SELECT 1 FROM dbo.ReturnSet1 )
    BEGIN
        SELECT NickName
         FROM dbo.ReturnSet1
    END

    IF EXISTS ( SELECT 1 FROM dbo.ReturnSet2 )
    BEGIN
        SELECT NickName
         FROM dbo.ReturnSet2
    END


END
GO

EXEC dbo.TestReturnSet

DROP TABLE dbo.ReturnSet1
DROP TABLE dbo.ReturnSet2
DROP PROCEDURE dbo.TestReturnSet
4
Yannick Liekens

En supposant que les données des trois tables ont une structure similaire, vous pouvez insérer les données dans une seule table temporaire, puis demander à votre procédure de renvoyer un jeu de résultats avec toutes les lignes disponibles:

create procedure one_result_set

    # create temp table to hold all result rows
    create temporary table temp_one {
        table_name char(50),  # this field indicates source table
        field1 type1,
        ...
        fieldN typeN
    }

    # insert rows from first table into temp table 
    insert into temp_one
    select 'table1', t.* from table1 t;

    # insert rows from second table into temp table 
    insert into temp_one
    select 'table2', t.* from table2 t;

    # insert rows from third table into temp table 
    insert into temp_one
    select 'table3', t.* from table3 t;

    # finally, return all the fetched rows as a single result set
    select * from temp_one;

end procedure$$

Le jeu de résultats renvoyé peut toujours être vide - si aucune des trois tables source n'a de données à renvoyer - mais vous pouvez le déterminer à partir des métadonnées.

Si les tables source ne pas partagent une structure similaire, je dois être d'accord avec les réponses précédentes - renvoyer un nombre variable d'ensembles de résultats est une mauvaise idée. Si les tables source sont différentes et que votre procédure renvoie moins de trois jeux de résultats, vous devrez vérifier la liste des champs pour chaque jeu de résultats juste pour comprendre ce qui manquait avant de pouvoir traiter les données.

1
Sam