48

Using SQL Server 2008, say I have a table called testing with 80 columns and I want to find a value called foo.

I can do:

SELECT * 
FROM testing 
WHERE COLNAME = 'foo'

Is it possible I can query all 80 columns and return all the results where foo is contained in any of the 80 columns?

starball
  • 20,030
  • 7
  • 43
  • 238
nsilva
  • 5,184
  • 16
  • 66
  • 108
  • Yes you can. You can add allo columns with `or` in your where statement. `SELECT * FROM testing where COLNAME = 'foo' or COLNAME2 = 'foo' or ....` – Jens Feb 25 '15 at 11:31
  • it can be helpful http://vyaskn.tripod.com/search_all_columns_in_all_tables.htm – Sachin Feb 25 '15 at 11:32
  • @Jens What a pain. Especially if you have thousands of tables, each with hundreds of fields, and you're not familiar with many of them. – Michael Dec 02 '21 at 17:12
  • 1
    @Michael maybe. But if you have tables with hundreds of fields, sounds like bad db design – Jens Dec 02 '21 at 19:31
  • Duplicate of: [How can I search all columns in a table?](https://stackoverflow.com/questions/7922744/how-can-i-search-all-columns-in-a-table) – 41686d6564 stands w. Palestine Apr 11 '22 at 19:59

7 Answers7

52

You can use in:

SELECT *
FROM testing 
WHERE 'foo' in (col1, col2, col3, . . . );
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • 3
    Thanks, is it possible without defining every column name? @Gordon Linoff – nsilva Feb 25 '15 at 11:31
  • 1
    @nsilva . . . Yes, but you wouldn't want to do that. One method I can think of would involve a rather complicated XML trick. You can get the list of columns from `information_schema.columns` if you are averse to typing them. – Gordon Linoff Feb 25 '15 at 11:32
  • 1
    Yes @Gordon! 'SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'testing';' -will give you all table values together. – Ataboy Josef Feb 25 '15 at 11:38
  • @eMi . . . That is a rather generic statement to make about working code. You could just try it out. – Gordon Linoff Jan 09 '20 at 20:26
  • 2
    @GordonLinoff it works if you search for the exact word "foo" but it doesn't work in a way with LIKE "%foo%". You should add that variant too. It is different and not possible with the IN. – eMi Jan 10 '20 at 10:56
  • SELECT * FROM testing WHERE col1 LIKE '%foo%' OR col2 LIKE '%foo%' ... – eMi Jan 10 '20 at 10:58
  • 4
    Oh. My. Goodness. I have been using MySQL for something like 20 years and had never realised that IN() can be used this way around. I feel silly. This has really simplified a query I just had to make. Thank you!!! – thomasrutter Apr 01 '21 at 07:03
  • 1
    This should be the accepted answer - it's by far the simplest way of doing this. – EJoshuaS - Stand with Ukraine May 17 '22 at 14:09
10

First Method(Tested) First get list of columns in string variable separated by commas and then you can search 'foo' using that variable by use of IN

Check stored procedure below which first gets columns and then searches for string:

DECLARE @TABLE_NAME VARCHAR(128)
DECLARE @SCHEMA_NAME VARCHAR(128)

-----------------------------------------------------------------------

-- Set up the name of the table here :
SET @TABLE_NAME = 'testing'
-- Set up the name of the schema here, or just leave set to 'dbo' :
SET @SCHEMA_NAME = 'dbo'

-----------------------------------------------------------------------

DECLARE @vvc_ColumnName VARCHAR(128)
DECLARE @vvc_ColumnList VARCHAR(MAX)

IF @SCHEMA_NAME =''
  BEGIN
  PRINT 'Error : No schema defined!'
  RETURN
  END

IF NOT EXISTS (SELECT * FROM sys.tables T JOIN sys.schemas S
      ON T.schema_id=S.schema_id
      WHERE T.Name=@TABLE_NAME AND S.name=@SCHEMA_NAME)
  BEGIN
  PRINT 'Error : The table '''+@TABLE_NAME+''' in schema '''+
      @SCHEMA_NAME+''' does not exist in this database!' 
  RETURN
 END

DECLARE TableCursor CURSOR FAST_FORWARD FOR
SELECT   CASE WHEN PATINDEX('% %',C.name) > 0 
     THEN '['+ C.name +']' 
     ELSE C.name 
     END
FROM     sys.columns C
JOIN     sys.tables T
ON       C.object_id  = T.object_id
JOIN     sys.schemas S
ON       S.schema_id  = T.schema_id
WHERE    T.name    = @TABLE_NAME
AND      S.name    = @SCHEMA_NAME
ORDER BY column_id


SET @vvc_ColumnList=''

OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @vvc_ColumnName

WHILE @@FETCH_STATUS=0
  BEGIN
   SET @vvc_ColumnList = @vvc_ColumnList + @vvc_ColumnName

    -- get the details of the next column
   FETCH NEXT FROM TableCursor INTO @vvc_ColumnName

  -- add a comma if we are not at the end of the row
   IF @@FETCH_STATUS=0
    SET @vvc_ColumnList = @vvc_ColumnList + ','
   END

 CLOSE TableCursor
 DEALLOCATE TableCursor

-- Now search for `foo`


SELECT *
FROM testing 
WHERE 'foo' in (@vvc_ColumnList );

2nd Method In sql server you can get object id of table then using that object id you can fetch columns. In that case it will be as below:

Step 1: First get Object Id of table

select * from sys.tables order by name    

Step 2: Now get columns of your table and search in it:

 select * from testing where 'foo' in (select name from sys.columns  where  object_id =1977058079)

Note: object_id is what you get fetch in first step for you relevant table

Ubaid Ashraf
  • 1,049
  • 5
  • 15
  • 43
  • I tested it and it works, just give it a run @nsilva – Ubaid Ashraf Feb 25 '15 at 12:01
  • 2
    Hi, I've just tried, I did a SELECT * FROM testing to find a value I want to return to check, but running the script just returned nothing. I've changed table name, and SELECT at the bottom to match the database i'm checking, there's nothing else I need to change right? – nsilva Feb 25 '15 at 12:26
  • you just need to keep in mind that schemna name in this case dbo and table name are given correctly. I am giving table and schemna at start of procedure. Alternatively you can try 2nd method – Ubaid Ashraf Feb 25 '15 at 12:32
  • If you go for first method, you need to create stored procedure!! @nsilva But second method it too easy, just check that also – Ubaid Ashraf Feb 25 '15 at 12:33
  • 2
    Object names are Unicode, use NVARCHAR. Do not write in-house quoting a-la `'['+ C.name +']' `, use [`QUOTENAME`](https://msdn.microsoft.com/en-us/library/ms176114.aspx), you are not handling properly escape sequences in quoted identifiers. Always quote a name, not only if it contains space, there are many more problem chars (`\n`, `\t` obvious ones, but there a whole lot more in Unicode space). – Remus Rusanu Feb 25 '15 at 13:06
  • 1
    Apart from issues mentioned by @RemusRusanu, the "first method" does not work in principle. It (badly) generates a string that contains comma-separated column names and uses that string in the `IN` clause which makes no sense and is equivalent to `WHERE 'foo' = 'column1,column2,column3'`, which is not going to find anything. It does make sense to build comma-separated list of columns, but it then must be used to [build dynamic SQL](https://stackoverflow.com/a/2944612/11683). – GSerg Aug 16 '17 at 20:47
1

You can use in and you can get the column names dynamically and pass them to IN clause by making sql string and executing it using execute sp_executesql.

declare @sql nvarchar(2100)
declare @cols nvarchar(2000)
declare @toSearch nvarchar(200)
declare @tableName nvarchar(200)
set @tableName = 'tbltemp'
set @toSearch = '5' 
set @cols =(
 SELECT LEFT(column_name, LEN(column_name) - 1)
FROM (
    SELECT column_name + ', '
    FROM INFORMATION_SCHEMA.COLUMNS where table_name = @tableName
    FOR XML PATH ('')
  ) c (column_name )
)
set @sql = 'select * from tbltemp where '''+ @toSearch + '''  in (' + @cols + ')';  
execute sp_executesql @sql
Adil
  • 146,340
  • 25
  • 209
  • 204
1

I took the idea from ubaid ashraf's answer, but made it actually work. Just change MyTableName here:

SELECT STUFF((
    SELECT ', ' + c.name 
    FROM sys.columns  c
    JOIN sys.types AS t ON c.user_type_id=t.user_type_id
    WHERE t.name != 'int'  AND t.name != 'bit' AND t.name !='date' AND t.name !='datetime'
        AND object_id =(SELECT object_id FROM sys.tables WHERE name='MyTableName')
    FOR XML PATH('')),1,2,'')

You could tweak it to your needs and add or remove conditions from the where column (the 't.name != 'int' AND t.name != 'bit' etc. part), e.g. add 't.name != 'uniqueidentifier'' to avoid getting Conversion failed when converting the varchar value 'myvalue' to data type int type of errors..

Then copy paste the result into this query (otherwise it didn't work):

SELECT * from MyTableName where 'foo' in (COPY PASTE PREVIOUS QUERY RESULT INTO HERE)
Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
BornToCode
  • 9,495
  • 9
  • 66
  • 83
  • did not work for me. it was like --> ... where 1 in (calculation1, calculation2) – Eray Balkanli Jan 16 '19 at 14:34
  • @ErayBalkanli - I just verified again and it does work. I don't understand from your comment what it did not work. If you could make it more clear I can try to help.. – BornToCode Jan 17 '19 at 10:25
1

I think this is one of the best ways of doing it

SELECT * FROM sys.columns  a
inner join 
(
SELECT object_id
FROM sys.tables 
where 
type='U'--user table
and name like 'testing' 
) b on a.object_id=b.object_id
WHERE a.name like '%foo%'
yaritaft
  • 56
  • 3
0
--Obtain object_id
SELECT object_id FROM sys.tables WHERE name = <your_table>


--look for desired value in specified columns using below syntax
SELECT * FROM <your_table> WHERE <VALUE_YOU_SEARCH_FOR> in
(SELECT name FROM sys.tables WHERE object_id = <your_table_object_id>
and name like '<if_you_have_multiple_columns_with_same_name_pattern>')
marcin2x4
  • 1,321
  • 2
  • 18
  • 44
0

I've worked with BornToCode's answer and this script generates the queries to find a value in all columns of type varchar for any view (can be table) of the database:

DECLARE @id INT
declare @name nvarchar(30)
DECLARE @getid CURSOR
declare @value nvarchar(30)
set @value = 'x'

SET @getid = CURSOR FOR
SELECT object_id,name
FROM   sys.views

OPEN @getid
FETCH NEXT
FROM @getid INTO @id, @name
WHILE @@FETCH_STATUS = 0
BEGIN

---------

SELECT  'SELECT * from ' + @name + ' where ''' + @value + ''' in (' + 
    STUFF((
    SELECT ', ' + c.name 
    FROM sys.columns  c
    JOIN sys.types AS t ON c.user_type_id=t.user_type_id
    WHERE t.name = 'varchar'--  AND t.name != 'bit' AND t.name !='date' AND t.name !='datetime'
        AND object_id =(SELECT object_id FROM sys.views WHERE name=@name)
    FOR XML PATH('')),1,2,'')
    + ')' as 'query'

------
FETCH NEXT
    FROM @getid INTO @id, @name

END

CLOSE @getid
DEALLOCATE @getid
Murilo Maciel Curti
  • 2,677
  • 1
  • 21
  • 26