Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 22/11/2011, 22h30   #1
Membre du Club
 
Inscription : juin 2007
Messages : 156
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 156
Points : 69
Points : 69
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
yozine est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/11/2011, 07h32   #2
Membre Expert
 
Avatar de iberserk
 
Homme Bruno IGNACE
Architecte de base de données
Inscription : novembre 2004
Messages : 1 299
Détails du profil
Informations personnelles :
Nom : Homme Bruno IGNACE
Âge : 30
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 299
Points : 2 282
Points : 2 282
Envoyer un message via MSN à iberserk
Bonjour vous devez passer par du SQL dynamique:

Code :
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.
iberserk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/11/2011, 07h38   #3
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 724
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 724
Points : 6 848
Points : 6 848
Bonjour,

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

Code :
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 :
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]
++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/11/2011, 10h08   #4
Membre du Club
 
Inscription : juin 2007
Messages : 156
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 156
Points : 69
Points : 69
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 :
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
yozine est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/11/2011, 11h13   #5
Membre Expert
 
Homme Etienne ZINZINDOHOUE
Ingénieur développement
Inscription : mars 2010
Messages : 1 139
Détails du profil
Informations personnelles :
Nom : Homme Etienne ZINZINDOHOUE
Localisation : France, Nord (Nord Pas de Calais)

Informations professionnelles :
Activité : Ingénieur développement
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : mars 2010
Messages : 1 139
Points : 2 470
Points : 2 470
Envoyer un message via Yahoo à zinzineti
Citation:
Envoyé par mikedavem Voir le message

Code :
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
zinzineti est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/11/2011, 15h13   #6
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 724
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 724
Points : 6 848
Points : 6 848
Oui c'était juste là à titre d'exemple pour yozine. Mais c'est bien de le rappeler également.

++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h29.


 
 
 
 
Partenaires

Hébergement Web