Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment trouver une chaîne dans une base de données entière ?

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 outrageusement lent et non optimisé . Toutes les valeurs sont converties en nvarchar simplement pour pouvoir les comparer sans erreur. Vous pouvez rencontrer des problèmes avec des valeurs telles que datetime ne se convertit pas comme prévu et n'est donc pas mis en correspondance quand il le devrait (faux négatifs).

Le WHERE (0 = 1) est là pour faire construire le OR clause plus facile. S'il n'y a pas de correspondances, vous ne récupérerez aucune ligne.