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 :

Comment coder une requete dynamique avec une Variable binaire.


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Profil pro
    DSI
    Inscrit en
    Mars 2009
    Messages
    102
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : DSI

    Informations forums :
    Inscription : Mars 2009
    Messages : 102
    Points : 73
    Points
    73
    Par défaut Comment coder une requete dynamique avec une Variable binaire.
    Bonjour à tous.

    Je dois tester une variable binaire dans une requete dynamique, et je n'arrive pas à trouver de solution.

    Un exemple:
    /* Soit une table ERP, disposant d'un champ appelé Colonne_Timestamp de type Time Stamp.
    Je dois l'historiser dans une table Datamart au format presque identique.
    Dans cette table datamart le champ Colonne_Timestamp de type BINARY(8).
    */

    @company --> contient un code société passé en parametre de la ProcSto.

    Declare @Maximum as binary(8)
    Declace @Requete as varchar(max)

    -- Je détermine le TimeStamp maximum de la table datamart.
    Set @Maximum = (select max(colonne_timestamp) from table_datamart

    -- Je récupère dans ERP tous les Time Stamp supérieurs à @Maximum
    Set @Requete = 'insert into table_datamart select C1, C2, C3, ... '
    + ' from ' + ''' + @company + ''' + '.table_erp '
    + 'where table_erp.colonne_timestamp > ' + @maximum


    Mon probleme se situe au niveau de la clause where!
    le 'where table_erp.colonne_timestamp > ' + @maximum ne passe pas.


    Auriez vous une idée, ou mieux une solution ?

  2. #2
    Expert éminent
    Avatar de Lyche
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2007
    Messages
    2 523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 523
    Points : 6 775
    Points
    6 775
    Billets dans le blog
    4
    Par défaut
    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
     
    /* Soit une table ERP, disposant d'un champ appelé Colonne_Timestamp de type Time Stamp.
    Je dois l'historiser dans une table Datamart au format presque identique.
    Dans cette table datamart le champ Colonne_Timestamp de type BINARY(8).
    */
     
    @company --> contient un code société passé en parametre de la ProcSto.
     
    Declare @Maximum as binary(8)
    Declace @Requete as varchar(max)
     
    -- Je détermine le TimeStamp maximum de la table datamart.
    Set @Maximum = (select max(colonne_timestamp) from table_datamart
     
    -- Je récupère dans ERP tous les Time Stamp supérieurs à @Maximum
    Set @Requete = 'insert into table_datamart select C1, C2, C3, ... '
    + ' from ' + ''' + @company + ''' + '.table_erp '
    + 'where table_erp.colonne_timestamp > ' + @maximum


    et pourquoi tu ferais pas une sous requète? au lieu d'avoir une requète qui te remplis ta variable @maximum, pourquoi ne pas faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    + 'where table_erp.colonne_timestamp > (select max(colonne_timestamp) from table_datamart)'
    PS : en haut tu as 2 declare. change les en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Declare @Maximum as binary(8)
          , @Requete as varchar(max)

  3. #3
    Membre régulier
    Profil pro
    DSI
    Inscrit en
    Mars 2009
    Messages
    102
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : DSI

    Informations forums :
    Inscription : Mars 2009
    Messages : 102
    Points : 73
    Points
    73
    Par défaut
    Je l 'ai fait bien sur, mais ma proc sto dynamique codée avec un
    (select max(colonne_timestamp) from table_datamart)'
    va drolement plus lentement que quand je travaille avec une requête statique codée comme indiqué.
    J'interprete cette lenteur au fait que la sous requete est évaluée à chaque ligne non ?

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Avez-vous essayé en encadrant votre valeur binaire par des quotes ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SET @Requete = 'insert into table_datamart select C1, C2, C3, ... '
    + ' from ' + ''' + @company + ''' + '.table_erp '
    + 'where table_erp.colonne_timestamp > ''' + @maximum + ''
    Dans tous les cas pour savoir ce que vous passez comme requête, utilisez la commande PRINT @Requete avant de l'exécuter

    @++

  5. #5
    Membre régulier
    Profil pro
    DSI
    Inscrit en
    Mars 2009
    Messages
    102
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : DSI

    Informations forums :
    Inscription : Mars 2009
    Messages : 102
    Points : 73
    Points
    73
    Par défaut
    J avais essayé bien sur...
    Message
    The data types varchar and binary are incompatible in the add operator.

  6. #6
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Exact, j'y ai repensé 5 minutes après en me disant qu'avec sp_executeSQL cela doit fonctionner :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DECLARE @SQL NVARCHAR(256),
    		@ParamDef NVARCHAR(255),
    		@bin BINARY(8)
     
    SELECT @SQL = 'INSERT INTO table_datamart ' +
    			' SELECT C1, C2, C3, ...' +
    			' FROM ' + @company + '.table_erp' +
    			' WHERE colonne_timestamp > @bin',
    		@ParamDef = N'@binIN BINARY(8)',
    		@bin = 0x0000000000000005
     
    EXEC master.dbo.sp_executeSQL @SQL, @ParamDef, @binIN = @bin
    Dites-nous si c'est OK

    @++

  7. #7
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Bonjour,

    Et utilisant la fonction master.dbo.fn_varbintohexstr ? (Voir code ci dessous)
    Edit => En plus de celle proposée par Elsuket

    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
    /* Soit une table ERP, disposant d'un champ appelé Colonne_Timestamp de type Time Stamp.
    Je dois l'historiser dans une table Datamart au format presque identique.
    Dans cette table datamart le champ Colonne_Timestamp de type BINARY(8).
    */
     
    @company --> contient un code société passé en parametre de la ProcSto.
     
    Declare @Maximum AS BINARY(8)
    Declace @Requete AS varchar(max)
     
    -- Je détermine le TimeStamp maximum de la table datamart.
    SELECT @Maximum = max(colonne_timestamp) FROM table_datamart
     
    -- Je récupère dans ERP tous les Time Stamp supérieurs à @Maximum
    SET @Requete = 'insert into table_datamart select C1, C2, C3, ... '
    + ' from ' + @company + '.table_erp '
    + 'where table_erp.colonne_timestamp > ' + master.dbo.fn_varbintohexstr(@maximum)
     
    EXEC(@Requete)
    ++

  8. #8
    Membre régulier
    Profil pro
    DSI
    Inscrit en
    Mars 2009
    Messages
    102
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : DSI

    Informations forums :
    Inscription : Mars 2009
    Messages : 102
    Points : 73
    Points
    73
    Par défaut
    Merci à elsuket et mikedavem.

    Solution de ELSUKET OK.


    Declare @Requete as nvarchar(max)
    Declare @maxim as binary(8)
    Declare @ParamDef as NVARCHAR(500)

    set @maxim = (select max([timestamp]) from [mserveur].[mbase].[dbo].[msociete$G_L Entry])
    Set @requete = 'select * from [mserveur].[mbase].[dbo].[msociete$G_L Entry] '
    + 'where [Timestamp] = @maximum '
    Set @ParamDef = N'@maximum BINARY(8)'

    EXECUTE sp_executeSQL @requete, @ParamDef, @maximum = @maxim

    Solution de mikedavem OK

    Declare @Requete as varchar(max)
    Declare @maxim as binary(8)

    set @maxim = (select max([timestamp]) from [mserveur].[mbase].[dbo].[msociete$G_L Entry])

    Set @requete = 'select * from [mserveur].[mbase].[dbo].[msociete$G_L Entry] '
    + 'where [Timestamp] = ' + master.dbo.fn_varbintohexstr(@maxim)
    Execute (@requete)

  9. #9
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Ceci me conforte dans l'idée de bannir l'utilisation de EXEC(@SQL) pour exécuter du code SQL dynamique :

    - le plan des requêtes exécutées avec sp_executeSQL est conservé, ce qui n'est pas le cas avec EXEC(@SQL)
    - le contexte d'exécution est le même que la procédure appelante lorsqu'on utilise sp_executeSQL, mais pas avec EXEC(@SQL),
    - on peut retourner des valeurs avec sp_executeSQL, ce qui n'est pas possible avec EXEC(@SQL)

    @++

  10. #10
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    En terme de performance il est kler qu'il vaut mieux utiliser sp_executsql pour les raisons que tu as cité.

    L'important dans la 2ème solution est simplement de voir qu'il est possible d'utiliser la fonction master.dbo.fn_varbintohexstr()

    ++

  11. #11
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Une fonction intéressante, mais qui n'est pas documentée ...
    A utiliser à nos risques et périls donc

    @++

  12. #12
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Aussi

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 26/03/2010, 08h16
  2. optimisé une requete SQl avec une requete imbriqués
    Par fabien14 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 16/01/2009, 10h01
  3. Réponses: 4
    Dernier message: 14/11/2008, 20h56
  4. [RegEx] Ecrire une requete INSERT avec des variables $_POST
    Par arnaudperfect dans le forum Langage
    Réponses: 10
    Dernier message: 13/06/2007, 15h12
  5. Comment faire une requete liée avec une requete ?
    Par DavidDeTroyes dans le forum Requêtes
    Réponses: 4
    Dernier message: 18/04/2006, 13h18

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