2009-10-14 7 views
0

J'ai un travail qui effectue plusieurs vérifications de validation sur des lignes dans plusieurs tables d'une base de données. Si la vérification échoue, elle enregistre l'échec dans une table. Les informations consignées incluent le nom de la table, une valeur uniqueidentifier de la ligne ayant échoué, la vérification de l'échec et le travail en cours d'exécution. Voici la définition de table simplifiée du journalFonction TSQL pour renvoyer le nombre de lignes dans un jeu de résultats à partir d'une fonction

CREATE TABLE [tblSY_ValidationFieldFailures](
    [pkValidationFieldFailure] [int] IDENTITY(1,1) NOT NULL, 
    [fkJobID] [int] NOT NULL, 
    [fkValidationFieldFailureType] [int] NOT NULL, 
    [TableName] nvarchar(128), 
    [TableUniqueIdentifier] [nvarchar](100) NULL) 

Je voudrais écrire une fonction qui renvoie le nombre de lignes ont échoué donné une certaine table et ID de tâche (à savoir fnGetNumberOfFailedRows (@JobID, @TableName)). J'ai essayé quelque chose de semblable au suivant:

CREATE FUNCTION fnGetNumberOfRowsThatFailedValidationCheck 
(
    @pkJobID int, 
    @TableName nvarchar(128) 
) 
RETURNS int 
AS 
BEGIN 
    -- Declare the return variable here 
    DECLARE @NumFailedRows int 

    Select fkJobID, 
      TableUniqueIdentifier, 
      TableName 
    From tblSY_ValidationFieldFailures 
     Where [email protected] And [email protected] 
        Group By fkJobID, TableName, TableUniqueIdentifier 

    SET @NumFailedRows = @@ROWCOUNT 

    RETURN @NumFailedRows  
END 

Mais bien sûr, vous ne pouvez pas avoir cette instruction Select dans une fonction. Existe-t-il un moyen de faire ce que je veux dans une fonction ou est-ce que je dois faire la route de la procédure stockée?

Répondre

3

Cela devrait le faire pour vous:

CREATE FUNCTION fnGetNumberOfRowsThatFailedValidationCheck 
    ( 
    @pkJobID int,  
    @TableName nvarchar(128) 
    ) 
RETURNS int 
AS 

BEGIN 

-- Declare the return variable here 
DECLARE @NumFailedRows int 

SELECT @NumFailedRows = count(*) 
FROM (
    Select 
     fkJobID,    
     TableUniqueIdentifier,    
     TableName 
    From tblSY_ValidationFieldFailures  
    Where [email protected] 
    And [email protected] 
    Group By fkJobID, TableName, TableUniqueIdentifier 
    ) a 

RETURN @NumFailedRows 

END 
+0

Merci cela a fonctionné. J'ai essayé ceci avant sans l'alias et il a eu une erreur de syntaxe. Savez-vous pourquoi le a est nécessaire à la fin? –

+0

Content de pouvoir aider. Je ne peux pas dire exactement pourquoi il y a un besoin pour un alias, sauf pour dire que tous les champs doivent être capables d'être pleinement qualifiés (la plupart du temps, le moteur gère cela pour vous), et sans nom pour le dérivé table/resultset, vous n'avez pas de nom pour la source des champs référencés. Je devine juste, cependant. –

4

Vous pouvez utiliser un compte (*) déclaration dans votre sélection et affecter cette bien, tels que:

CREATE FUNCTION fnGetNumberOfRowsThatFailedValidationCheck 
(
    @pkJobID int, 
    @TableName nvarchar(128) 
) 
RETURNS int 
AS 
BEGIN 
-- Declare the return variable here 
DECLARE @NumFailedRows int 

Select @NumFailedRows = count(*) 
From tblSY_ValidationFieldFailures 
    Where [email protected] And [email protected] 
       Group By fkJobID, TableName, TableUniqueIdentifier 

--SET @NumFailedRows = @@ROWCOUNT 

RETURN @NumFailedRows  
END 
+0

Malheureusement, cela va juste me donner le compte du nombre de tests différents une ligne particulière a échoué; par exemple. si UniqueIdentifier = 1 et fkJobID = 1 et TableName = 'table1' et que cette ligne a échoué fkValidationFieldFailureType 1, 6 et 7 Count (*) retournera 3. Fondamentalement, cela retourne un nombre pour chaque ligne qui a échoué à un test –

+0

Vous devez enveloppez-le de sorte que COUNT (*) soit le nombre de groupes et non le nombre de chaque groupe. –

1

Dans SQL Server 2008 et plus tard, ajoutez COUNT (*) OVER() comme l'un des noms de colonne dans votre requête et qui sera rempli avec le nombre total de lignes retournées. Il est répété dans chaque rangée mais au moins la valeur est disponible. La raison pour laquelle de nombreuses autres solutions ne fonctionnent pas est que, pour les jeux de résultats très volumineux, vous ne connaîtrez pas le total avant d'avoir itéré toutes les lignes ce qui n'est pas pratique dans la plupart des cas. Cette technique vous donne le nombre total après avoir appelé le premier IDataReader.Read(), par exemple.

select COUNT (*) OVER() comme TOTAL_ROWS ... de ...

Questions connexes