| Author |
Topic |
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-05 : 09:23:49
|
| I want to search a table using a stored procedure that accepts one parameter.If the parameter is 'firstname lastname' I want to search all columns for like %firstname% then like %lastname%. I would like the same functionality if there were 3,4,n words delimited by a space.Whats the best way to do this? There are no columns with lots of text. The largest column is nvarchar(65). Should I consider full text search?Thanks! |
|
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2008-09-05 : 10:24:54
|
| That makes absolutely no sense at all.Please explain your requirements more clearly, with examples, if you want assistance.Boycotted Beijing Olympics 2008 |
 |
|
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-05 : 11:02:22
|
| Sorry,Here is my table:ColleagueID int 4 PKFirstName nvarchar 100MiddleName nvarchar 100LastName nvarchar 100JobTitle nvarchar 130DepartmentName nvarchar 100DivisionName nvarchar 100Extension varchar 4The end user will have a single text box and search button where they can search all of these columns:FirstNameMiddleNameLastNameJobTitleDepartmentNameDivisionNameREQUIREMENTS:Basically I want to search all fields for each word in the search string, allowing for inexact matches (example: 'ron' matches 'Ronnie') Also, if the search string contains multiple words, returned records must match ALL words.EXAMPLES:End user search query: 'ron over'This would return the records having %ron% in ANY column AND %over% in ANY column, where % represents a wildcard.For example, the record with FirstName = 'Ronnie' & LastName = 'Overby' would be a match.End user search query: 'online'This would return the records having %online% in ANY column, where % represents a wildcard.I have never searched a table this way before and I am researching the best way to do it. Thanks in advance for any help! |
 |
|
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2008-09-05 : 11:51:19
|
| There is no best way to do this.The requirements are going to ensure that whatever you come up with is inefficient.But your best bet would probably be full text search.Boycotted Beijing Olympics 2008 |
 |
|
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-05 : 11:57:26
|
Well, if that's my "best bet", then it's the best way as far as I am concerned.Here is something I was playing with:SELECT *FROM Directory.EmployeesWHERE CONTAINS ( *, '"*ron*"' )INTERSECTSELECT *FROM Directory.EmployeesWHERE CONTAINS ( *, '"*over*"' ) This achieves the effect I want, but of course I can't actually do it this way. Can anyone offer any ideas for getting this to work with a single text box? |
 |
|
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-05 : 16:04:41
|
I created a CLR stored procedure and got this to work. Below is the code. Does anyone see any major problems with this? I think I will limit the # of allowed words coming in to keep someone from overworking the database.using System;using System.Data;using System.Data.SqlClient;using System.Data.SqlTypes;using Microsoft.SqlServer.Server;public partial class StoredProcedures{ [Microsoft.SqlServer.Server.SqlProcedure] public static void SearchEmployees( SqlString searchText ) { /* This sproc builds a sql statement from the searchText parameter. * The words in the searchtext delimited by space are split into an array. * The array is traversed and a tsql statement is constructed. * * Example: @searchText = 'ron over dwayne' * * HERE IS THE CONSTRUCTED SQL STATEMENT: * * SELECT * FROM Directory.Employees WHERE CONTAINS ( *, '"*ron*"' ) INTERSECT SELECT * FROM Directory.Employees WHERE CONTAINS ( *, '"*over*"' ) INTERSECT SELECT * FROM Directory.Employees WHERE CONTAINS ( *, '"*dwayne*"' ) * * The result set would be all rows that match EVERY WORD in the array in AT LEAST ONE COLUMN. * Wildcards are appended before and after each word. */ SqlCommand cmd = new SqlCommand(); cmd.Connection = new SqlConnection("context connection=true"); // template for sql statement; {0} is where each word will be inserted string sqlTemplate = "SELECT * FROM Directory.Employees WHERE CONTAINS ( *, '\"*{0}*\"' )"; string sql = string.Empty; // split parameter into array of words string[] searchWords = searchText.ToString().Split(' '); // iterate through array, building sql statement for (int i = 0; i < searchWords.Length; i++) { sql += string.Format(sqlTemplate, searchWords[i]); if (i != searchWords.Length - 1) { sql += " INTERSECT "; // on all but last pass, INTERSECT is inserted into statement } } // set commandtext of command to sql statement we just built cmd.CommandText = sql; //Get a reference to the SqlPipe for this calling context SqlPipe pipe = SqlContext.Pipe; // do the deed cmd.Connection.Open(); pipe.Send(cmd.ExecuteReader()); cmd.Connection.Close(); }}; |
 |
|
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2008-09-05 : 16:27:37
|
| Whoever thought up CLRs at Microsoft deserves to be shot.Boycotted Beijing Olympics 2008 |
 |
|
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-06 : 11:33:16
|
| Blindman, will you just stop looking at this thread?When I get a topic reply notification, there is a tinge of excitement because I think maybe someone has something useful to say in response to my problem. And then I come on here and see more of your useless comments. You haven't helped me in the slightest.I am a relatively new developer; I don't know the best way to do many things. I search the net trying to find some guidance before I ever think about creating a thread about a given problem. If I feel like I am wasting too much time searching, when I could just ask someone more knowledgeable, I come here. So, please, if you don't have anything that will contribute to my solving a problem, why waste your time and mine?That's a rhetorical question, by the way. Don't even bother with one of your famous replies. |
 |
|
|
preethi
Starting Member
11 Posts |
Posted - 2008-09-06 : 13:46:09
|
Hi Ronnie,I Understand your worries. I have a couple of concerns over the functionality as it may scan the entire table each time a person uses this functionality. it may cripple the other procedures from using this table.However, given your scenario I have a solution:1. Create a fucntion whcih splits the string into a table. For this purpose you can write a CLR User defined function code also. It could be faster (I haven't checked it.2. Write a procedure which joins with your table for a search. The join condition is complex I suggest that you should use multiple IF conditions (if not multiple procedures) so that deifferent execution plans could be used if each statement and each will be optimized for each condition.Here is the sample code:CREATE FUNCTION dbo.GetList(@NameList nvarchar(MAX))RETURNS @RetTable Table (name nvarchar(20))ASBEGIN DECLARE @FirstPos int, @EndPos int, @Len int SELECT @Len = Len(@NameList), @FirstPos = 0 WHILE @FirstPos < @Len BEGIN SELECT @EndPos = charindex(' ', @NameList, @FirstPos + 1) IF @EndPos = 0 SELECT @EndPos = @Len + 1 INSERT INTO @RetTable VALUES (LTrim(SUBSTRING(@IDList, @FirstPos + 1, @EndPos - @FirstPos - 1))) SELECT @FirstPos = @EndPos END RETURNENDGOCREATE PROCEDURE dbo.Search (@NameList nvarchar(MAX),@Column varchar(100))ASBEGIN IF @Column = '' BEGIN SELECT <COLUMNList> FROM Directory.Employee e, dbo.GetList(@NameList) l WHERE (e.FirstName like '%'+l.name+'%' OR e.LastName like '%'+l.name+'%' OR -- the rest of the columns come here ) END IF @Column = 'FirstName' BEGIN SELECT <COLUMNList> FROM Directory.Employee e, dbo.GetList(@NameList) l WHERE (e.FirstName like '%'+l.name+'%') END-- The rest of the code comes here. ENDGOHope this helps!Cheers,Preethiviraj KulasinghamMCITP: DBA |
 |
|
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-06 : 18:50:44
|
| Thanks, preethi! I appreciate the code for the function to disect the string; it helps a lot. I also like the option to pass a column name to the search procedure. That will add some nice flexability.One question I have is about the CLR code. You said that I could write my UDF in CLR code, but the examples you provided were in TSQL. I'd just like to know what your thought on writing code to run in the CLR? I have just scratched the surface on writing code in the CLR and I am curious about the pros and cons.Thanks, again! |
 |
|
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2008-09-07 : 12:22:21
|
quote: Originally posted by ronnieoverby Blindman, will you just stop looking at this thread?
I can't help myself. It's like watching a train wreck in slow motion. Ghastly and fascinating at the same time.Boycotted Beijing Olympics 2008 |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
|
|
ronnieoverby
Starting Member
36 Posts |
Posted - 2008-09-08 : 15:20:15
|
| Thanks! I may try that.I have actually moved my thoughts to a different architechture for this application, altogther. Instead of having every search hit a procedure at the database, I am going to cache my table on the web server, and filter the cached data (a strongly typed collection of employee record objects) using LINQ to Objects. Sound ok? |
 |
|
|
|