Nous avons une application utilisée au travail qui a été créée par un tiers. Nous avons donc accès à l'interface utilisateur et non au code backend. Sur cette application, il y a une liste déroulante. J'ai accès à la base de données MSSQL sur laquelle cette application s'exécute.
J'ai besoin de savoir d'où cette liste déroulante tire ses informations mais je ne sais pas quelle table elle utilise (car je ne peux pas vérifier le code directement).
Y a-t-il une requête que je peux écrire pour rechercher dans toute la base de données des tables contenant des colonnes contenant une valeur spécifique?
Les valeurs de la liste déroulante sont:
5 Réponses :
Vous pouvez interroger sys.tables et sys.columns pour localiser une liste de table.column contenant des informations textuelles, puis à partir de cela générer un certain nombre de requêtes SQL
sélectionnez [nom_colonne] dans [nom_table] où [nom_colonne] dans ('valeur1', 'valeur2')
Vous pouvez utiliser SQL Server Profiler ou Session d'événements étendus pour capturer les instructions exécutées par rapport à la base de données. Pour ce faire, le moyen le plus simple consiste à utiliser le Fonctionnalité SSMS XEvent Profiler (introduite dans Management Studio version 17.3). En gros, vous commencez à capturer les instructions exécutées, ouvrez l'application pour lui faire charger la liste, arrêtez le traçage et regardez les requêtes capturées pour déterminer la source des données.
Le problème avec SQL Server Profiler est que des milliers de personnes utilisent quotidiennement l'application. localiser cette requête exacte sera une mission
Vous pouvez le faire sur une instance de test distincte ou dans la fenêtre de maintenance. Mais si vous ne pouvez pas, vous pouvez rechercher le contenu de toutes les colonnes de texte dans tous les tableaux. Il y a beaucoup de questions dans SO, par exemple celui-ci .
USE AdventureWorks;
GO
SET NOCOUNT ON;
DECLARE @T TABLE (ColumnName SYSNAME, TableName SYSNAME);
DECLARE
@SearchString VARCHAR(255) = 'Simon',
@SQL NVARCHAR(MAX);
DECLARE CUR CURSOR LOCAL FAST_FORWARD FOR
SELECT
'SELECT ' +
QUOTENAME(c.name) + ', ''' +
OBJECT_SCHEMA_NAME(c.object_id) + '.' + OBJECT_NAME(c.object_id) +
''' FROM ' + QUOTENAME(OBJECT_SCHEMA_NAME(c.object_id)) + '.' + QUOTENAME(OBJECT_NAME(c.object_id)) +
' WHERE ' + QUOTENAME(c.name) + ' = ''' + @SearchString + ''';'
FROM
sys.columns c
INNER JOIN
sys.types t
ON c.user_type_id = t.user_type_id
WHERE
c.collation_name IS NOT NULL
AND t.name NOT IN ('text','ntext')
AND OBJECTPROPERTY(c.object_id,'IsSystemTable') = 0
AND OBJECTPROPERTY(c.object_id,'IsMSShipped') = 0
AND OBJECTPROPERTY(c.object_id,'IsTable') = 1;
OPEN CUR;
FETCH CUR INTO @SQL;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @SQL;
INSERT INTO @T
EXEC sp_executesql @SQL;
FETCH CUR INTO @SQL;
END;
CLOSE CUR;
DEALLOCATE CUR;
SELECT DISTINCT
*
FROM
@T;
Vous pouvez essayer de générer et d'exécuter une instruction SQL dynamique, basée sur les informations contenues dans INFORMATION_SCHEMA.COLUMNS:
SELECT
N'SELECT ' +
N'''' + TABLE_NAME + N''' AS TableName, ' +
N'''' + COLUMN_NAME + N''' AS ColumnName, ' +
QUOTENAME(COLUMN_NAME) +
N' FROM ' + QUOTENAME(TABLE_NAME) +
N' WHERE ' + QUOTENAME(COLUMN_NAME) + N' IN (''WebsiteAPP'', ''BOT App'', ''Walkin'', ''BotLead''); '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
DATA_TYPE = ('varchar') OR
DATA_TYPE = ('nvarchar');
Ou simplement obtenir toutes les instructions SQL dans une table et les exécuter comme vous le souhaitez :
DECLARE @stm nvarchar(max)
SET @stm = N''
SELECT @stm = @stm +
N'SELECT ' +
N'''' + TABLE_NAME + N''' AS TableName, ' +
N'''' + COLUMN_NAME + N''' AS ColumnName, ' +
QUOTENAME(COLUMN_NAME) +
N' FROM ' + QUOTENAME(TABLE_NAME) +
N' WHERE ' + QUOTENAME(COLUMN_NAME) + N' IN (''WebsiteAPP'', ''BOT App'', ''Walkin'', ''BotLead''); '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
DATA_TYPE = ('varchar') OR
DATA_TYPE = ('nvarchar');
PRINT @stm
EXEC sp_executesql @stm
Vous pouvez obtenir ce que vous voulez avec la requête suivante, remplacez simplement MyDatabase par le nom de votre base de données (commentaires nécessaires dans le code):
-- define cursor to loop through all columns
declare crs cursor for
select object_name(object_id), name from MyDatabase.sys.columns
where collation_name is not null --here we add this constraint to check only varchar columns
declare @tableName varchar(1000), @columnName varchar(1000), @sql varchar(1000);
open crs
fetch next from crs into @tableName, @columnName
while @@FETCH_STATUS = 0
begin
-- craete dynamic sql, which will check if all values exist in that column, if so, print table name
set @sql = 'if exists(select * from MyDatabase..' + @tableName + ' where ' + @columnName + ' = ''Value1'') ' +
-- to add more values, just modify this dynamic sql (add another exist(...))
'and exists(select * from MyDatabase..' + @tableName + ' where ' + @columnName + ' = ''Value2'') '
'and exists(select * from MyDatabase..' + @tableName + ' where ' + @columnName + ' = ''Value3'') print ''' + @tableName + ''';'
exec (@sql)
fetch next from crs into @tableName, @columnName
end
close crs
deallocate crs
REMARQUE : cela générera quelques erreurs, mais parmi elles, le nom de la table sera imprimé, il suffit de le rechercher :)