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 :

Souci suite à la Migration de bases de 2014 vers 2019 [2014]


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut Souci suite à la Migration de bases de 2014 vers 2019
    Bonjour (et bonne année 2024)

    Je rencontre un souci suite à la migration de mon serveur SQL de 2014 à 2019

    J'ai une fonction scalaire fn_IdentiteNomPrenomCodeCEA qui renvoi une chaine

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT dbo.fn_IdentiteNomPrenomCodeCEA(CodeUtil) as IdentiteCIInverse
    donne ceci sur mon serveur 2014
    NOM PRENOM BADGE

    Lancée sur mon serveur 2019, j’ai une erreur de requête
    Msg 208, Level 16, State 1, Procedure fn_IdentiteNomPrenomCodeCEA, Line 48
    Nom d'objet 'Annuaire.dbo.AnnuaireUnifie' non valide.

    La fonction regarde sur quel serveur elle est lancée pour choisir la base concernée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
           set @serveur=@@SERVERNAME
           set @Regime=(SELECT Regime FROM ParamServeurAppliSTIC.dbo.ServeursSQL WHERE NomServeur=@@servername)
     
           if(@Regime='Test') set @Retour= (SELECT Nom+' '+Prenom+' '+CodeCEA FROM TestAnnuaire.dbo.AnnuaireUnifie WHERE ConnectId=@Code)
           else set @Retour= (SELECT Nom+' '+Prenom+' '+CodeCEA FROM Annuaire.dbo.AnnuaireUnifie WHERE ConnectId=@Code)
    Ma variable @Regime=Test donc seule la 1° requête est sensée s'exécuter
    Mais il semble que la fonction veuille quand même interpréter la requête du else

    Ce type de test est très présent dans mes procédures stockées et fonctions diverses. Ce serait un gros souci pour moi si je devais l’abandonner.

    Avez-vous une idée ?

    Merci

  2. #2
    Membre expérimenté Avatar de AaâÂäÄàAaâÂäÄàAaâÂäÄ
    Homme Profil pro
    db@
    Inscrit en
    Septembre 2021
    Messages
    515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : db@

    Informations forums :
    Inscription : Septembre 2021
    Messages : 515
    Points : 1 506
    Points
    1 506
    Par défaut
    Difficile de débugger une fonction avec juste 4 lignes de code et pas beaucoup de contexte...
    Est-ce que toutes les bds qui sont utilisées dans le bout de code ont été également migrées sur la nouvelle instance ?
    Je parle de ParamServeurAppliSTIC, TestAnnuaire et Annuaire

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Il nous faudrait le code intégrale de cette fonction. Y a t-il des serveurs liés ?

    A +

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut
    Voici le code de la fonction

    Il n'y a pas de serveurs liés concernés dans cette fonction utilisateur.

    Toutes les bases de données du serveur ont théoriquement été basculées de 2014 en 2019

    La fonction est la même sur le serveur de PROD que sur le serveur de DEV.
    Sur la PROD c'est la base Annuaire, qui est définie donc lue dans cette fonction
    Sur la DEV c'est la base TestAnnuaire, qui est définie donc lue dans cette fonction

    J'ai remarqué que les procédures stockées, qui utilisent le même système d'identification du serveur (Prod ou Test) ne sont pas sujet à cette erreur ?!

    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
     
    CREATE FUNCTION [dbo].[fn_IdentiteNomPrenomCodeCEA] (@Code as char(8))
    RETURNS varchar(100)
    AS  
     
    BEGIN
    	/* Fonction fournissant l'identité (Nom+' '+Prénom+' '+CodeCEA) à partir du ConnectId  */
     
    	/* VERSION du 16/07/2013 10:00 */
     
    	-- pour les tests
    	/*
    	declare @Code as char(8)
    	set @Code='DL098922'
    	*/
     
    	declare @Retour				varchar(100)
     
    	declare @Serveur 			varchar(100)
    	declare @Regime				varchar(10)
     
    	-- récupération du nom du serveur sur lequel on 'tourne'	
    	set @serveur=@@SERVERNAME
    	set @Regime=(SELECT Regime FROM ParamServeurAppliSTIC.dbo.ServeursSQL WHERE NomServeur=@@servername)
     
    	if(@Regime='Test') set @Retour= (SELECT Nom+' '+Prenom+' '+CodeCEA FROM TestAnnuaire.dbo.AnnuaireUnifie WHERE ConnectId=@Code)
    	else set @Retour= (SELECT Nom+' '+Prenom+' '+CodeCEA FROM Annuaire.dbo.AnnuaireUnifie WHERE ConnectId=@Code)
     
    	if(@Retour is null)
    	begin
    		if(@Regime='Test') set @Retour= (SELECT NomReel_Util+' '+PrenomReel_Util+' '+substring(Connect_Util,3,6) FROM TestAnnuaire.dbo.HabilitaSTIC WHERE Connect_Util=@Code)
    		else set @Retour= (SELECT NomReel_Util+' '+PrenomReel_Util+' '+substring(Connect_Util,3,6) FROM Annuaire.dbo.HabilitaSTIC WHERE Connect_Util=@Code)
    	end
     
    	if(@Retour is null) set @Retour=''
     
    	--print @Retour
     
    	-- pas de traitement d'erreur actuellement 
     
    	RETURN @Retour
    END
    J'espère que vous avez maintenant plus d'informations pour donner un avis.
    Cordialement

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut suite
    Un collègue a fait un test sur plusieurs versions de bases de données.
    Pour lui cela fonctionne de 2008 à 2017 mais comme moi plus avec 2019.

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Quel est la version de patch de votre instance :


    Quel sont les collations du serveur et des bases ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT SERVERPROPERTY('Collation') AS SERVER_COLLATION, 
           name AS DATABASE_NAME,
           collation_name AS DATABASE_COLLATION,
           CASE SERVERPROPERTY('Collation')
              WHEN collation_name THEN 0
              ELSE 1
           END AS MIXED_COLLATION
    FROM  sys.databases
    ??

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Enfin je la récrirais sans toutes les verrues comme ceci :

    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
    CREATE FUNCTION [dbo].[fn_IdentiteNomPrenomCodeCEA]
    (@Code AS CHAR(8)
    )
    RETURNS VARCHAR(100)
    AS
    BEGIN
     
    /* Fonction fournissant l'identité (Nom+' '+Prénom+' '+CodeCEA) à partir du ConnectId  */
    /* VERSION du 16/07/2013 10:00 */
     
    -- pour les tests
    /*
    declare @Code as char(8)
    set @Code='DL098922'
    */
     
       DECLARE @Retour VARCHAR(100),
               @Regime VARCHAR(10);
     
       -- récupération du nom du serveur sur lequel on 'tourne'	
       SELECT @Regime =Regime
       FROM   ParamServeurAppliSTIC.dbo.ServeursSQL
       WHERE  NomServeur = @@servername;
     
       IF @Regime = 'Test'
          SELECT @Retour = Nom + ' ' + Prenom + ' ' + CodeCEA
          FROM TestAnnuaire.dbo.AnnuaireUnifie
          WHERE ConnectId = @Code;
       ELSE
          SELECT @Retour =Nom + ' ' + Prenom + ' ' + CodeCEA
          FROM Annuaire.dbo.AnnuaireUnifie
          WHERE ConnectId = @Code;
     
       IF @Retour IS NULL 
          IF @Regime = 'Test'
              SELECT @Retour =NomReel_Util + ' ' + PrenomReel_Util + ' ' + SUBSTRING(Connect_Util, 3, 6)
              FROM TestAnnuaire.dbo.HabilitaSTIC
              WHERE Connect_Util = @Code;
          ELSE
              SELECT @Retour =NomReel_Util + ' ' + PrenomReel_Util + ' ' + SUBSTRING(Connect_Util, 3, 6)
              FROM Annuaire.dbo.HabilitaSTIC
              WHERE Connect_Util = @Code;
     
             --print @Retour
             -- pas de traitement d'erreur actuellement 
     
       RETURN COALESCE(@Retour, '');
    END;

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut Suite et début d'explication
    Bonjour

    J'ai une peut-être un embryon de piste.

    Que je prenne ma création de ma fonction ou celle proposé ci-dessus, lorsque j'exécute (via Managment Studio) l'appel la 1° fois, j'ai toujours l'erreur.
    Je relance l'appel, et là plus d'erreur.
    Je me déconnecte du serveur, me reconnecte et relance l'appel.
    Erreur
    Nouvel appel
    Erreur
    Nouvel appel (et pour tous les suivants) plus d'erreur.

    Je suppose qu'il y a 2 erreurs car j'ai 2 lignes où la base de données n'existe pas sur ce serveur.
    Il semble donc que la totalité des requêtes soient interprétées sans tenir compte des éventuels tests mis en place.
    Puis que le système finisse par mémoriser la juste requête.

    Pour le moment, à part rétrograder la version des bases en 2017 , je ne vois pas comment faire.
    L'intérêt de mes tests de régime (serveur) est que le fichier source sql est toujours le même en DEV comme en PROD.

  9. #9
    Membre expérimenté Avatar de AaâÂäÄàAaâÂäÄàAaâÂäÄ
    Homme Profil pro
    db@
    Inscrit en
    Septembre 2021
    Messages
    515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : db@

    Informations forums :
    Inscription : Septembre 2021
    Messages : 515
    Points : 1 506
    Points
    1 506
    Par défaut
    une solution pas trop clean serait de passer par du sql dynamique pour choisir la bd sans interpréter la ligne.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut suite
    Donc construire la requête et passer un un EXECUT ?
    Du style :
    declare @Requete varchar(max)
    if(Regime='Test') SET @Requete ='SELECT .... FROM TestAnnuaire WHERE ....'
    else SET @Requete ='SELECT .... FROM Annuaire WHERE ....'
    execute (@Requete)

    Si c'est la seule solution je le ferai mais j'ai plus de 300 objets à modifier ainsi ...

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par AaâÂäÄàAaâÂäÄàAaâÂäÄ Voir le message
    une solution pas trop clean serait de passer par du sql dynamique pour choisir la bd sans interpréter la ligne.
    Impossible dans une fonction. Nécessite d'utiliser une procédure.

  12. #12
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par ulmeen Voir le message
    ...

    Pour le moment, à part rétrograder la version des bases en 2017 , je ne vois pas comment faire.
    L'intérêt de mes tests de régime (serveur) est que le fichier source sql est toujours le même en DEV comme en PROD.
    Avant de migrer à l'envers, voyez si le fait de mettre la base en rétrocompatibilité 2017 ou 2012 ou 2008 change la donne...

    A +

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut Suite
    Bonjour
    Je viens de baisser le niveau de compatibilité. Je suis redescendu à SQL Server 2017.
    L'appel de fonction renvoie bien une valeur.
    Je repasse en SQL Server 2019, et l'erreur réapparait.

    Que me conseillez-vous ?

    Rétrograder mes bases en 2017.
    Mais est-ce que ce n'est pas cacher la poussière sous le tapis et retrouver le problème plus tard (nouvelle migration, ...) ?
    A moins que plus tard ce problème soit corrigé.

    Supprimer ces tests pour ne plus avoir 2 requêtes possibles. Ce qui impose des fonctions différentes entre PROD et DEV et une reprise de toutes celle-ci ?
    Mais cela simplifie les fonctions et permet sans doute au système d'être plus performant.

    Merci pour vos remarques

  14. #14
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    Essayez en mode 2019 en ajoutant à votre fonction l'option INLINE = OFF

    Comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE FUNCTION [dbo].[fn_IdentiteNomPrenomCodeCEA] (@Code as char(8))
    RETURNS varchar(100)
    WITH INLINE = OFF
    AS  
     
    BEGIN
    	...
    END
    A +

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 107
    Points : 72
    Points
    72
    Par défaut Bilan
    Bonjour

    En ajoutant le WITH INLINE= OFF cela fonctionne !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    CREATE FUNCTION [dbo].[fn_IdentiteNomPrenomCodeCEA] (@Code as char(8))
    RETURNS varchar(100)
    WITH INLINE = OFF
    AS
    Merci beaucoup

  16. #16
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    En fait ce qui s'est passé a été prévu par SQL Server...

    Depuis la version 2017, Microsoft a beaucoup travaillé sur de nouvelles optimisations dans le cadre d'un projet appelé "Intelligent Query Processor" (IQP), dont l'une des fonctionnalité consiste à supprimer l'appel de la fonction (UDF) en l'intégrant directement dans la requête afin que le tout soit optimisé. Cela s'appelle l'inligning (enlignement)...
    En effet, les requêtes ont un comportement ensembliste (toutes les opérations s'effectuent en même temps <=> parallélisme) alors qu'une fonction est toujours itérative (c'est à dire que le code se déroule séquentiellement) ce qui fait que l'introduction de fonctions dans le code d'une requête casse ordinairement le fonctionnement ensembliste de la requête et la rend itérative et par conséquent lente... Pour palier ce problème de performance Microsoft Research a initié le projet "FROID" a eut pour but de récrire les requêtes en réintégrant le code SQL de la fonction dans la requête. . On obtient alors une requête parfaitement ensembliste et les performances n'ont plus rien à voir....
    Cependant, ce mode a un inconvénient : il étudie toutes les possibilités d'exécution simultanément, alors que l'itération dans le code d'une UDF coupe des branches via les commande de contrôle telles que IF THEN ELSE...
    Sachant cela, il y a quelques rares cas ou cet "enlignement" de la fonction peut devenir un problème et c'est votre cas... En effet, une requête est compilée d'un seul bloc et l'absence de certains objets à ce moment peut se révéler critique...
    Pour palier cet effet de bord, Microsoft SQL Server a rajouté une option dans la création des fonctions (INLINE = OFF) afin d'interdire l'enlignement d'une UDF au cas ou cela produirait une anomalie...

    Vous êtes tombé dessus !

    A +

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

Discussions similaires

  1. Migration Catalogs SSIS de 2012 vers 2019 (sur un autre serveur)
    Par sylvie81 dans le forum Administration
    Réponses: 1
    Dernier message: 25/08/2023, 12h48
  2. Migration (upgrade) base oracle 9iR2 vers 11gR2
    Par devkais dans le forum Oracle
    Réponses: 2
    Dernier message: 10/02/2012, 15h04
  3. Réponses: 0
    Dernier message: 23/11/2009, 13h38
  4. migration de base ACCESS 03 vers SQL Serveur 05.
    Par solaar dans le forum Access
    Réponses: 3
    Dernier message: 16/06/2008, 01h33

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