Foros del Web » Programación para mayores de 30 ;) » .NET »

Crear criterios de consulta para Acess

Estas en el tema de Crear criterios de consulta para Acess en el foro de .NET en Foros del Web. Hola a todos. Estoy creando un buscador que se apoya en una base de datos Access. Los campos a consultar son varios y los criterios ...
  #1 (permalink)  
Antiguo 18/07/2005, 07:03
Avatar de Bravenap  
Fecha de Ingreso: noviembre-2002
Ubicación: Los Arroyos, El Escorial, Madrid
Mensajes: 2.084
Antigüedad: 21 años, 5 meses
Puntos: 4
Crear criterios de consulta para Acess

Hola a todos. Estoy creando un buscador que se apoya en una base de datos Access. Los campos a consultar son varios y los criterios también pueden variar. Por ejemplo:

El usuario escribe en el campo "Nombre" lo siguiente
Cita:
MANOLO .O JOSÉ .Y .NO PEPE
Con lo que la consulta quedaría:

Cita:
SELECT *
FROM tabla
WHERE
(
tabla.Nombre LIKE '*MANOLO*' OR
tabla.Nombre LIKE '*JOSÉ*' AND NOT
tabla.Nombre LIKE '*PEPE*'
)
De momento tengo este código:

Código:
    Dim nombre As String = preparaCriterio(preparaCadena(Me.txtNombre.Text),"Nombre")

    .....

    Private Function preparaCadena(ByVal cadena As String) As String

        Dim regExp As System.Text.RegularExpressions.Regex
        cadena = cadena.Trim
        cadena = cadena.ToUpper
        Do While cadena.IndexOf("  ") <> -1
            cadena = cadena.Replace("  ", " ")
        Loop
        cadena = cadena.Replace(".O", "|")
        cadena = cadena.Replace(".Y", "&")
        cadena = cadena.Replace(".Y .NO", "¬")
        cadena = regExp.Replace(cadena, "[AÁ]", "[AÁ]")
        cadena = regExp.Replace(cadena, "[EÉ]", "[EÉ]")
        cadena = regExp.Replace(cadena, "[IÍ]", "[IÍ]")
        cadena = regExp.Replace(cadena, "[OÓ]", "[OÓ]")
        cadena = regExp.Replace(cadena, "[UÚ]", "[UÚ]")
        Return cadena

    End Function

    Private Function preparaCriterio(ByVal cadena As String, ByVal campo As String) As String

        campo += " LIKE "
        If cadena.StartsWith("|") Or cadena.StartsWith("&") Or cadena.StartsWith("¬") Then
            cadena = cadena.Substring(1)
        End If
        '********************
        'SIN HACER:
        'Aquí hay que separar cada palabra o conjunto de palabras
        'por los operadores
        '********************
        cadena = cadena.Replace("¬", " AND NOT " & campo)
        cadena = cadena.Replace("|", " OR " & campo)
        cadena = cadena.Replace("&", " AND " & campo)
        Return cadena

    End Function
Lo que está en verde es lo que me tiene bloqueado. Alguna ayuda.

Gracias y un saludo.
__________________
¡¡NO A LA GUERRA!!
Si ponemos a nuestros mensajes títulos adecuados, la gente se animará más a abrirlos y resultarán más útiles en las busquedas. ¡No a los ayuuudaaa, urgenteee y similares!
  #2 (permalink)  
Antiguo 18/07/2005, 10:23
Avatar de Bravenap  
Fecha de Ingreso: noviembre-2002
Ubicación: Los Arroyos, El Escorial, Madrid
Mensajes: 2.084
Antigüedad: 21 años, 5 meses
Puntos: 4
Apabullante cantidad de respuestas . Bueno, más o menos creo que lo tengo resuelto. Espero que se entienda por si le sirve a alguien. Más adelante pondré la cadena de consulta completa para que os echéis a llorar, sobre todo porque tengo que adapatar la función también para las fechas . Yo por mi parte montaré un fiesta si lo consigo. Un saludo.

Código:
    Private Function preparaCriterio(ByVal cadena As String, ByVal campo As String) As String

        campo += " LIKE "
        If cadena.StartsWith("|") Or cadena.StartsWith("&") Or cadena.StartsWith("¬") Then
            cadena = cadena.Substring(1)
        End If
        Dim operador As New ArrayList
        Dim i As Integer
        For i = 0 To cadena.Length - 1
            If cadena.Chars(i) = "|" Or cadena.Chars(i) = "&" Or cadena.Chars(i) = "¬" Then
                operador.Add(cadena.Chars(i))
            End If
        Next
        If operador.Count > 0 Then
            Dim operadores() As Char = {"|", "&", "¬"}
            Dim arrCadena() As String = cadena.Split(operadores)
            cadena = campo & "'*" & Trim(arrCadena.GetValue(0)) & "*'" & operador(0)
            For i = 1 To operador.Count - 1
                cadena += campo & "'*" & Trim(arrCadena.GetValue(i)) & "*'" & operador(i)
            Next
            cadena += campo & "'*" & Trim(arrCadena.GetValue(arrCadena.Length - 1)) & "*'"
        Else
            cadena = campo & "'*" & cadena.Trim & "*'"
        End If
        cadena = cadena.Replace("¬", " AND NOT ")
        cadena = cadena.Replace("|", " OR ")
        cadena = cadena.Replace("&", " AND ")
        Return cadena

    End Function
__________________
¡¡NO A LA GUERRA!!
Si ponemos a nuestros mensajes títulos adecuados, la gente se animará más a abrirlos y resultarán más útiles en las busquedas. ¡No a los ayuuudaaa, urgenteee y similares!
  #3 (permalink)  
Antiguo 18/07/2005, 12:15
Avatar de RootK
Moderador
 
Fecha de Ingreso: febrero-2002
Ubicación: México D.F
Mensajes: 8.004
Antigüedad: 22 años, 2 meses
Puntos: 50
Hola Bravenap, creo que te podrías ahorra código y objetos utilizando otra lógica... ademas de que nmo es necesaria usar un objeto de tipo Regex..(tambien te ahorrarias el método preparaCadena )

Podría quedarte mas o menos así tu funcion...(es solo una idea..)
Cita:
Private Function PrepareQuery(ByVal sText As String, ByVal sTableName As String) As String
Dim arrCriteries() As String = {".O", ".Y", ".NO"}
Dim arrReplacements() As String = {"OR", "AND", "NOT"}
Dim myString As String = sText.Trim 'quito los espacios si hay
Dim i As Int16 = 0
Dim iTam As Int16 = arrCriteries.Length

For i = 0 To iTam - 1
myString = myString.Replace(arrCriteries(i), arrReplacements(i))
Next

Dim myStringTemp As String = String.Empty
Dim b As Boolean = True 'verifico que sea una cadena y no un criterio
For Each sTemp As String In myString.Split(New Char() {" "})
For ix As Int16 = 0 To iTam - 1
If sTemp = arrReplacements(ix) Then b = False
Next
If b Then
myStringTemp &= " " & sTableName & " LIKE '*" & sTemp & "*' "
Else
myStringTemp &= " " & sTemp 'concateno el criterio
End If

b = True
Next

myStringTemp = "SELECT * FROM tabla WHERE ( " & myStringTemp & " )"

Return myStringTemp

End Function

Y ya la mandas a llamar por ejemplo:

Cita:
MessageBox.Show(PrepareQuery(TextBox1.Text, "Nombre"))

Y en tus arrays puedes guardar la cantidad que desees de criterios y colocar su equivalente para hacer el barrido al mismo tiempo..

Espero que te sirva.

Salu2
__________________
Nadie roba nada ya que en la vida todo se paga . . .

Exentrit - Soluciones SharePoint & Net
  #4 (permalink)  
Antiguo 19/07/2005, 02:22
Avatar de Bravenap  
Fecha de Ingreso: noviembre-2002
Ubicación: Los Arroyos, El Escorial, Madrid
Mensajes: 2.084
Antigüedad: 21 años, 5 meses
Puntos: 4
Ummm... parece buena la función. Voy a probarla. De todas formas te comento.

Lo de la expresión regular, por ejemplo [AÁ], y su reemplazo posterior en la cadena es para que busque en la base de datos las palabras con y sin tildes. Por eso los operadores los paso a símbolos para que no den problemas y que, por ejemplo, AND se me convierta en [AÁ]ND.

prepararCadena() la puedo sustituir e incluir el código en prepararCriterio(). Era una función que tenía previamente de otro proyecto y por eso estaban separadas en un principio.

Finalmente, no puedo separar la cadena en un vector en función de los espacios en blanco, porque hay criterios que no son una sola palabra sino una frase, por ejemplo, "Agricultura de montaña .Y Montes". Eso serían dos criterios y no 4: "agricultura", "de", "montaña" y "montes".

De todas formas como te digo le echaré un vistazo porque tiene muy buena pinta, aunque ya lo había resuelto de manera, eso sí, un poco precaria.

Un saludo y, como siempre, muchas gracias RootK.
__________________
¡¡NO A LA GUERRA!!
Si ponemos a nuestros mensajes títulos adecuados, la gente se animará más a abrirlos y resultarán más útiles en las busquedas. ¡No a los ayuuudaaa, urgenteee y similares!
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 17:26.