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 :

CTE récursive : plantage incompréhensible.


Sujet :

Développement SQL Server

  1. #1
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 792
    Points : 1 511
    Points
    1 511
    Par défaut CTE récursive : plantage incompréhensible.
    Bonsoir à tous,


    Je suis en train de faire des exercices de "style". Le sujet en question est : "Différentes écritures pour la recherche des nombres premiers"
    L'algo est celui d'Eratosthène légèrement modifié.

    Donc voici le code qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -- Creation de la table
    CREATE TABLE [dbo].[nombre]( 	[numero] [int] NULL,	[multiple] [bit] NOT NULL) ON [PRIMARY]
    GO
    --Alimentation de la table
    insert into dbo.nombre
    select top 32767 
    ROW_NUMBER() over (order by nb) as numero, 0 as multiple
     from
    	(select 0 as nb 
    	from sys.all_columns C1 ,sys.all_columns C2 ,sys.all_columns C3 ,sys.all_columns C4 ,sys.all_columns C5 ,sys.all_columns C6,sys.all_columns C7 ,sys.all_columns C8 ,sys.all_columns C9,sys.all_columns C0) as T;
    --
    -- Select qui liste les valeurs NON premières entre 3 et 32767
    --
    -- celui-ci fonctionne : 81456 lignes en 00:00:02
    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
     
    declare @limit int ;
    set @limit =32767;
    with
    	Curseur(valeurtest)
    		as (select 3 
    			union all
    			select valeurtest+2 from curseur	where valeurtest <@limit)
    	,Discriminant(Valeurmultiple, valeurtest, pas)
    		as (select valeurtest*valeurtest, valeurtest, valeurtest*2  from Curseur
    			union all
    			select Valeurmultiple + valeurtest, valeurtest, pas from Discriminant where Valeurmultiple <@limit) 
    select *  
    from discriminant D join nombre n on n.numero=D.valeurtest
    order by valeurtest desc, Valeurmultiple
    option (maxrecursion 32767);

    --
    -- Et là c'est super long et ça plante !!
    --
    -- L'instruction a été terminée. La récursivité maximale 32767 a été épuisée avant la fin de l'instruction.
    -- 0 lignes en 00:30:08

    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
    declare @limit int ;
    set @limit =32767;
    with
    	Curseur(valeurtest)
    		as (select 3 
    			union all
    			select valeurtest+2 from curseur	where valeurtest <square(@limit))
    	,Discriminant(Valeurmultiple, valeurtest, pas, Mutiple)
    		as (select valeurtest*valeurtest, valeurtest, valeurtest*2,0  from Curseur
    			union all
    			select Valeurmultiple + valeurtest, valeurtest, pas,1 from Discriminant where Valeurmultiple <square(@limit) ) 
    select D.*
    from discriminant D join nombre n on n.numero=D.valeurtest
    order by valeurtest desc, Valeurmultiple
    option (maxrecursion 32767);
    --
    --
    --
    En plus les 2 requêtes ont le même plan d'exécution.
    qui a une idée ??

  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
    21 897
    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 : 21 897
    Points : 53 135
    Points
    53 135
    Billets dans le blog
    6
    Par défaut
    Vos requêtes sont écrite de manière dégueulasse... Commencez par les récrire correctement avec une bonne indentation et vous verrez alors qu'une de vos requêtes est incohérente !

    A +

  3. #3
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 792
    Points : 1 511
    Points
    1 511
    Par défaut
    Bonjour M. Brouard,

    Merci pour la remarque sur l'incohérence.
    C'est pas bon de s'énerver avant d'aller se coucher.
    L'erreur la plus conne : Confondre square() et sqrt() ... pas bien et en plus c'est juste stupide de chercher à l'utiliser ici...

    Désolé pour l'indentation.
    Lors de la création du message le copié-collé a merdé et j'ai retapé le tout un peu trop vite.
    Merci quand même pour la relecture

    Voici le code que je souhaitais avoir : (sans besoin de générer de table préalablement)

    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
     
    declare @limite_generation int ;
    declare @limite_discriminant int;
    set @limite_generation = 65533;
     
    with
    	 -- Generation des nombre impairs de 3 à @limite_generation
    	Curseur(valeurtest)
    		as (
    			select convert(bigint,3 )
    				union all
    			select valeurtest+2 from curseur	
    			where valeurtest <(@limite_generation)
    			)
    	 -- identification des valeurs multiples pour chaque nombre impair, borné à @limite_generation
    	,Discriminant(Valeurmultiple, valeurtest, pas, Multiple) 
    		as (
    			select valeurtest*valeurtest, valeurtest, valeurtest*2,0  
    			from Curseur
    				union all
    			select Valeurmultiple +pas, valeurtest, pas,1 
    			from Discriminant 
    			where Valeurmultiple < @limite_generation
    			) 
    select min(valeurtest)
    	from discriminant D 
    	group by Valeurmultiple
    	having SUM(multiple) =0
    	option (maxrecursion 32767);

    C'est bon professeur pour l'indentation ?

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 897
    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 : 21 897
    Points : 53 135
    Points
    53 135
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par Michel.Priori Voir le message
    Bonjour M. Brouard,

    C'est bon professeur pour l'indentation ?
    C'est mieux, mais pas terrible, élève !!!! Évitez les tabulations, cela merde dans les différentes éditeurs... Évitez les parenthèses inutiles, cela rend difficilement lisible votre requête... Écrivez soit en "Camel Case" soit en minuscule soit en majuscule, mais pas avec un mélange tantôt si, tantôt là...

    Il existe au moins une dizaine d'outils en ligne pour ce faire...
    Exemple : http://www.architectshack.com/PoorMa...Formatter.ashx (intégration à SSMS)

    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
    declare @limite_generation int = 32767;
     
    with -- Generation des nombre impairs de 3 à @limite_generation
    curseur (valeurtest) as 
    (select convert(bigint, 3) 
     union  all
     select valeurtest + 2 
     from   curseur 
     where  valeurtest < @limite_generation
    ),
    -- identification des valeurs multiples pour chaque nombre impair, borné à @limite_generation
    discriminant (valeurmultiple, valeurtest, pas, multiple) as 
    (select valeurtest * valeurtest,
            valeurtest,
            valeurtest*2,
            0 
     from   curseur 
     union  all
     select valeurmultiple + pas,
            valeurtest,
            pas,
            1 
     from   discriminant 
     where  valeurmultiple < @limite_generation 
    )
    select  min(valeurtest) 
    from    discriminant D 
    group   by valeurmultiple 
    having  SUM(multiple) = 0 option (maxrecursion 32767);
    Et la requête passe très bien !

    A +

Discussions similaires

  1. [AC-2010] Plantage incompréhensible !
    Par guen dans le forum IHM
    Réponses: 1
    Dernier message: 28/02/2011, 14h26
  2. Probleme incompréhensible de plantage Windows.
    Par botakelymg dans le forum Windows XP
    Réponses: 4
    Dernier message: 02/11/2009, 13h40
  3. Réponses: 4
    Dernier message: 02/02/2009, 19h44
  4. plantage incompréhensible XP
    Par Lancelot du Lac dans le forum Windows XP
    Réponses: 3
    Dernier message: 29/07/2008, 14h48
  5. Plantage incompréhensible de windows xp
    Par Shakan972 dans le forum Windows XP
    Réponses: 20
    Dernier message: 03/09/2006, 19h35

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