IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

@@ FETCH_STATUS = -2 [2012]


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Juillet 2009
    Messages : 43
    Par défaut @@ FETCH_STATUS = -2
    Bonjour a tous,

    Il est rare que je fasse appel a la communauté pour me sortir d'un soucis, en général je trouve ce qu'il me faut sur le net mais la j'ai fais choux blanc.

    Sur mes plateformes principales (SQL2012 SP3, edition Entreprise, Groupe de disponibilité AlwaysOn) je rencontre de manière aléatoire un problème étrange. Afin d'appliqué un traitement particulier a l'ensemble des bases d'un de mes groupe de disponibilité j'utilise des jobs appelant un curseur listant les bases a traité et générant dynamiquement le code a executer pour chaque base. En voici un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    DECLARE @errnum int
    DECLARE @errmess nvarchar(4000)
    DECLARE @ret int
    DECLARE @NbBaseTheo int
    DECLARE @NbBaseTrt int
    DECLARE @NbBaseErr int
    DECLARE @IamThePrimary Int
    DECLARE @sqlorder nvarchar(max)
    DECLARE @DBNAME sysname
    DECLARE CUR_DB CURSOR
    FOR select name from sys.databases
    where name not in ('master', 'msdb', 'tempdb', 'model', 'ANNUAIRE_ZEPHYR')
    and name not like '%OFFLINE%' and name not like 'META%' and name not like 'LOADGEN%'
    order by name
     
    BEGIN
     
    SET @IamThePrimary = 0
    SELECT @IamThePrimary = 1
    FROM [master].[sys].[dm_hadr_availability_replica_states] as DMHA
    inner join [master].[sys].[availability_replicas] as SYAR
    	ON DMHA.replica_id = SYAR.replica_id
    WHERE DMHA.[role] = 1
    AND SYAR.[replica_server_name] = @@SERVERNAME
     
    IF (@IamThePrimary = 1)
    BEGIN
    select @NbBaseTheo=count(name) from sys.databases where name not in ('master', 'msdb', 'tempdb', 'model', 'ANNUAIRE_ZEPHYR')
    and name not like '%OFFLINE%' and name not like 'META%' and name not like 'LOADGEN%'
    set @NbBaseTrt = 0
    set @NbBaseErr = 0
    PRINT 'Debut traitement ' + cast(@NbBaseTheo as varchar) +' bases a traiter'
    OPEN CUR_DB
    FETCH NEXT FROM CUR_DB
    INTO @DBNAME
    WHILE @@FETCH_STATUS = 0 
    Begin Try
    BEGIN
    SET @sqlorder= 'IF EXISTS (SELECT * FROM '+@DBNAME+'.sys.objects WHERE object_id = OBJECT_ID(N''['+@DBNAME+'].[data].[PS_Refresh_Ofr_Cde_EnCours]'') AND type in (N''P'', N''PC''))
    BEGIN
    exec ['+@DBNAME+'].[data].[PS_Refresh_Ofr_Cde_EnCours]
    END'
    SET @ret = 0
    exec @ret = sp_executesql @sqlorder
    IF @ret =0 
    BEGIN
    PRINT @sqlorder+'  ==> OK'
    set @NbBaseTrt = @NbBaseTrt +1
    FETCH NEXT FROM CUR_DB INTO @DBNAME
    END
    IF @ret <> 0 
    BEGIN
    PRINT @sqlorder+'  ==> KO'
    SET @errnum = ERROR_NUMBER();
    SET @errmess = ERROR_MESSAGE()
    PRINT @errmess
    RAISERROR(60001,17,1, @errnum, @errmess) ;
    END
    END
    END TRY
    BEGIN CATCH
    PRINT @sqlorder  + ' KO'
    set @NbBaseErr = @NbBaseErr +1
    SET @errnum = ERROR_NUMBER();
    SET @errmess = ERROR_MESSAGE() + N' Base : '+ @DBNAME ;
    RAISERROR(60001,17,1, @errnum, @errmess) ;
    FETCH NEXT FROM CUR_DB INTO @DBNAME
    END CATCH
    CLOSE CUR_DB 
    DEALLOCATE CUR_DB
    PRINT 'Etat du Fetch_Status = ' + cast(@@FETCH_STATUS as nvarchar)
    PRINT 'Fin traitement ' + cast(@NbBaseTrt as varchar) +' bases traitées, ' + cast(@NbBaseErr as varchar) + ' bases en erreur'
    SET @errmess = 'Le nombre de base a traiter etait de ' + cast(@NbBaseTheo as varchar) +' mais seul '+ cast(@NbBaseTrt+@NbBaseErr as varchar)+' l''ont été'
    IF @NbBaseTrt+@NbBaseErr <> @NbBaseTheo RAISERROR(60001,17,1, 60001, @errmess) ;
    END
    END
    Je me suis rendu compte que lors de certains lancement de ces jobs, certaines bases n'étaient pas traitées toutefois le job ne semblait rencontrer aucune erreur, ne passait jamais dans le catch et ne signalait aucun problème, j'ai donc ajouter la petite astuce finale de comptage des bases a traiter en théorie et du nombre réellement traitées et je déclenche un erreur si ils ne sont pas égaux. Cela m'aide a superviser mais pas a comprendre pourquoi toutes les bases ne sont pas traiter (de manière aléatoire, la plus part des lancements des jobs traitent correctement toutes les bases).
    J'ai donc aussi ajouter en dernier lieu l'etat du fetch status afin de comprendre pourquoi ma boucle s'arrêtait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Etat du Fetch_Status = -2 [SQLSTATE 01000]
    Fin traitement 80 bases traitées, 0 bases en erreur [SQLSTATE 01000]
    Msg 60001, Sev 17, State 1, Line 75 : Une erreur 60001 est survenue avec le texte Le nombre de base a traiter était de 91 mais seul 80 l'ont été [SQLSTATE 42000]
    J'ai donc un FETCH_STATUS à -2, d'après MSDN :
    -2 The row fetched is missing.

    Et la j'avoue que je ne sais pas du tout ce qui provoque ça. Aussi, quelqu'un peut il m'éclairer ?

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 001
    Billets dans le blog
    6
    Par défaut
    Beaucoup d'horreur dans ce code !!!!
    1) absence de ; pour terminer ses instructions
    2) absence de synthèse des commande (DECLARE, SET...)
    3) curseur ouvert en mode le plus pourri possible
    4) imbrication de boucles étranges pouvant donner des résultats aléatoire (WHILE / begin try / BEGIN !!!)
    5) mélange de chaines ASCII et UNICODE (faites précédez par N'...')
    6) utilisation de RAISERROR obsolète à remplacer par THROW
    7) il manque la fin de la phrase à "'Le nombre de base a traiter etait de ' + cast(@NbBaseTheo as varchar) +' mais seul '+ cast(@NbBaseTrt+@NbBaseErr as varchar)+' l''ont été "

    Et votre bloc try catch est mal placé puisqu'en dehors de la boucle ey donc le FETCH NEXT n'a aucun sens, si la boucle esyt terminé il va générer une erreur si erreur il y a ! Ceci expliquant le -2 de FETCH_STATUS

    Récriture :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    DECLARE @errnum int,
            @errmess nvarchar(4000),
            @ret int,
            @NbBaseTheo int,
            @NbBaseTrt int,
            @NbBaseErr int,
            @IamThePrimary Int,
            @sqlorder nvarchar(max),
            @DBNAME sysname;
     
    DECLARE CUR_DB CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY --> important pour pas bloquer !!!
       FOR 
           select name 
           from   sys.databases
           where  name not in ('master', 'msdb', 'tempdb', 'model', 'ANNUAIRE_ZEPHYR')
                   and name not like '%OFFLINE%' and name not like 'META%' and name not like 'LOADGEN%'
           order by name;
     
    BEGIN -- corps
     
    SET @IamThePrimary = 0
    SELECT @IamThePrimary = 1
    FROM   [master].[sys].[dm_hadr_availability_replica_states] as DMHA
           inner join [master].[sys].[availability_replicas] as SYAR
    	          ON DMHA.replica_id = SYAR.replica_id
    WHERE  DMHA.[role] = 1
      AND  SYAR.[replica_server_name] = @@SERVERNAME;
     
    IF @IamThePrimary = 1
    BEGIN -- condition
       SELECT @NbBaseTheo=count(name) 
       FROM   sys.databases 
       WHERE  name not in ('master', 'msdb', 'tempdb', 'model', 'ANNUAIRE_ZEPHYR')
         and  name not like '%OFFLINE%' and name not like 'META%' and name not like 'LOADGEN%';
     
       SELECT @NbBaseTrt = 0, @NbBaseErr = 0;
     
       PRINT 'Debut traitement ' + cast(@NbBaseTheo as varchar) +' bases a traiter';--###
     
       OPEN CUR_DB;
     
       FETCH CUR_DB INTO @DBNAME;
     
       WHILE @@FETCH_STATUS = 0 
       BEGIN -- boucle while
     
          BEGIN TRY
     
             SET @sqlorder = N'IF EXISTS (SELECT * FROM ' + @DBNAME + N'.sys.objects WHERE object_id = OBJECT_ID(N''[' 
                           + @DBNAME + N'].[data].[PS_Refresh_Ofr_Cde_EnCours]'') AND type in (N''P'', N''PC'')) BEGIN exec [' 
                           + @DBNAME + N'].[data].[PS_Refresh_Ofr_Cde_EnCours] END'
             SET @ret = 0;
             EXEC @ret = sp_executesql @sqlorder;
             IF @ret =0 
             BEGIN -- if
                PRINT @sqlorder+'  ==> OK' --###
                SET @NbBaseTrt = @NbBaseTrt +1
                FETCH NEXT FROM CUR_DB INTO @DBNAME
             END -- if
             IF @ret <> 0 
             BEGIN -- if
                PRINT @sqlorder+'  ==> KO' --###
                SELECT @errnum = ERROR_NUMBER(), @errmess = ERROR_MESSAGE();
                PRINT @errmess; --###
                THROW @errnum, @errmess, 1;
             END -- if
     
          END TRY
          BEGIN CATCH
     
             PRINT @sqlorder  + ' KO';
             SELECT @NbBaseErr = @NbBaseErr +1, 
                    @errnum = ERROR_NUMBER(),
                    @errmess = ERROR_MESSAGE() + N' Base : '+ @DBNAME;
             RAISERROR(60001,17,1, @errnum, @errmess) ;
          END CATCH
     
          FETCH NEXT FROM CUR_DB INTO @DBNAME
     
       END; -- boucle while
     
       CLOSE CUR_DB;
       DEALLOCATE CUR_DB;
     
       PRINT 'Etat du Fetch_Status = ' + cast(@@FETCH_STATUS as nvarchar); --###
     
       PRINT 'Fin traitement ' + cast(@NbBaseTrt as varchar) +' bases traitées, ' + cast(@NbBaseErr as varchar) + ' bases en erreur'; --###
     
       SET @errmess = 'Le nombre de base a traiter etait de ' + cast(@NbBaseTheo as varchar) +' mais seul '+ cast(@NbBaseTrt+@NbBaseErr as varchar)+' l''ont été traitées'
       IF @NbBaseTrt+@NbBaseErr <> @NbBaseTheo 
          RAISERROR(60001,17,1, 60001, @errmess) ;
    END; -- condition
     
    END; -- corps

    je donne pas mal de cours à Orsys... Peut être serait-il temps d'y aller !!!

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre averti
    Inscrit en
    Juillet 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Juillet 2009
    Messages : 43
    Par défaut
    Bonjour Monsieur Brouard,

    (ps j'ai déjà assisté a un de vos cours chez Orsys mais c'etait il y a longtemps et pas sur un sujet purement T-SQL)

    Je comprends vos remarques certaines sont en effet une honte pour moi (parfois trop pressé sans doute) mais votre code ne répond pas au problème car après test il ressort comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Etat du Fetch_Status = -1
    Fin traitement 13 bases traitées, 0 bases en erreur
    Msg*60001, Niveau*17, État*1, Ligne*91
    Une erreur 60001 est survenue avec le texte Le nombre de base a traiter était de 26 mais seul 13 l'ont été traitées
    Dans mes souvenirs (car ce code est vieux) j'avais rencontrer ce soucis d'où mon déplacement des blocs try/catch. Je vais repartir de votre code pour tenter de trouver le soucis.

  4. #4
    Membre averti
    Inscrit en
    Juillet 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Juillet 2009
    Messages : 43
    Par défaut
    Pour être exhaustif voici la log complete.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    Debut traitement 26 bases a traiter
    IF EXISTS (SELECT * FROM BC_CES_FEIGEL.sys.objects WHERE object_id = OBJECT_ID(N'[BC_CES_FEIGEL].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [BC_CES_FEIGEL].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (537*lignes affectées)
    IF EXISTS (SELECT * FROM P38_CCO_CCO_CHAUD.sys.objects WHERE object_id = OBJECT_ID(N'[P38_CCO_CCO_CHAUD].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_CCO_CCO_CHAUD].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (7306*lignes affectées)
    IF EXISTS (SELECT * FROM P38_CIF_COSSON.sys.objects WHERE object_id = OBJECT_ID(N'[P38_CIF_COSSON].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_CIF_COSSON].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (1785*lignes affectées)
    IF EXISTS (SELECT * FROM P38_CIF_SPME.sys.objects WHERE object_id = OBJECT_ID(N'[P38_CIF_SPME].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_CIF_SPME].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (2*lignes affectées)
    IF EXISTS (SELECT * FROM P38_CMM_CORSOVIA.sys.objects WHERE object_id = OBJECT_ID(N'[P38_CMM_CORSOVIA].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_CMM_CORSOVIA].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (8097*lignes affectées)
    IF EXISTS (SELECT * FROM P38_CSW_GAMA.sys.objects WHERE object_id = OBJECT_ID(N'[P38_CSW_GAMA].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_CSW_GAMA].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (53834*lignes affectées)
    IF EXISTS (SELECT * FROM P38_PERALPES.sys.objects WHERE object_id = OBJECT_ID(N'[P38_PERALPES].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_PERALPES].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
     
    (29598*lignes affectées)
    IF EXISTS (SELECT * FROM P38_PERTRONC.sys.objects WHERE object_id = OBJECT_ID(N'[P38_PERTRONC].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_PERTRONC].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
    IF EXISTS (SELECT * FROM P38_SCPR_preMig.sys.objects WHERE object_id = OBJECT_ID(N'[P38_SCPR_preMig].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [P38_SCPR_preMig].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
    IF EXISTS (SELECT * FROM PB_CMM_GARENQ.sys.objects WHERE object_id = OBJECT_ID(N'[PB_CMM_GARENQ].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [PB_CMM_GARENQ].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
    IF EXISTS (SELECT * FROM PB_CMM_PYRENEES_ORIENT.sys.objects WHERE object_id = OBJECT_ID(N'[PB_CMM_PYRENEES_ORIENT].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [PB_CMM_PYRENEES_ORIENT].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
    IF EXISTS (SELECT * FROM PB_CRA_INDUSTRIES_DEPT03.sys.objects WHERE object_id = OBJECT_ID(N'[PB_CRA_INDUSTRIES_DEPT03].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [PB_CRA_INDUSTRIES_DEPT03].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
    IF EXISTS (SELECT * FROM PB_CSW_VARIHLES.sys.objects WHERE object_id = OBJECT_ID(N'[PB_CSW_VARIHLES].[data].[PS_Refresh_Ofr_Cde_EnCours]') AND type in (N'P', N'PC')) BEGIN exec [PB_CSW_VARIHLES].[data].[PS_Refresh_Ofr_Cde_EnCours] END  ==> OK
    Etat du Fetch_Status = -1
    Fin traitement 13 bases traitées, 0 bases en erreur
    Msg*60001, Niveau*17, État*1, Ligne*91
    Une erreur 60001 est survenue avec le texte Le nombre de base a traiter etait de 26 mais seul 13 l'ont été traitées
    ainsi que le resultat de la requete du curseur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    name
    --------------------------------------------------------------------------------------------------------------------------------
    BC_CES_FEIGEL
    IndexAuditAllDB
    P38_CCO_CCO_CHAUD
    P38_CCO_CCO_CHAUD_preMig
    P38_CIF_COSSON
    P38_CIF_COSSON_preMig
    P38_CIF_SPME
    P38_CMGOP
    P38_CMM_CORSOVIA
    P38_CMM_PYRENEES_ORIENT
    P38_CSW_GAMA
    P38_EVAI
    P38_PERALPES
    P38_PERALPES_preMig
    P38_PERTRONC
    P38_SCPR
    P38_SCPR_preMig
    P38_SCPR_Purge
    PB_CMM_GARENQ
    PB_CMM_LA_PEJADE
    PB_CMM_PYRENEES_ORIENT
    PB_CMM_STBLAISE
    PB_CRA_INDUSTRIES_DEPT03
    PB_CSW_AVEYRON
    PB_CSW_VARIHLES
    traceStore
     
    (26*lignes affectées)

  5. #5
    Membre averti
    Inscrit en
    Juillet 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Juillet 2009
    Messages : 43
    Par défaut
    C'est bon j'ai trouvé,

    Un fetch de trop dans le if ret =0

    Merci pour votre aide, je vérifierais a être plus rigoureux dans mes codes et a mieux indenter pour ne pas me perdre.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. curseur et @@fetch_status
    Par ShaGaTsoin dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 19/09/2007, 02h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo