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 :

requête sur nomtable pour chaque enregistrement table nomtable/nomcolonne


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Inscrit en
    Juin 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 161
    Points : 109
    Points
    109
    Par défaut requête sur nomtable pour chaque enregistrement table nomtable/nomcolonne
    Bonjour, j'ai bloqué aujourd'hui sur un problème qui parait tout simple au premier abord. A la base, j'ai plus un profil développeur JAVA, et le transact-SQL est en train de me faire vivre un calvaire !

    Alors j'essaie d'expliquer (si j'arrive à faire un copier-coller de mon code, et passer le filtrage web du client pour arriver ici demain, j'essaierai d'ajouter un bout de code pour illustrer) :

    Premièrement, je remplis une table toto(nomtable varchar(128), nomcol varchar(128)). Cette table contient des noms de table, et des noms de colonne qui existent dans la base.

    Deuxièmement, je déclare un curseur qui alimente deux parametres de type varchar(128) @nomtable, @nomcol, a partir des lignes de la table toto.

    Jusque là rien de particulier.

    A chaque, ligne ramenée par le curseur, je souhaite effectuer une opération sur la colonne @nomcol, de la table @nomtable (trouver le min et le max en fait).

    J'espere que vous avez pû suivre jusque là.

    Si je lance une requête par exemple : 'select * from @nomtable'. J'obtiens une erreur qui me dit que la variable de type 'table' @nomtable n'est pas définie. OK, c'est assez logique en fait, puisque @nomtable est déclaré comme varchar(128). Donc j'essaie autre chose du type : 'select * from object_id(@nomtable, 'U')'... ça ne fonctionne pas non plus.

    En fait je n'arrive pas à récupérer un 'objet' de type 'table' à partir du nom de la table contenu dans @nomtable (pour m'exprimer autrement).

    Bref, je ne vois pas comment itérer sur ma liste de table/colonne, et effectuer des requêtes pour chaque enregistrement. Quelqu'un a-t-il une solution (élégante) ?
    JAVA le dire a tout le monde

  2. #2
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Bonjour vous devez passer par du SQL dynamique:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    DECLARE @REQUETE VARCHAR(MAX)
    SET @REQUETE='SELECT * FROM '+@nomtable
    EXEC (@REQUETE)
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  3. #3
    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,

    La syntaxe SELECT * FROM @nomTable ne fonctionne pas. Il faudra utiliser une requête dynamique du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EXEC('SELECT * FROM ' + @nomTable)
    Vous pouvez néanmoins éviter les curseurs pour cela mais il faudrait avoir plus de précision sur votre but final. Par exemple il est possible de chercher le min et le max d'une colonne pour une table concernée de la façon suivante dans votre cas :

    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
    DECLARE @T TABLE
    (
     nomTable SYSNAME,
     nomCol VARCHAR(128)
    )
     
    INSERT @T VALUES ('T1', 'col1')
    INSERT @T VALUES ('T2', 'col2')
     
    DECLARE @sql VARCHAR(MAX);
     
    SELECT 
     @sql = COALESCE(@sql, '') + 'SELECT MIN([' + nomCol + ']) AS minvalue, MAX([' + nomCol + ']) FROM dbo.[' + nomTable + ']' + CHAR(13)
    FROM @T;
     
    PRINT @sql
     
    --SELECT MIN([col1]) AS minvalue, MAX([col1]) FROM dbo.[T1]
    --SELECT MIN([col2]) AS minvalue, MAX([col2]) FROM dbo.[T2]
    ++

  4. #4
    Membre régulier
    Inscrit en
    Juin 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 161
    Points : 109
    Points
    109
    Par défaut
    Merci beaucoup pour l'info sur les requêtes dynamiques.

    Ce script sert à ramener la valeur minimum des clefs primaires des tables à 1, et à modifier toutes les autres valeurs de la clef primaire par ('valeur clef' - 'valeur min clef' +1).
    Ensuite les valeurs de 'foreign key', qui référencent ces clefs primaires sont également mises à jour. Pour ce point, je n'ai pas de contrainte 'UPDATE ON CASCADE', et on ne m'autorise pas à modifier cette contrainte.

    ce script m'a été demandé pour des besoins de migration d'environnement.

    Ci-dessous le script sans prendre en compte la notion de requête dynamique.
    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
    95
    96
    97
    98
     
    -- declaration de variables
    DECLARE @joker varchar(128);
    DECLARE @tablename varchar(128);
    DECLARE @colname varchar(128);
    DECLARE @minseqval bigint;
    DECLARE @lastvalue bigint;
    DECLARE @tablenameref varchar(128);
    DECLARE @colnameref varchar(128);
    -- variables de type 'table'
    DECLARE @fkreftable TABLE (tablename varchar(128), colname varchar(128));
    -- Initialisation du Joker (motif) - ex: commence par 'T_'
    SET @joker = 'T_'
     
    -- creation tables
    IF OBJECT_ID('tempdb..#ident', 'U') IS NOT NULL
    DROP TABLE #ident
    --GO
     
    CREATE TABLE #ident(tablename varchar(128), colname varchar(128), seqname varchar(128), minseqval bigint, lastvalue bigint);
     
    -- ENREGISTREMENT des pk à partir des sequences de la base, dans la table '#ident'
    INSERT INTO #ident(tablename, colname)
    SELECT ...;
     
    -- desactivation des contraintes des tables
    exec sp_MSforeachtable 
    'ALTER TABLE ? NOCHECK CONSTRAINT ALL';
     
    DECLARE curseur_seq CURSOR FOR
    	SELECT tablename, colname FROM #ident;
     
    -- DEALLOCATE curseur_ref;
    DECLARE curseur_ref CURSOR FAST_FORWARD FOR
    	SELECT tablename, colname FROM @fkreftable;
     
    OPEN curseur_seq;
     
    FETCH curseur_seq INTO @tablename, @colname;
     
    -- parcours de la table des sequences
    WHILE @@FETCH_STATUS = 0
    BEGIN
    	-- récupération du min de la séquence
    	UPDATE #ident
    	SET @minseqval = (SELECT MIN(@colname) FROM OBJECT_ID(@tablename, 'U') )
    	WHERE tablename = @tablename AND colname = @colname;
     
    	-- récupération du max (= lastvalue) de la séquence
    	UPDATE #ident
    	SET @lastvalue = (SELECT MAX(@colname) FROM OBJECT_ID(@tablename, 'U') )
    	WHERE tablename = @tablename AND colname = @colname;		
     
    	-- mise à jour des valeurs de la clef primaire
    	UPDATE OBJECT_ID(@tablename, 'U') SET @colname = @colname - @minseqval + 1;
     
    	-- mise à jour de 'last value' de la sequence
    	-- DBCC CHECKIDENT ("@tablename", RESEED, @lastvalue );
     
     
    	-- recuperation des clefs etrangeres qui referencent la sequence dans la table '@fkreftable'
    	INSERT INTO @fkreftable("tablename", "colname")
    	SELECT OBJECT_NAME (f.referenced_object_id), COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
    	FROM sys.foreign_keys AS f 
    	INNER JOIN sys.foreign_key_columns AS fc 
    	   ON f.OBJECT_ID = fc.constraint_object_id
    	WHERE OBJECT_NAME(f.parent_object_id) = @tablename
    	AND COL_NAME(fc.parent_object_id, fc.parent_column_id) = @colname;
     
    	-- mise à jour les valeurs des foreign keys
    	OPEN curseur_ref;
     
    	FETCH curseur_ref INTO @tablenameref, @colnameref
     
    	WHILE @@FETCH_STATUS = 0
    	BEGIN
    		UPDATE OBJECT_ID(@tablenameref, 'U') SET @colnameref = @colnameref - @minseqval + 1;
    		FETCH curseur_ref INTO @tablenameref, @colnameref;
    	END
    	CLOSE curseur_ref;
    	DEALLOCATE curseur_ref;
     
    	-- reinitialisation table temporaire
    	DELETE FROM @fkreftable;
     
    	FETCH curseur_seq INTO @tablename, @colname;
     
     
    END;
     
    CLOSE curseur_seq;
    DEALLOCATE curseur_seq;
     
    -- reactivation des contraintes des tables
    exec sp_MSforeachtable 
    'ALTER TABLE ? CHECK CONSTRAINT ALL';
     
    GO
    JAVA le dire a tout le monde

  5. #5
    Membre émérite

    Homme Profil pro
    Chargé de Développement et d'Analyse de données
    Inscrit en
    Mars 2010
    Messages
    1 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé de Développement et d'Analyse de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 278
    Points : 2 856
    Points
    2 856
    Par défaut
    Citation Envoyé par mikedavem Voir le message

    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
    DECLARE @T TABLE
    (
     nomTable SYSNAME,
     nomCol VARCHAR(128)
    )
     
    INSERT @T VALUES ('T1', 'col1')
    INSERT @T VALUES ('T2', 'col2')
     
    DECLARE @sql VARCHAR(MAX);
     
    SELECT 
     @sql = COALESCE(@sql, '') + 'SELECT MIN([' + nomCol + ']) AS minvalue, MAX([' + nomCol + ']) FROM dbo.[' + nomTable + ']' + CHAR(13)
    FROM @T;
     
    PRINT @sql
     
    --SELECT MIN([col1]) AS minvalue, MAX([col1]) FROM dbo.[T1]
    --SELECT MIN([col2]) AS minvalue, MAX([col2]) FROM dbo.[T2]
    ++
    Rappel :
    Attention à l'utilisation de PRINT ! il ya une limitation de 8000 caractères pour les chaines de caratères non unicode et 4000 pour les chaines de caractères unicode
    Etienne ZINZINDOHOUE
    Billets-Articles

  6. #6
    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
    Oui c'était juste là à titre d'exemple pour yozine. Mais c'est bien de le rappeler également.

    ++

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 29/04/2015, 14h44
  2. [AC-2003] Document sur deux pages A4 pour chaque enregistrement
    Par Hmiachon dans le forum IHM
    Réponses: 1
    Dernier message: 22/05/2014, 18h59
  3. Réponses: 6
    Dernier message: 11/08/2010, 15h50
  4. Réponses: 7
    Dernier message: 05/01/2007, 14h14
  5. Réponses: 3
    Dernier message: 18/11/2006, 20h21

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