J'essaie d'écrire cette requête pour trouver toutes les tables avec une colonne spécifique avec une valeur spécifique. C'est ce que j'ai fait jusqu'à présent -
EXEC sp_MSforeachtable
@command1='
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE")
BEGIN
IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0
BEGIN
SELECT * FROM ? WHERE EMP_CODE="HO081"
END
END
'
J'espère que mes intentions sont claires, je veux juste sélectionner uniquement les tables où la colonne EMP_CODE
est présent et dans ces tableaux, je veux sélectionner les lignes où EMP_CODE='HO081'
.
Modifier -
Maintenant, ça ressemble à ça. Mais je ne peux pas remplacer @EMPCODE
variable dans la requête.
DECLARE @EMPCODE AS VARCHAR(20)
SET @EMPCODE='HO081'
EXEC sp_MSforeachtable
@command1='
DECLARE @COUNT AS INT
SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''+@EMPCODE+'''
IF @COUNT>0
BEGIN
PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)''
--PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''+@EMPCODE+'''''''
END
',@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME='''+@EMPCODE+''')'
Vous savez comment sp_MSforeachtable
N'est pas documenté et peut disparaître à tout moment/être modifié?
Eh bien, si vous êtes content de l'ignorer, il a un autre paramètre appelé @whereand
, Qui est ajouté à la clause WHERE
de la requête interne qui est utilisée pour trouver les tables (et devrait commencer par un AND
).
Vous devez également savoir qu'il existe un alias, o
contre sysobjects
, et un deuxième alias syso
contre sys.all_objects
.
En utilisant ces connaissances, vous pouvez créer votre paramètre @whereand
Comme:
EXEC sp_MSforeachtable
@command1='...',
@whereand='AND o.id in (select object_id from sys.columns c where c.name=''EMP_CODE'')'
Vous pouvez désormais également simplifier votre command1
, Car vous savez qu'il ne sera exécuté que sur des tables contenant une colonne EMP_CODE
. Je supprimerais probablement également la condition COUNT(*)
, car je ne vois pas quelle valeur il ajoute.
Mis à jour en fonction de vos travaux ultérieurs et testé sur une table:
DECLARE @EMPCODE AS VARCHAR(20)
SET @EMPCODE='HO081'
declare @sql nvarchar(2000)
set @sql = '
DECLARE @COUNT AS INT
SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''+@EMPCODE+'''
IF @COUNT>0
BEGIN
PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)''
--PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''+@EMPCODE+'''''''
END
'
EXEC sp_MSforeachtable
@command1=@sql,@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME=''EMP_CODE'')'
(J'ai rétabli le @whereand
Pour rechercher EMP_CODE
, Car vous ne voulez pas remplacer la valeur ici).
Le problème est que vous pouvez passer paramètres à une procédure stockée, ou littéraux, mais vous ne pouvez pas effectuer de calculs/combiner des actions entre eux - j'ai donc déplacé la construction de l'instruction sql dans une action distincte.
Je suppose que vous obtenez une erreur quelconque, peut-être Invalid column name 'EMP_CODE'
?
C'est parce que le code est compilé avant de vérifier la colonne. Vous pourriez faire comme ça à la place.
EXEC sp_MSforeachtable
@command1='
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE")
BEGIN
EXEC(''
IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0
BEGIN
SELECT * FROM ? WHERE EMP_CODE="HO081"
END
'')
END
'