| Author |
Topic |
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-24 : 10:09:23
|
Hi,First posting, so please go easy on me !I am writing a stored procedure that takes a series of input parameters and executes a SELECT statement using them in the WHERE clause:SET @ISBN = '%' + @ISBN + '%'SET @TITLE= '%' + @TITLE+ '%'SET @AUTHOR= '%' + @AUTHOR+ '%'SELECT ISBN, TITLE, AUTHOR FROM BOOKS WHERE ISBN LIKE @ISBN OR TITLE LIKE @TITLE OR AUTHOR LIKE @AUTHOR (@ISBN, @TITLE and @AUTHOR are the input params of the stored proc)The code works fine (ish ), but the problem is that if the proc is called with empty values for any of the params, the query returns all records (as you would expect as the query would effectively be WHERE ISBN LIKE %% ....)I can understand why this is happening, but am looking for a way round this.Basically I what I'm trying to achieve is a search where the user can enter as much or as little detail as required - they might enter author details, or title details, or both, or ISBN, or .... you get the ideaI need to do this as a stored proc as I need to help prevent SQL injections, and for the same reason I really dont want to compose a string of the SELECT command and EXECUTE it within the SPI think I need to use CASE statements in the WHERE clauses - but not really sure how it would be structured.Any help with this would be very much appreciated,TIANathan |
|
|
PSamsig
Constraint Violating Yak Guru
384 Posts |
Posted - 2006-04-24 : 10:31:22
|
| Using AND instead of OR would be a start |
 |
|
|
Srinika
Master Smack Fu Yak Hacker
1378 Posts |
Posted - 2006-04-24 : 10:34:13
|
| Create ur "Where clause" Seperately and use Dynamic SQL eg....if @ISBN is not null Set @Where = ' ISBN LIKE @ISBN OR'.......... Set @Where = ' Where ' + @Where + ' 1=0'Execute ('SELECT ISBN, TITLE, AUTHOR FROM BOOKS ' + @Where )Srinika |
 |
|
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-24 : 10:48:32
|
quote: Originally posted by Srinika Create ur "Where clause" Seperately and use Dynamic SQL eg....if @ISBN is not null Set @Where = ' ISBN LIKE @ISBN OR'.......... Set @Where = ' Where ' + @Where + ' 1=0'Execute ('SELECT ISBN, TITLE, AUTHOR FROM BOOKS ' + @Where )Srinika
From my original posting:quote: I need to do this as a stored proc as I need to help prevent SQL injections, and for the same reason I really dont want to compose a string of the SELECT command and EXECUTE it within the SP
I am sure the answer to this is CASE - any other help with this ? |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
|
|
RyanRandall
Master Smack Fu Yak Hacker
1074 Posts |
Posted - 2006-04-24 : 10:58:13
|
Hi Jakes,It's not clear (to me at least) what behaviour it is you want. If you can describe it, I think think you'll get what you need. For example...a) What behaviour do you want when all inputs are 'blank'?b) What behaviour do you want when both isbn and title have values? (either one or the other or both criteria should be met?)And, by the way, what is the value of isbn when it has an 'empty value'?Ryan Randallwww.monsoonmalabar.com London-based IT consultancy Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
PSamsig
Constraint Violating Yak Guru
384 Posts |
Posted - 2006-04-24 : 10:58:41
|
| Do i really have to repeat my self ? |
 |
|
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-24 : 11:16:46
|
| Ryan,Yes, good question; I should explain my requirements a little better.OK, I have a web application that is backed by a database. Within the database is this table (BOOKS), which (no prizes for guessing ...) contains records about books !I am writing a page for the web site which allows the user to search the BOOKS table. I am presenting the following HTML input fields: title, author, and ISBNI would like the user to be able to search on any combination of fields, and I want to do OR matching (this bit is for you PSamsig !)If the user enters just something in the title field, the WHERE clause should be just WHERE TITLE LIKE @TITLE. The same goes for author and ISBNIf the user enters details into title and author, the WHERE clause should be WHERE TITLE LIKE @TITLE OR AUTHOR LIKE @AUTHORThe reason I want to use OR (PSamsig !!) is that I want to show results where the user has entered something in any 2 fields that do not match. EG. They enter 'SQL' in the title field, and 'Jakes Daddy' in the author field. I have not written any SQL books, but there are lots of SQL books in my database, as there are lots of books by the author 'Jakes Daddy'. I want to display books that match either SQL or that were written by Jakes Daddy - not nothing (which an AND would produce).(And the final comment on the AND/OR - I know the difference between the two and have decided to use OR - thank you !)Phew, out of rant mode ! Back to normal ....If the user does not enter a value for a given field on the web page, I would imagine that it is presented to the SP as an empty string rather than a null (but I dont know that for sure)Hope this helps understand my requirements a little better .... over you guys !Thanks againNathan |
 |
|
|
RyanRandall
Master Smack Fu Yak Hacker
1074 Posts |
Posted - 2006-04-24 : 11:37:20
|
Wow, you managed to write all that and I still don't see an answer to a) Ryan Randallwww.monsoonmalabar.com London-based IT consultancy Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
PSamsig
Constraint Violating Yak Guru
384 Posts |
Posted - 2006-04-24 : 11:45:32
|
| I think I get it, dynamic SQL would be the easy answer, static is something I have to think about (never yet used COALESCE() before, maybe now is the time) |
 |
|
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-24 : 11:52:08
|
quote: Originally posted by RyanRandall Wow, you managed to write all that and I still don't see an answer to a) Ryan Randallwww.monsoonmalabar.com London-based IT consultancy Solutions are easy. Understanding the problem, now, that's the hard part.
Whoops ! Yes, forgot to answer that one Basically it would never happen. The server side code of the webpage checks for any one of the input values - if all are blank it does nothing but represent the web form. If any one of the fields have a value, the stored proc is called with all fields from the form (even the 'empty' ones) as params to the SP. (hence my thinking that 'empty' values are sent as an empty string "", and not nulls)Nathan |
 |
|
|
jen
Master Smack Fu Yak Hacker
4110 Posts |
Posted - 2006-04-24 : 11:52:17
|
| pass the value of your criteria as is... append the % inside the sprocnull + any string = nullso your criteria would be field1 like null which is false--editi forgot... nullify if space... nullif(@variable,'')--------------------keeping it simple... |
 |
|
|
PSamsig
Constraint Violating Yak Guru
384 Posts |
Posted - 2006-04-24 : 11:53:48
|
| Nope, no COALESCE() this time eitherSELECT ISBN, TITLE, AUTHOR FROM BOOKS WHERE ISBN LIKE CASE WHEN @ISBN = '' THEN NULL ELSE '%' + @ISBN + '%' ENDOR TITLE LIKE CASE WHEN @TITLE = '' THEN NULL ELSE '%' + @TITLE + '%' END OR AUTHOR LIKE CASE WHEN @AUTHOR = '' THEN NULL ELSE '%' + @AUTHOR + '%' END |
 |
|
|
RyanRandall
Master Smack Fu Yak Hacker
1074 Posts |
Posted - 2006-04-24 : 12:01:19
|
There's some proof of my sig if ever I saw it. Ryan Randallwww.monsoonmalabar.com London-based IT consultancy Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-24 : 12:01:26
|
| PSamsig - that looks sweet - I knew CASE would solve it, just could not work out the syntax myself (bit of a newbie you see !)I'll give that a go shortly, but I'm sure that looks sound.Thanks (and sorry for giving you a bit of a flamer earlier on !!)Nathan |
 |
|
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-24 : 16:16:16
|
OK, me again !So, the suggestion by PSamsig is working a charm - excellent. I've added a few fields (as I do !), and my code now looks like:SELECT ISBN, TITLE, CASE WHEN AUTHOR='' THEN 'Not Specified' ELSE AUTHOR END AS AUTHOR, CASE WHEN PUBLISHER='' THEN 'Not Specified' ELSE PUBLISHER END AS PUBLISHER, FROM BOOKS WHERE ( ISBN LIKE CASE WHEN @Isbn='' THEN NULL ELSE '%'+@Isbn+'%' END OR TITLE LIKE CASE WHEN @Title='' THEN NULL ELSE '%'+@Title+'%' END OR AUTHOR LIKE CASE WHEN @Author='' THEN NULL ELSE '%'+@Author+'%' END OR PUBLISHER LIKE CASE WHEN @Publisher='' THEN NULL ELSE '%'+@Publisher+'%' END OR REVIEWS LIKE CASE WHEN @ReviewTxt='' THEN NULL ELSE '%'+@ReviewTxt+'%' END ) AND TITLE IS NOT NULL All working perfectly - but hey, I wanna add to it !I'm now passing a new parameter into the SP - @L_operator - its the logical operator for the WHERE clause, and its either 'AND' or 'OR' - basically in the query where I am currently doing an OR, I want to use @L_operator (on top of all the functionality you guys have already helped me with !)Can I work out the correct CASE statement for this ? Can I 'eck !As before, any help with this would very much be appreciated,ThanksNathan |
 |
|
|
jen
Master Smack Fu Yak Hacker
4110 Posts |
Posted - 2006-04-24 : 21:28:29
|
ok paper and pencil method (not tested)...where case when @operator='or' then the rest of your criteria...else the 'and' criteriaendotherwise it will be easier for you to construct the dsql inside the sproc and play around with that... but my assumption, since this is a search, you will need to consider performance and speed of retrieval, doing the way you are doing it just slows things down...if you keep on going along this line of solutioning, then you'll get into a huff when after 1 year you go back to this sproc and try to modify it, it'll be easier to create separate sprocs now or do the filtering in your appsbut that's me --------------------keeping it simple... |
 |
|
|
PSamsig
Constraint Violating Yak Guru
384 Posts |
Posted - 2006-04-25 : 02:04:59
|
| Oh why not humor him :)SELECT ISBN, TITLE, CASE WHEN AUTHOR='' THEN 'Not Specified' ELSE AUTHOR END AS AUTHOR, CASE WHEN PUBLISHER='' THEN 'Not Specified' ELSE PUBLISHER END AS PUBLISHER, FROM BOOKS WHERE ( ISBN LIKE CASE WHEN @L_operator = 'AND' OR @Isbn='' THEN NULL ELSE '%'+@Isbn+'%' END OR TITLE LIKE CASE WHEN @L_operator = 'AND' OR @Title='' THEN NULL ELSE '%'+@Title+'%' END OR AUTHOR LIKE CASE WHEN @L_operator = 'AND' OR @Author='' THEN NULL ELSE '%'+@Author+'%' END OR PUBLISHER LIKE CASE WHEN @L_operator = 'AND' OR @Publisher='' THEN NULL ELSE '%'+@Publisher+'%' END OR REVIEWS LIKE CASE WHEN @L_operator = 'AND' OR @ReviewTxt='' THEN NULL ELSE '%'+@ReviewTxt+'%' END ) AND ISBN LIKE CASE WHEN @L_operator = 'OR' OR @Isbn='' THEN ISBN ELSE '%'+@Isbn+'%' END AND TITLE LIKE CASE WHEN @L_operator = 'OR' OR @Title='' THEN TITLE ELSE '%'+@Title+'%' END AND AUTHOR LIKE CASE WHEN @L_operator = 'OR' OR @Author='' THEN AUTHOR ELSE '%'+@Author+'%' END AND PUBLISHER LIKE CASE WHEN @L_operator = 'OR' OR @Publisher='' THEN PUBLISHER ELSE '%'+@Publisher+'%' END AND REVIEWS LIKE CASE WHEN @L_operator = 'OR' OR @ReviewTxt='' THEN REVIEWS ELSE '%'+@ReviewTxt+'%' END AND TITLE IS NOT NULL--This one's tricky. You have to use calculus and imaginary numbers for this. You know, eleventeen, thirty-twelve and all those. |
 |
|
|
Jakes Daddy
Starting Member
7 Posts |
Posted - 2006-04-25 : 08:07:27
|
Thanks guys for your comments.PSamsig - couldn't quite get your solution to work, but eventually got it going like this: IF @L_operator='OR' BEGIN -- select statement for OR SELECT ISBN, TITLE, CASE WHEN AUTHOR='' THEN 'Not Specified' ELSE AUTHOR END AS AUTHOR, CASE WHEN PUBLISHER='' THEN 'Not Specified' ELSE PUBLISHER END AS PUBLISHER FROM BOOKS WHERE ( ISBN LIKE CASE WHEN @Isbn<>'' THEN '%'+@Isbn+'%' ELSE NULL END OR TITLE LIKE CASE WHEN @Title<>'' THEN '%'+@Title+'%' ELSE NULL END OR AUTHOR LIKE CASE WHEN @Author<>'' THEN '%'+@Author+'%' ELSE NULL END OR PUBLISHER LIKE CASE WHEN @Publisher<>'' THEN '%'+@Publisher+'%' ELSE NULL END OR REVIEWS LIKE CASE WHEN @ReviewTxt<>'' THEN '%'+@ReviewTxt+'%' ELSE NULL END ) AND TITLE IS NOT NULL END ELSE BEGIN -- select statement for AND SELECT ISBN, TITLE, CASE WHEN AUTHOR='' THEN 'Not Specified' ELSE AUTHOR END AS AUTHOR, CASE WHEN PUBLISHER='' THEN 'Not Specified' ELSE PUBLISHER END AS PUBLISHER FROM BOOKS WHERE ( ISBN LIKE CASE WHEN @Isbn<>'' THEN '%'+@Isbn+'%' ELSE '%%' END AND TITLE LIKE CASE WHEN @Title<>'' THEN '%'+@Title+'%' ELSE '%%' END AND AUTHOR LIKE CASE WHEN @Author<>'' THEN '%'+@Author+'%' ELSE '%%' END AND PUBLISHER LIKE CASE WHEN @Publisher<>'' THEN '%'+@Publisher+'%' ELSE '%%' END AND REVIEWS LIKE CASE WHEN @ReviewTxt<>'' THEN '%'+@ReviewTxt+'%' ELSE '%%' END ) AND TITLE IS NOT NULL END It works (so I'm happy with it), but I can see that its perhaps a bit messy/amatuer/not idealI am however intrigued by the suggestions to use dynamic sql - build a string of the SQL I want to run, then call it with EXECUTEI was under the impression that this is generally a bad idea ??? I want to prevent SQL injection attacks, and isn't there something about SQL execution plans or something ???As you can tell, I am a complete novice with this stuff, and I bow to your superior knowledge. I would just be interested to a) hear why dsql was suggested and b) if my concerns about dsql are valid ?Thanks againNathan |
 |
|
|
PSamsig
Constraint Violating Yak Guru
384 Posts |
Posted - 2006-04-25 : 11:03:48
|
| Ok I made a little mistake and I didnt take NULLs into account either, but here is the ultimate oneliner (tested this time)SELECT ISBN, TITLE, CASE WHEN AUTHOR='' THEN 'Not Specified' ELSE AUTHOR END AS AUTHOR,CASE WHEN PUBLISHER='' THEN 'Not Specified' ELSE PUBLISHER END AS PUBLISHERFROM BOOKS WHERE (ISBN LIKE CASE WHEN @L_operator = 'AND' OR @Isbn='' THEN NULL ELSE '%'+@Isbn+'%' END ORTITLE LIKE CASE WHEN @L_operator = 'AND' OR @Title='' THEN NULL ELSE '%'+@Title+'%' END ORAUTHOR LIKE CASE WHEN @L_operator = 'AND' OR @Author='' THEN NULL ELSE '%'+@Author+'%' END ORPUBLISHER LIKE CASE WHEN @L_operator = 'AND' OR @Publisher='' THEN NULL ELSE '%'+@Publisher+'%' END ORREVIEWS LIKE CASE WHEN @L_operator = 'AND' OR @ReviewTxt='' THEN NULL ELSE '%'+@ReviewTxt+'%' END OR@L_operator = 'AND') ANDCOALESCE(ISBN, '') LIKE CASE WHEN @L_operator = 'OR' OR @Isbn='' THEN COALESCE(ISBN, '') ELSE '%'+@Isbn+'%' END ANDCOALESCE(TITLE, '') LIKE CASE WHEN @L_operator = 'OR' OR @Title='' THEN COALESCE(TITLE, '') ELSE '%'+@Title+'%' END ANDCOALESCE(AUTHOR, '') LIKE CASE WHEN @L_operator = 'OR' OR @Author='' THEN COALESCE(AUTHOR, '') ELSE '%'+@Author+'%' END ANDCOALESCE(PUBLISHER, '') LIKE CASE WHEN @L_operator = 'OR' OR @Publisher='' THEN COALESCE(PUBLISHER, '') ELSE '%'+@Publisher+'%' END ANDCOALESCE(REVIEWS, '') LIKE CASE WHEN @L_operator = 'OR' OR @ReviewTxt='' THEN COALESCE(REVIEWS, '') ELSE '%'+@ReviewTxt+'%' ENDAND TITLE IS NOT NULLIf it looks messy/amatuer/not ideal then its my fault, but it is a static (somewhat at least) SELECT, the good question here is (and I am not qualified to answer this) if this actually can be compiled into one execution plan, someone ?--This one's tricky. You have to use calculus and imaginary numbers for this. You know, eleventeen, thirty-twelve and all those. |
 |
|
|
pootle_flump
1064 Posts |
Posted - 2006-04-26 : 04:04:59
|
quote: Originally posted by Jakes DaddyI am however intrigued by the suggestions to use dynamic sql - build a string of the SQL I want to run, then call it with EXECUTEI was under the impression that this is generally a bad idea ??? I want to prevent SQL injection attacks, and isn't there something about SQL execution plans or something ???As you can tell, I am a complete novice with this stuff, and I bow to your superior knowledge. I would just be interested to a) hear why dsql was suggested and b) if my concerns about dsql are valid ?Thanks againNathan
Hi NathanIf you look up the entry in BOL for sp_executesql you'll see that it accepts parameters (making it more secure) and the query results in an execution plan. In fact this article shows how you can use the sproc to create multiple plans for ostensibly the same query:http://www.sqljunkies.com/WebLog/amachanic/articles/StoredProcedureCaching.aspxHTH |
 |
|
|
Next Page
|