2013-08-30 6 views
6

like %termToFind%を使用して、t-sqlのテーブルの1つの列にある用語を検索できることがわかりました。そして私は、私はこれで、テーブルのすべての列を取得することができます知っている:テーブル内の任意の列の文字列のようなレコードを選択するにはどうすればよいですか?

SELECT * 
FROM MyDataBaseName.INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = N'MyTableName` 

私は、テーブルの列のそれぞれに同様comprparisonを実行するにはどうすればよいですか?私は非常に大きなテーブルを持っているので、各列にLIKEを書き出すことはできません。

+3

今後、このようなことが多発していると思われる場合は、SQL Serverの全文検索機能を参照する必要があります。 @ RomanPekarのXMLアプローチはうまくいくが、実際にはインデックスを使用することはできないため、高速化はできない。これはしばらくの間だけこれをやっても問題ありませんが、オンラインのユーザークエリでこれが必要な場合は、サーバーがかなり早く落ちてしまいます。 – RBarryYoung

+0

@RBarryYoung非常に真実 –

答えて

10

いつものように、私はこれについてxmlを提案します(SQL Serverにネイティブサポートがある場合はJSONを提案します:))。あなたはそれが多数の行にありませんので、よく実行することができますが、このクエリを使用しようとすることができます:

;with cte as (
    select 
     *, 
     (select t.* for xml raw('data'), type) as data 
    from test as t 
) 
select * 
from cte 
where data.exist('data/@*[local-name() != "id" and contains(., sql:variable("@search"))]') = 1 

より詳細な例についてはsql fiddle demoを参照してください。コメント欄でAlexander Fedorenkoによって

重要注:contains関数は大文字と小文字が区別され、文字列の比較のためのXQueryデフォルトのUnicodeコードポイント照合を使用していることを理解すべきです。私はここに、動的SQLを使用したい

declare @search nvarchar(max) 
declare @stmt nvarchar(max) 

select @stmt = isnull(@stmt + ' or ', '') + quotename(name) + ' like @search' 
from sys.columns as c 
where c.[object_id] = object_id('dbo.test') 
-- 
-- also possible 
-- 
-- select @stmt = isnull(@stmt + ' or ', '') + quotename(column_name) + ' like @search' 
-- from INFORMATION_SCHEMA.COLUMNS 
-- where TABLE_NAME = 'test' 

select @stmt = 'select * from test where ' + @stmt 

exec sp_executesql 
    @stmt = @stmt, 
    @params = N'@search nvarchar(max)', 
    @search = @search 

sql fiddle demo

+1

+1 - クールな答え。 – Devart

+0

@Devartありがとう、動的SQLソリューションを追加しました –

+0

IMHO: 'sys.columns'は' INFORMATION_SCHEMA.COLUMNS'と比較して隠しジョインを含んでいません: 'SELECT c.name FROM sys.columns c WHERE OBJECT_ID( 'dbo.test' )= c。[object_id] ' – Devart

1

より一般的な方法は、動的SQLのソリューションを使用することです。

フルクレジット - この回答は他のユーザーによって最初に投稿され、削除されました。私はそれが良い答えだと思うので、私はそれを再び追加しています。

DECLARE @sql NVARCHAR(MAX); 
DECLARE @table NVARCHAR(50); 
DECLARE @term NVARCHAR(50); 

SET @term = '%term to find%'; 
SET @table = 'TableName'; 
SET @sql = 'SELECT * FROM ' + @table + ' WHERE ' 

SELECT @sql = @sql + COALESCE('CAST('+ column_name 
    + ' as NVARCHAR(MAX)) like N''' + @term + ''' OR ', '') 
FROM INFORMATION_SCHEMA.COLUMNS WHERE [TABLE_NAME] = @table 

SET @sql = @sql + ' 1 = 0' 
SELECT @sql 
EXEC sp_executesql @sql 

XMLの答えはきれいです(私は必要なときだけ、動的SQLを好む)が、この利点は、それがあなたのテーブルの上にあなたが持っているすべてのインデックスを利用することで、用のXMLのCTEを構築するにはオーバーヘッドがありません照会。

+0

これはSQLインジェクションの対象になる可能性があります。そのため、sp_executesqlをパラメータとともに使用しています –

0

場合、誰かがPostgreSQLのソリューションを探しています:

SELECT * FROM table_name WHERE position('your_value' IN (table_name.*)::text)>0 

は、任意の列の「your_value」を持つすべてのレコードを選択します。他のデータベースでこれを試してみませんか?

残念ながら、これはすべての列をテキスト文字列に結合してから、その文字列の値を検索するので、「セル全体」に一致させる方法はわかりません。セルのいずれかの部分が 'your_value'と一致すると、常に一致します。

関連する問題