Buscar el underscore con Like

16/08/2008 - 16:37 por Carlos | Informe spam
Quiero hacer una busqueda con like:

select campos... from tabla where campo1 like '%_%

para encontrar los campo1's que contengan un underscore pero resulta que el
underscore es un comodin reservado que se usa para reemplazar cualquier
caracter.

Como hago para configurar esta condicion ?

Gracias

Preguntas similare

Leer las respuestas

#1 Alejandro Mesa
17/08/2008 - 00:56 | Informe spam
Carlos,

1 - Puedes encerrar el underscore entre corchetes, lo cual indica el
caracter a buscar y le quita el significado como comodin de busqueda.

select c1
from (select 'table_con_underscore' as c1 union all select
'tablasinunderscore') as t
where c1 like '%[_]%'

2 - Puedes usar la clausula ESCAPE para indicar que no se considere ese
caracter de la forma comun.

select c1
from (select 'table_con_underscore' as c1 union all select
'tablasinunderscore') as t
where c1 like '%\_%' escape '\'

A pesar de que ambos metodos generan el mismo resultado, el segundo metodo
tiene el incoveniente de que evita que el optimizador use las estadisticas de
cadena en un indice por una columna char / varchar / nchar / nvarchar, cuando
se usa un patron de busqueda que usa el comodin % en el inicio de la cadena,
como '%\_%'. Esta facilidad se introdujo en SQL Server 2005.

Fijate que diferente los planes de ejecucion de estas dos sentencias.

use AdventureWorks
go

sp_helpindex 'Person.Person'
go

dbcc show_statistics ('Person.Person',
'IX_Person_LastName_FirstName_MiddleName') with STAT_HEADER
go

set showplan_text on
go

select *
from Person.Person
where LastName like '%[_]%'
go

select *
from Person.Person
where LastName like '%\_%' escape '\'
go

set showplan_text off
go

Resultado:


Plan 1

|--Nested Loops(Inner Join, OUTER
REFERENCES:([AdventureWorks2008].[Person].[Person].[BusinessEntityID]))
|--Index
Scan(OBJECT:([AdventureWorks2008].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]),
WHERE:([AdventureWorks2008].[Person].[Person].[LastName] like N'%[_]%'))
|--Clustered Index
Seek(OBJECT:([AdventureWorks2008].[Person].[Person].[PK_Person_BusinessEntityID]),
SEEK:([AdventureWorks2008].[Person].[Person].[BusinessEntityID]=[AdventureWorks2008].[Person].[Person].[BusinessEntityID]) LOOKUP ORDERED FORWARD)

Plan 2

|--Clustered Index
Scan(OBJECT:([AdventureWorks2008].[Person].[Person].[PK_Person_BusinessEntityID]),
WHERE:([AdventureWorks2008].[Person].[Person].[LastName] like N'%\_%' escape
N'\' ))


Si te fijas en el resultado de el comando DBCC, notaras que la columna
"String Index" tiene valor "YES", lo cual indica que se mantienen
estadisticas sobre las diferentes valores de la columna "LastName".

Este indice no cubre todas las columnas referenciadas por la sentencia
"select", ya que usa "*", lo cual referencia todas las columnas de la tabla,
mientras que las unicas columnas que cubre el indice son [LastName],
[FirstName], y [MiddleName], por lo que SQL Server necesita ir de todas
maneras al indice clustered para traer toda la data necesaria. Ahora, se
puede escanear todo el indice clustered para encontrar las filas deseadas o
escanear el indice mencionado (el scan se debe a que se usa "%" como inicio
de el patron de busqueda), el cual es mas angosto y menos costoso de scanear,
si las filas que cumplen con la condicion son pocas (esto se sabe por las
estadisticas indicadas anteriormente) entonces se escanea el indice
nonclustered, se toma la clave de la fila en el indice clustered y se accesa
el indice clustered, usando una operacion "seek", para traer el resto de la
data.

Fijate que ese es el compartamiento para la sentencia que usa el patron
'%[_]%', no asi la sentencia que usa la clausula o palabra clave "escape".


AMB


"Carlos" wrote:

Quiero hacer una busqueda con like:

select campos... from tabla where campo1 like '%_%

para encontrar los campo1's que contengan un underscore pero resulta que el
underscore es un comodin reservado que se usa para reemplazar cualquier
caracter.

Como hago para configurar esta condicion ?

Gracias


Respuesta Responder a este mensaje
#2 Alejandro Mesa
17/08/2008 - 01:15 | Informe spam
Dejame aclarar que las estadisticas a las que hago referencia, no son las
estadisticas normales que se mantienen sobre los valores de la primara
columna de la clave de el indice, sino otras estadisticas que se llevan sobre
diferentes subcadenas existentes en la primera columna de la clave de el
indice cuando esta es char / varchar / nchar / nvarchar.

Aca pueden leer sobre el tema.

Statistics Used by the Query Optimizer in Microsoft SQL Server 2005
http://www.microsoft.com/technet/pr...stats.mspx


AMB



"Alejandro Mesa" wrote:

Carlos,

1 - Puedes encerrar el underscore entre corchetes, lo cual indica el
caracter a buscar y le quita el significado como comodin de busqueda.

select c1
from (select 'table_con_underscore' as c1 union all select
'tablasinunderscore') as t
where c1 like '%[_]%'

2 - Puedes usar la clausula ESCAPE para indicar que no se considere ese
caracter de la forma comun.

select c1
from (select 'table_con_underscore' as c1 union all select
'tablasinunderscore') as t
where c1 like '%\_%' escape '\'

A pesar de que ambos metodos generan el mismo resultado, el segundo metodo
tiene el incoveniente de que evita que el optimizador use las estadisticas de
cadena en un indice por una columna char / varchar / nchar / nvarchar, cuando
se usa un patron de busqueda que usa el comodin % en el inicio de la cadena,
como '%\_%'. Esta facilidad se introdujo en SQL Server 2005.

Fijate que diferente los planes de ejecucion de estas dos sentencias.

use AdventureWorks
go

sp_helpindex 'Person.Person'
go

dbcc show_statistics ('Person.Person',
'IX_Person_LastName_FirstName_MiddleName') with STAT_HEADER
go

set showplan_text on
go

select *
from Person.Person
where LastName like '%[_]%'
go

select *
from Person.Person
where LastName like '%\_%' escape '\'
go

set showplan_text off
go

Resultado:


Plan 1

|--Nested Loops(Inner Join, OUTER
REFERENCES:([AdventureWorks2008].[Person].[Person].[BusinessEntityID]))
|--Index
Scan(OBJECT:([AdventureWorks2008].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]),
WHERE:([AdventureWorks2008].[Person].[Person].[LastName] like N'%[_]%'))
|--Clustered Index
Seek(OBJECT:([AdventureWorks2008].[Person].[Person].[PK_Person_BusinessEntityID]),
SEEK:([AdventureWorks2008].[Person].[Person].[BusinessEntityID]=[AdventureWorks2008].[Person].[Person].[BusinessEntityID]) LOOKUP ORDERED FORWARD)

Plan 2

|--Clustered Index
Scan(OBJECT:([AdventureWorks2008].[Person].[Person].[PK_Person_BusinessEntityID]),
WHERE:([AdventureWorks2008].[Person].[Person].[LastName] like N'%\_%' escape
N'\' ))


Si te fijas en el resultado de el comando DBCC, notaras que la columna
"String Index" tiene valor "YES", lo cual indica que se mantienen
estadisticas sobre las diferentes valores de la columna "LastName".

Este indice no cubre todas las columnas referenciadas por la sentencia
"select", ya que usa "*", lo cual referencia todas las columnas de la tabla,
mientras que las unicas columnas que cubre el indice son [LastName],
[FirstName], y [MiddleName], por lo que SQL Server necesita ir de todas
maneras al indice clustered para traer toda la data necesaria. Ahora, se
puede escanear todo el indice clustered para encontrar las filas deseadas o
escanear el indice mencionado (el scan se debe a que se usa "%" como inicio
de el patron de busqueda), el cual es mas angosto y menos costoso de scanear,
si las filas que cumplen con la condicion son pocas (esto se sabe por las
estadisticas indicadas anteriormente) entonces se escanea el indice
nonclustered, se toma la clave de la fila en el indice clustered y se accesa
el indice clustered, usando una operacion "seek", para traer el resto de la
data.

Fijate que ese es el compartamiento para la sentencia que usa el patron
'%[_]%', no asi la sentencia que usa la clausula o palabra clave "escape".


AMB


"Carlos" wrote:

> Quiero hacer una busqueda con like:
>
> select campos... from tabla where campo1 like '%_%
>
> para encontrar los campo1's que contengan un underscore pero resulta que el
> underscore es un comodin reservado que se usa para reemplazar cualquier
> caracter.
>
> Como hago para configurar esta condicion ?
>
> Gracias
>
>
Respuesta Responder a este mensaje
#3 Carlos
18/08/2008 - 22:31 | Informe spam
Muchas gracias, problema resuelto!!!


"Alejandro Mesa" wrote in message
news:
Carlos,

1 - Puedes encerrar el underscore entre corchetes, lo cual indica el
caracter a buscar y le quita el significado como comodin de busqueda.

select c1
from (select 'table_con_underscore' as c1 union all select
'tablasinunderscore') as t
where c1 like '%[_]%'

2 - Puedes usar la clausula ESCAPE para indicar que no se considere ese
caracter de la forma comun.

select c1
from (select 'table_con_underscore' as c1 union all select
'tablasinunderscore') as t
where c1 like '%\_%' escape '\'

A pesar de que ambos metodos generan el mismo resultado, el segundo metodo
tiene el incoveniente de que evita que el optimizador use las estadisticas
de
cadena en un indice por una columna char / varchar / nchar / nvarchar,
cuando
se usa un patron de busqueda que usa el comodin % en el inicio de la
cadena,
como '%\_%'. Esta facilidad se introdujo en SQL Server 2005.

Fijate que diferente los planes de ejecucion de estas dos sentencias.

use AdventureWorks
go

sp_helpindex 'Person.Person'
go

dbcc show_statistics ('Person.Person',
'IX_Person_LastName_FirstName_MiddleName') with STAT_HEADER
go

set showplan_text on
go

select *
from Person.Person
where LastName like '%[_]%'
go

select *
from Person.Person
where LastName like '%\_%' escape '\'
go

set showplan_text off
go

Resultado:


Plan 1

|--Nested Loops(Inner Join, OUTER
REFERENCES:([AdventureWorks2008].[Person].[Person].[BusinessEntityID]))
|--Index
Scan(OBJECT:([AdventureWorks2008].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]),
WHERE:([AdventureWorks2008].[Person].[Person].[LastName] like N'%[_]%'))
|--Clustered Index
Seek(OBJECT:([AdventureWorks2008].[Person].[Person].[PK_Person_BusinessEntityID]),
SEEK:([AdventureWorks2008].[Person].[Person].[BusinessEntityID]=[AdventureWorks2008].[Person].[Person].[BusinessEntityID])
LOOKUP ORDERED FORWARD)

Plan 2

|--Clustered Index
Scan(OBJECT:([AdventureWorks2008].[Person].[Person].[PK_Person_BusinessEntityID]),
WHERE:([AdventureWorks2008].[Person].[Person].[LastName] like N'%\_%'
escape
N'\' ))


Si te fijas en el resultado de el comando DBCC, notaras que la columna
"String Index" tiene valor "YES", lo cual indica que se mantienen
estadisticas sobre las diferentes valores de la columna "LastName".

Este indice no cubre todas las columnas referenciadas por la sentencia
"select", ya que usa "*", lo cual referencia todas las columnas de la
tabla,
mientras que las unicas columnas que cubre el indice son [LastName],
[FirstName], y [MiddleName], por lo que SQL Server necesita ir de todas
maneras al indice clustered para traer toda la data necesaria. Ahora, se
puede escanear todo el indice clustered para encontrar las filas deseadas
o
escanear el indice mencionado (el scan se debe a que se usa "%" como
inicio
de el patron de busqueda), el cual es mas angosto y menos costoso de
scanear,
si las filas que cumplen con la condicion son pocas (esto se sabe por las
estadisticas indicadas anteriormente) entonces se escanea el indice
nonclustered, se toma la clave de la fila en el indice clustered y se
accesa
el indice clustered, usando una operacion "seek", para traer el resto de
la
data.

Fijate que ese es el compartamiento para la sentencia que usa el patron
'%[_]%', no asi la sentencia que usa la clausula o palabra clave "escape".


AMB


"Carlos" wrote:

Quiero hacer una busqueda con like:

select campos... from tabla where campo1 like '%_%

para encontrar los campo1's que contengan un underscore pero resulta que
el
underscore es un comodin reservado que se usa para reemplazar cualquier
caracter.

Como hago para configurar esta condicion ?

Gracias


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida