2013-08-30 12 views
6

Ich weiß, dass ich nach einem Begriff in einer Spalte in einer Tabelle in t-sql mit like %termToFind% suchen kann. Und ich weiß, dass ich alle Spalten in einer Tabelle mit dieser bekommen:Wie wähle ich Datensätze aus, die wie eine Zeichenfolge für eine Spalte in einer Tabelle sind?

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

Wie kann ich eine wie comprparison auf jeder der Spalten einer Tabelle durchführen? Ich habe einen sehr großen Tisch, so dass ich nicht einfach LIKE für jede Spalte buchstabieren kann.

+3

Wenn Sie denken, dass Sie in Zukunft solche Dinge häufig tun könnten, sollten Sie sich die Volltext-Suchfunktion von SQL Server ansehen. @ RomanPekar's XML-Ansatz funktioniert, aber es kann nicht wirklich Indizes verwenden, wird also nicht schnell sein. Das ist in Ordnung, wenn Sie dies nur gelegentlich tun, aber wenn Sie dies für Online-Benutzerabfragen benötigen, wird Ihr Server ziemlich schnell stecken bleiben. – RBarryYoung

+0

@RBarryYoung sehr wahr –

Antwort

10

Wie immer, ich werde xml dafür vorschlagen (ich würde JSON vorschlagen, wenn SQL Server native Unterstützung dafür hatte :)). Sie können versuchen, diese Abfrage zu verwenden, obwohl es nicht so gut auf große Anzahl von Zeilen durchführen konnte:

;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 Detailliertere Beispiel.

Wichtige Notiz von Alexander Fedorenko in den Kommentaren: sollte es selbstverständlich sein, dass contains Funktion Groß- und Kleinschreibung und verwendet xQuery Standard-Unicode-Codepunkt Sortierung für den String-Vergleich.

Weitere allgemeine Art und Weise wäre dynamische SQL-Lösung zu verwenden:

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 - coole Antwort. – Devart

+0

@Devart danke, dynamische SQL-Lösung hinzugefügt –

+0

IMHO: 'sys.columns' enthält keine versteckten Joins im Vergleich zu' INFORMATION_SCHEMA.COLUMNS': 'SELECT c.name FROM sys.columns c WHERE OBJECT_ID ('dbo.test') = c. [object_id] ' – Devart

1

ich hier dynamischen SQL verwenden würde.

Gesamter Kredit - diese Antwort wurde ursprünglich von einem anderen Benutzer veröffentlicht und gelöscht. Ich denke, es ist eine gute Antwort, also füge ich es wieder hinzu.

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 

Die XML-Antwort ist sauberer (ich ziehe dynamische SQL nur bei Bedarf), aber der Vorteil ist, dass es jeden Index nutzen werden Sie auf Ihrem Tisch haben, und es gibt keinen Overhead den XML-CTE bei der Konstruktion für Abfrage.

+0

Dies könnte Gegenstand der SQL-Injektion sein - deshalb habe ich sp_executesql mit Parametern verwendet –

0

Falls jemand sucht PostgreSQL Lösung:

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

werden alle Datensätze auswählen, die 'your_value' in jeder Spalte haben. Habe das mit keiner anderen Datenbank versucht.

Leider funktioniert das so, als würde man alle Spalten mit einer Textzeichenfolge kombinieren und dann nach einem Wert in dieser Zeichenfolge suchen, so dass ich keine Möglichkeit kenne, es nur mit "ganze Zelle" zu verknüpfen. Es wird immer übereinstimmen, wenn irgendein Teil einer Zelle 'Ihr_Wert' entspricht.

Verwandte Themen