J'ai une chaîne spécifique, telle que "123abcd" par exemple, mais je ne connais pas le nom de la table ni même le nom de la colonne à l'intérieur de la table de ma base de données SQL Server. Je veux le trouver avec une sélection et afficher toutes les colonnes de la chaîne associée, alors je me demandais quelque chose comme:
select * from Database.dbo.* where * like '%123abcd%'
Pour des raisons évidentes, cela ne fonctionne pas, mais il existe un moyen simple de créer une instruction select pour faire quelque chose comme ça?
Cela fonctionnera:
DECLARE @MyValue NVarChar(4000) = 'something';
SELECT S.name SchemaName, T.name TableName
INTO #T
FROM sys.schemas S INNER JOIN
sys.tables T ON S.schema_id = T.schema_id;
WHILE (EXISTS (SELECT * FROM #T)) BEGIN
DECLARE @SQL NVarChar(4000) = 'SELECT * FROM $$TableName WHERE (0 = 1) ';
DECLARE @TableName NVarChar(1000) = (
SELECT TOP 1 SchemaName + '.' + TableName FROM #T
);
SELECT @SQL = REPLACE(@SQL, '$$TableName', @TableName);
DECLARE @Cols NVarChar(4000) = '';
SELECT
@Cols = COALESCE(@Cols + 'OR CONVERT(NVarChar(4000), ', '') + C.name + ') = CONVERT(NVarChar(4000), ''$$MyValue'') '
FROM sys.columns C
WHERE C.object_id = OBJECT_ID(@TableName);
SELECT @Cols = REPLACE(@Cols, '$$MyValue', @MyValue);
SELECT @SQL = @SQL + @Cols;
EXECUTE(@SQL);
DELETE FROM #T
WHERE SchemaName + '.' + TableName = @TableName;
END;
DROP TABLE #T;
Quelques mises en garde, cependant. Tout d’abord, c’est scandaleusement lent et non optimisé . Toutes les valeurs sont converties en nvarchar
simplement pour pouvoir être comparées sans erreur. Vous pouvez rencontrer des problèmes avec des valeurs telles que datetime
qui ne sont pas converties comme prévu et qui ne correspondent donc pas quand elles devraient l'être (faux négatifs).
La WHERE (0 = 1)
est là pour faciliter la construction de la clause OR
. S'il n'y a pas de correspondance, vous n'obtiendrez aucune ligne.
Voici quelques autres outils gratuits pouvant être utilisés pour cela. Les deux fonctionnent comme addins SSMS.
ApexSQL Search - 100% gratuit - recherche à la fois le schéma et les données dans des tables. A quelques options plus utiles telles que le suivi des dépendances…
Le pack d’outils SSMS - est gratuit pour toutes les versions, à l’exception de SQL 2012, n’a pas l’air aussi avancé que la version précédente, mais il possède de nombreuses autres fonctionnalités intéressantes.
create procedure usp_find_string(@string as varchar(1000))
as
begin
declare @mincounter as int
declare @maxcounter as int
declare @stmtquery as varchar(1000)
set @stmtquery=''
create table #tmp(tablename varchar(128),columnname varchar(128),rowid int identity)
create table #tablelist(tablename varchar(128),columnname varchar(128))
declare @tmp table(name varchar(128))
declare @tablename as varchar(128)
declare @columnname as varchar(128)
insert into #tmp(tablename,columnname)
select a.name,b.name as columnname from sysobjects a
inner join syscolumns b on a.name=object_name(b.id)
where a.type='u'
and b.xtype in(select xtype from systypes
where name='text' or name='ntext' or name='varchar' or name='nvarchar' or name='char' or name='nchar')
order by a.name
select @maxcounter=max(rowid),@mincounter=min(rowid) from #tmp
while(@mincounter <= @maxcounter )
begin
select @tablename=tablename, @columnname=columnname from #tmp where rowid=@mincounter
set @stmtquery ='select top 1 ' + '[' +@columnname+']' + ' from ' + '['+@tablename+']' + ' where ' + '['+@columnname+']' + ' like ' + '''%' + @string + '%'''
insert into @tmp(name) exec(@stmtquery)
if @@rowcount >0
insert into #tablelist values(@tablename,@columnname)
set @mincounter=@mincounter +1
end
select * from #tablelist
end
Je pense que vous avez des options:
Construisez un SQL dynamique en utilisant sys.tables
et sys.columns
pour effectuer la recherche ( exemple ici ).
Utilisez n'importe quel programme ayant cette fonction. Un exemple de ceci est SQL Workbench (free).
Dans Oracle, vous pouvez utiliser la commande SQL suivante pour générer les commandes SQL dont vous avez besoin:
select
"select * "
" from "||table_name||
" where "||column_name||" like '%123abcd%' ;" as sql_command
from user_tab_columns
where data_type='VARCHAR2';
SQL Locator (gratuit) a très bien fonctionné pour moi. Il vient avec beaucoup d'options et il est assez facile à utiliser.
Common Resource Grep (crgrep) recherche les correspondances de chaînes dans les tables/colonnes par nom ou contenu et prend en charge un certain nombre de bases de données, notamment SQLServer, Oracle et autres. Wild-carding complet et autres options utiles.
C'est opensource (je suis l'auteur).
J'utilise habituellement information_Schema.columns
et information_schema.tables
, bien que, comme @yuck ait dit, sys.tables
et sys.columns
soient plus courts à taper.
Dans une boucle, concaténez ces
@sql = @sql + 'select' + column_name +
' from ' + table_name +
' where ' + column_name ' like ''%''+value+''%' UNION
Ensuite, exécutez le SQL résultant.
Désolé pour la réponse tardive, mais je venais aussi de poser cette question et j'ai fini par la résoudre en utilisant une autre approche qui est probablement plus générique pour toutes les bases de données.
Voici une solution facile et pratique à base de curseur
DECLARE
@search_string VARCHAR(100),
@table_name SYSNAME,
@table_id INT,
@column_name SYSNAME,
@sql_string VARCHAR(2000)
SET @search_string = 'StringtoSearch'
DECLARE tables_cur CURSOR FOR SELECT name, object_id FROM sys.objects WHERE type = 'U'
OPEN tables_cur
FETCH NEXT FROM tables_cur INTO @table_name, @table_id
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE columns_cur CURSOR FOR SELECT name FROM sys.columns WHERE object_id = @table_id
AND system_type_id IN (167, 175, 231, 239)
OPEN columns_cur
FETCH NEXT FROM columns_cur INTO @column_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @sql_string = 'IF EXISTS (SELECT * FROM ' + @table_name + ' WHERE [' + @column_name + ']
LIKE ''%' + @search_string + '%'') PRINT ''' + @table_name + ', ' + @column_name + ''''
EXECUTE(@sql_string)
FETCH NEXT FROM columns_cur INTO @column_name
END
CLOSE columns_cur
DEALLOCATE columns_cur
FETCH NEXT FROM tables_cur INTO @table_name, @table_id
END
CLOSE tables_cur
DEALLOCATE tables_cur