Применить как ко всем столбцам без указания всех имен столбцов? - PullRequest
20 голосов
/ 11 января 2012

Я оказался в положении, когда я работаю с незнакомой базой данных, в которой имеется огромное количество столбцов для каждой таблицы. У меня есть представление о том, какие данные я ищу, но я не знаю, в каком столбце они находятся, и мне нужно использовать like, чтобы найти точные данные, которые мне нужны (и мне приходится повторять эту задачу для нескольких наборов данных).

Есть ли способ применить как декартовой выбор?

Следующее должно объяснить, что я хотел бы сделать немного лучше (даже если это синтаксически смешно):

select 
    *
from    
    a_table
where   
    * like '%x%'

редактировать :

Обратите внимание, что я не собираюсь использовать выбор карт в каких-либо отчетах - его цель здесь состоит в том, чтобы помочь мне определить соответствующие столбцы, которые мне нужно будет включить в мои запросы, и помочь мне ознакомиться с базой данных .

Ответы [ 7 ]

16 голосов
/ 11 января 2012

Обычно - это невозможно разумным способом ( без копания в метаданных БД ), но если вы знаете имена столбцов, вы можете использовать такой трюк:

select 
    YourTable.*
FROM YourTable
JOIN
( 
    select 
      id, 
      ISNULL(column1,'')+ISNULL(Column2,'')+...+ISNULL(ColumnN,'') concatenated
      FROM YourTable
) T ON T.Id = YourTable.Id
where   t.concatenated like '%x%'

OR

если вы ищете слова - используйте возможности FTS, потому что верхний запрос является убийцей производительности

7 голосов
/ 11 января 2012

Подобное обсуждение здесь .

Прямого пути нет, и вы должны сделать это следующим образом:

SELECT Name, Age, Description, Field1, Field2
FROM MyTable
WHERE Name LIKE 'Something%' OR Description LIKE 'Something%' OR Field1 LIKE 'Something%' OR Field2 LIKE 'Something%'

Одним из решений, опубликованных на этом форуме, было следующее: используется динамический SQL:

CREATE PROCEDURE TABLEVIEWSEARCH @TABLENAME        VARCHAR(60),@SEARCHSTRING VARCHAR(50)
-- EXEC TABLEVIEWSEARCH 'GMACT','demo'
-- EXEC TABLEVIEWSEARCH 'TABLEORVIEW','TEST'
AS
SET NOCOUNT ON
DECLARE @SQL      VARCHAR(500),
@COLUMNNAME       VARCHAR(60)

CREATE TABLE #RESULTS(TBLNAME VARCHAR(60),COLNAME VARCHAR(60),SQL VARCHAR(600))
SELECT 
  SYSOBJECTS.NAME AS TBLNAME,
  SYSCOLUMNS.NAME AS COLNAME,
  TYPE_NAME(SYSCOLUMNS.XTYPE) AS DATATYPE
  INTO #TMPCOLLECTION
    FROM SYSOBJECTS
      INNER JOIN SYSCOLUMNS ON SYSOBJECTS.ID=SYSCOLUMNS.ID
    WHERE SYSOBJECTS.NAME = @TABLENAME
    AND TYPE_NAME(SYSCOLUMNS.XTYPE) IN ('VARCHAR','NVARCHAR','CHAR','NCHAR')
    ORDER BY TBLNAME,COLNAME

DECLARE C1 CURSOR FOR 
SELECT COLNAME FROM #TMPCOLLECTION ORDER BY COLNAME
OPEN C1
FETCH NEXT FROM C1 INTO @COLUMNNAME
WHILE @@FETCH_STATUS <> -1
    BEGIN
        --SET @SQL = 'SELECT ''' + @TABLENAME + ''' AS TABLENAME,''' + @COLUMNNAME + ''' AS COLUMNNAME,* FROM ' + @TABLENAME + ' WHERE ' +  @COLUMNNAME + ' LIKE ''%' + @SEARCHSTRING + '%'''
        SET @SQL = 'IF EXISTS(SELECT * FROM [' + @TABLENAME + '] WHERE [' +  @COLUMNNAME + '] LIKE ''%' + @SEARCHSTRING + '%'') INSERT INTO #RESULTS(TBLNAME,COLNAME,SQL) VALUES(''' + @TABLENAME + ''',''' +  @COLUMNNAME + ''','' SELECT * FROM  [' + @TABLENAME + ']  WHERE [' + @COLUMNNAME + '] LIKE  ''''%' + @SEARCHSTRING + '%'''''') ;'
        PRINT @SQL
        EXEC (@SQL)
FETCH NEXT FROM C1 INTO @COLUMNNAME
    END
CLOSE C1
DEALLOCATE C1

SELECT * FROM #RESULTS

GO
CREATE PROCEDURE TABLEVIEWSEARCH2 @TABLENAME        VARCHAR(60),@SEARCHSTRING VARCHAR(50)
-- EXEC TABLEVIEWSEARCH2 'GMACT','SOURCE'
-- EXEC TABLEVIEWSEARCH2 'TABLEORVIEW','TEST'
AS
BEGIN
SET NOCOUNT ON
DECLARE @FINALSQL      VARCHAR(MAX),
@COLUMNNAMES       VARCHAR(MAX)
SET @FINALSQL = 'SELECT * FROM [' + @TABLENAME + '] WHERE 1 = 2 '
SELECT 
    @FINALSQL = @FINALSQL + ' OR [' + SYSCOLUMNS.NAME + '] LIKE ''%' + @SEARCHSTRING + '%'' '

    FROM SYSCOLUMNS 
    WHERE OBJECT_NAME(id) = @TABLENAME
    AND TYPE_NAME(SYSCOLUMNS.XTYPE) IN ('VARCHAR','NVARCHAR','CHAR','NCHAR')
    ORDER BY COLID

PRINT @FINALSQL
EXEC(@FINALSQL)
END --PROC

Я проверил это на таблице сотрудников, содержащей следующие данные:

enter image description here

Выполнение следующего оператора

EXEC TABLEVIEWSEARCH2 'employee','2'

В результате:

2   1   eng2
4   2   dev2
7   3   sup2
9   4   qa2

Я подумал, что приведу еще один пример этого в действии, поскольку в приведенной выше таблице Emp есть только одно поле для поиска данных.

Это таблица задач из базы данных todo: enter image description here

Поиск фразы en: (выделены ячейки, в которых сопоставляются данные)

EXEC TABLEVIEWSEARCH2 'task','en'

enter image description here

4 голосов
/ 11 января 2012

Нет, это невозможно с SQL. Это также будет считаться плохой практикой, хотя я вижу вариант использования в вашем сценарии. Лучше всего написать его на своем любимом языке, получив список всех имен столбцов и затем выполнить отдельный запрос с одинаковым значением для каждого столбца или один большой запрос, который объединяет все это:

select
    *
from
    a
where
    a.column_1 like '%blah%' or 
    a.column_2 like '%blah%';

или отдельные запросы:

select
    *
from 
    a 
where 
    a.column_1 like '%blah%'

select
    *
from 
    a 
where 
    a.column_2 like '%blah%'
3 голосов
/ 11 января 2012

Вы можете попробовать что-то вроде этого, но если ваша таблица действительно большая, у вас могут возникнуть некоторые проблемы, потому что она создаст XML всей вашей таблицы и затем запросит XML для поисковой строки. Выходными данными являются имена столбцов, в которых находится строка.

;with C(TableXML) as
(
  select *
  from YourTable
  for xml path('T'), type
)
select distinct T.X.value('local-name(.)', 'sysname') as ColumnName
from C
  cross apply C.TableXML.nodes('/T/*') as T(X)
where T.X.value('.', 'varchar(max)') like '%x%'

http://data.stackexchange.com/stackoverflow/query/58934/new

2 голосов
/ 23 октября 2015

Спасибо, Нанда:)

Вот мой уменьшенный сценарий:

use a_database

declare 
    @TableName as nvarchar(50) = 'a_table',
    @FilterContition as nvarchar(50) = 'like ''%x%''',
    @ColumnName as nvarchar(100),
    @ColumnCursor as cursor,
    @Sql as nvarchar(4000)

set @ColumnCursor = cursor for
    select distinct c.name
    from sys.objects as o
    inner join sys.columns as c
        on o.object_id = c.object_id
    where o.name = @TableName
    and type_name(c.user_type_id) in ('VARCHAR','NVARCHAR','CHAR','NCHAR')

open @ColumnCursor
fetch next from @ColumnCursor into @ColumnName 
set @Sql = 'select * from ' + @TableName + ' where ' + @ColumnName + ' ' + @FilterContition
while @@fetch_status = 0
begin
    fetch next from @ColumnCursor into @ColumnName
    set @Sql = @Sql + ' and ' + @ColumnName + ' ' + @FilterContition
end
close @ColumnCursor
deallocate @ColumnCursor

exec(@Sql)

он использует: - динамический sql - курсор - база метаданных

0 голосов
/ 08 августа 2017

одним простым способом: 1. выберите COLUMN_NAME из INFORMATION_SCHEMA.COLUMNS, где TABLE_NAME = 'your_table'

Копировать Вставить результат в лист Excel. Ячейка B1 тип isnull (в ячейке A1 type, '') + в ячейке C1 type = A1 & B1 & C1 вЯчейка D1 Перетащите ячейки A1, C1 и D1 вниз

Скопируйте Вставить столбец D в SQL

Добавьте select * из вашей_ таблицы, где (в начале

Удалите + в конце Добавить) как '% x%' в конце выполнить

Excel твой друг!

0 голосов
/ 06 августа 2017
Create PROCEDURE dbo.sp_FindStringInTable @stringToFind VARCHAR(100), @table sysname 
AS

BEGIN TRY
   DECLARE @sqlCommand varchar(max) = 'SELECT * FROM [' + @table + '] WHERE ' 

   SELECT @sqlCommand = @sqlCommand + '[' + COLUMN_NAME + '] LIKE ''' + @stringToFind + ''' OR '
   FROM INFORMATION_SCHEMA.COLUMNS 
   WHERE TABLE_NAME = @table 
   AND DATA_TYPE IN ('char','nchar','ntext','nvarchar','text','varchar')

   SET @sqlCommand = left(@sqlCommand,len(@sqlCommand)-3)
   EXEC (@sqlCommand)
   PRINT @sqlCommand
END TRY

BEGIN CATCH 
   PRINT 'There was an error. Check to make sure object exists.'
   PRINT error_message()
END CATCH 

- затем позвоните по этому

EXEC sp_FindStringInTable 'yoursearchitem', 'tablename'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...