So the purpose is to find a certain string in any table in the database? I've seen these kind of requests before, but I have always been thinking: how did they end up here?
In a well-modelled database, each table models a unique entity and each column models a unique attribute of that entity. Seen from this perspective, this kind of searches are a little funny. Of course, one situation could be that you are new to the database, and have not learnt the model yet. All you know is that they store cucumbers somewhere in the database, and in that case you may want to search for "cucumber" with a very wide net. Then again, those kind of queries should still be rare enough that you can accept that they take some time.
These sort of queries will be slow, since not only does every LIKE require a scan, but SQL Server also needs to scan the full string when you have leading and closing wild cards, and with a Windows collation or nvarchar, this will be quite expensive.
There are two ways to speed this up, though. One is to slap on a bunch of full-text indexes, but that is quite heavy artillery.
Here is a more moderate trick, which still will be slow, but 10-12 faster than with a normal collation:
declare @text_to_find as nvarchar(max) = N'TOTS' --Type here to search content
declare @txt as nvarchar(max) = concat('%', replace(replace( replace( @text_to_find, N'[', N'[[]'), N'%', N'[%]'), N'', N'['), N'%')
declare @sql as nvarchar(max)
;
with Q as
(
select
concat(N'select ', quotename( concat(quotename(s.name), N'.', quotename(t.name)), N''''),
N' as TableName where exists( select * from ', quotename(s.name), N'.', quotename(t.name), N' where ',
string_agg( concat('upper(', cast(quotename(c.name) as nvarchar(max)), N') COLLATE Latin1_General_BIN2 like upper(@txt)'), N' or '), N')' ) as x
from sys.tables t
inner join sys.schemas s on s.schema_id = t.schema_id
inner join sys.columns c on c.object_id = t.object_id
inner join sys.types y on y.user_type_id = c.user_type_id
where y.name in (N'text', N'ntext', N'char', N'nchar', N'varchar', N'nvarchar', N'sysname', N'xml')
group by s.name, t.name
)
select @sql = string_agg(x, N' union all ')
from Q
PRINT @sql
exec sp_executesql @sql, N'@txt nvarchar(max)', @txt = @txt
select @@ROWCOUNT as 'Total tables'
The trick is to cast the search column to a binary collation, and then applying upper
on both the search column and the search string to roll your own case-insensitivity.