2009-08-31 1 views
11

ho costruito una query T-SQL come questo:Le preoccupazioni per SQL Server 2008 Full Text Search

DECLARE @search nvarchar(1000) = 'FORMSOF(INFLECTIONAL,hills) AND FORMSOF(INFLECTIONAL,print) AND FORMSOF(INFLECTIONAL,emergency)' 

SELECT * FROM Tickets 
WHERE ID IN (
       -- unioned subqueries using CONTAINSTABLE 
          ... 
      ) 

La GUI per questa ricerca sarà una pagina aspx con un unico testo in cui l'utente può cercare.

Ho in programma di costruire il termine di ricerca in qualche modo come nell'esempio sopra (@search).

ho qualche preoccupazione, però:

  • È il termine di ricerca esempio precedente il modo migliore oppure solo per includere le inflessioni di tutte le parole nella ricerca?
  • Devo separare le parole e costruire il termine di ricerca in C# o T-SQL. Tendo ad inclinarmi verso C# per decisioni/loop/costruzione, ma voglio la tua opinione.
  • Odio creare SQL in modo dinamico a causa del rischio di iniezione. Come posso evitare questo?
  • Devo utilizzare FREETEXTTABLE invece? C'è un modo per far sì che FREETEXT cerchi TUTTE le parole invece di QUALSIASI?
  • In generale, in quale altro modo faresti questo?

risposta

3

Recentemente ho utilizzato la ricerca full-text, quindi cercherò di rispondere ad alcune delle vostre domande.

• "Odio costruire sql in modo dinamico a causa del rischio di iniezione, come posso evitare questo?"

ho usato un metodo sanitize come questo:

static string SanitizeInput(string searchPhrase) 
    { 
     if (searchPhrase.Length > 200) 
      searchPhrase = searchPhrase.Substring(0, 200); 

     searchPhrase = searchPhrase.Replace(";", " "); 
     searchPhrase = searchPhrase.Replace("'", " "); 
     searchPhrase = searchPhrase.Replace("--", " "); 
     searchPhrase = searchPhrase.Replace("/*", " "); 
     searchPhrase = searchPhrase.Replace("*/", " "); 
     searchPhrase = searchPhrase.Replace("xp_", " "); 

     return searchPhrase; 
    } 

• Dovrei usare FREETEXTTABLE invece? C'è un modo per far sì che FREETEXT cerchi TUTTE le parole invece di QUALSIASI?

Ho usato FREETEXTTABLE, ma avevo bisogno di una parola. Per quanto ne abbia letto (e ne ho letto parecchio), devi usare CONTAINSTABLE per cercare TUTTE le parole o combinazioni diverse. FREETEXTTABLE sembra essere la soluzione più leggera, ma non quella da scegliere quando si desidera una personalizzazione più profonda.

0

Nell'esempio si dispone della variabile @search già definita. Come regola generale, non è necessario includere il testo dinamicamente concatenato in SQL raw, a causa del rischio di iniezione. Tuttavia, è possibile impostare il valore di @search nell'oggetto comando di chiamata dall'applicazione. Ciò nega completamente il rischio di attacchi per iniezione.

Suggerirei la costruzione del termine di ricerca in C#; passando il termine di ricerca finale come parametro come già accennato.

Per quanto ricordo, FREETEXTTABLE utilizza i word breaker per decomporre completamente i termini di ricerca nei loro singoli componenti. Tuttavia, l'operatore FREETEXTTABLE decompone automaticamente le parole in equivalenti flessionali, quindi non sarà necessario costruire un operatore complesso CONTAINSTABLE se si decide di utilizzarlo.

È possibile INNER JOIN i risultati di più query FREETEXTTABLE per produrre un risultato equivalente AND.

2

Dan, mi piace il tuo metodo SanitizeInput.L'ho rifattorizzato per renderlo più compatto e migliorare le prestazioni un po '.

static string SanitizeInput(string searchPhrase, int maxLength) 
     { 
      Regex r = new Regex(@";|'|--|xp_|/\*|\*/", RegexOptions.Compiled); 
      return r.Replace(searchPhrase.Substring(0, searchPhrase.Length > maxLength ? maxLength : searchPhrase.Length), " "); 
     } 

     static string SanitizeInput(string searchPhrase) 
     { 
      const int MAX_SEARCH_PHRASE_LENGTH = 200; 
      return SanitizeInput(searchPhrase, MAX_SEARCH_PHRASE_LENGTH); 
     } 

Sono d'accordo che FREETEXTTABLE è troppo leggero di una soluzione.

0

Tutte le nostre ricerche sono su colonne nel database che hanno caratteri validi predefiniti. Il nostro algoritmo di ricerca incorpora questo con una regex che consente solo questi caratteri predefiniti. Per questo motivo, la ricerca nella stringa di ricerca non è necessaria. La nostra regex elimina ogni tentativo di iniezione nel codice web (asp & aspx). Per i commenti standard degli utenti, utilizziamo l'escaping che modifica tutti i caratteri che possono essere utilizzati per il danno in SQL, ASP, ASPX, & Javascript.
Il sito TransStar http://latranstar.tann.com/ utilizza un modulo esteso di Soundex per cercare nomi di strade, indirizzi e città ovunque nella California meridionale. Il Soundex di per sé elimina ogni necessità di codice anti-iniezione poiché opera solo su caratteri alfa.