Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
sushant17284
Starting Member
12 Posts |
Posted - 2010-04-15 : 15:34:01
|
| Guys , I am facing a small problem to which I just can't seem to find any solution.I am stuck for the last 2 days please help.Here is the scenario.I have a user table which has 3 columns : id,name and email.Now I have an SP in which another SP is called which returns a name of the user on the basis of some criteria.My problem is to find the email ID of that User.I used this following SQL which is very simple.Select email from User where name=@EMP_NAMEHere @EMP_NAME is the name returned by the stored proc which is being called within the stored proc which finds this email Id.This works perfectly fine when @EMP_NAME returns only one name like "John,Powell"Till now everything is fine.The problem happened when my client changed their Stored Proc to return multiple names in the @EMP_NAME separated with a delimiter.Now I get the value of @EMP_NAME as "John ,Powell / Gary, Mak "Note that the actual delimiter is "/". Commas are already inserted in the name field.Now since I get multiple names here , my existing select query fails and return null because there is no name with that value of @EMP_NAME.I would like anyone of you to help me on how to resolve this.Now I want to retrieve the email id of both the name within the @EMP_NAME.How is it possible ??The other condition is I can't change client's SP in anyway, So would have to deal with it within my SP. I don;t know I am stuck I tried using Like as well as split but no luck.I don't want to hardcode the splitted names as well because there can be more than two names also in the @EMP_NAME field in the future.PLEASE HELP ME !!!!!!!!!!! You guys have always helped me out.I will really appreciate your help.It looks like it should be a small modification in the query but I just can't seem to get it done. :( Btw , I am using MS SQL server |
|
|
malpashaa
Constraint Violating Yak Guru
264 Posts |
Posted - 2010-04-15 : 15:55:24
|
| SELECT email FROM User WHERE CHARINDEX(name, @EMP_NAME) > 0; |
 |
|
|
hanbingl
Aged Yak Warrior
652 Posts |
Posted - 2010-04-15 : 16:42:14
|
1st of all, BAD BAD client! I feel your pain. you can loop each name or you can generate a nvarchar statement string and use sqlexecute to run it.declare @SQLSTRING NVARCHAR(MAX);set @EMP_NAME = ''''+replace(ltrim(rtrim(@EMP_NAME)),' / ',''',''')+'''';SET @SQLSTRING = N'SELECT EMAIL FROM YOURTABLE WHERE NAME IN ('+@SQLSTRING+')';EXECUTE SP_EXECUTESQL @SQLSTRING;quote: Originally posted by sushant17284 Guys , I am facing a small problem to which I just can't seem to find any solution.I am stuck for the last 2 days please help.Here is the scenario.I have a user table which has 3 columns : id,name and email.Now I have an SP in which another SP is called which returns a name of the user on the basis of some criteria.My problem is to find the email ID of that User.I used this following SQL which is very simple.Select email from User where name=@EMP_NAMEHere @EMP_NAME is the name returned by the stored proc which is being called within the stored proc which finds this email Id.This works perfectly fine when @EMP_NAME returns only one name like "John,Powell"Till now everything is fine.The problem happened when my client changed their Stored Proc to return multiple names in the @EMP_NAME separated with a delimiter.Now I get the value of @EMP_NAME as "John ,Powell / Gary, Mak "Note that the actual delimiter is "/". Commas are already inserted in the name field.Now since I get multiple names here , my existing select query fails and return null because there is no name with that value of @EMP_NAME.I would like anyone of you to help me on how to resolve this.Now I want to retrieve the email id of both the name within the @EMP_NAME.How is it possible ??The other condition is I can't change client's SP in anyway, So would have to deal with it within my SP. I don;t know I am stuck I tried using Like as well as split but no luck.I don't want to hardcode the splitted names as well because there can be more than two names also in the @EMP_NAME field in the future.PLEASE HELP ME !!!!!!!!!!! You guys have always helped me out.I will really appreciate your help.It looks like it should be a small modification in the query but I just can't seem to get it done. :( Btw , I am using MS SQL server
|
 |
|
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2010-04-15 : 16:52:04
|
| Check out this set of articles about using Arrays in SQL:http://www.sommarskog.se/arrays-in-sql.htmlThis should help guide you to using a Split/Parse function to do what you need.If the data is stored as "John ,Powell" then you probably have bigger issues. However, the first response above will not be able to use an index do to the use of a function. The second response uses dynamic sql, which I'd be shy to use unless you use the sp_executesql stored procedure to help prevent malicious code from executing. But moreover, I'd suggest using a Split/Parse fucntion and avoid dynamic SQL altogether. |
 |
|
|
malpashaa
Constraint Violating Yak Guru
264 Posts |
Posted - 2010-04-15 : 17:38:39
|
quote: Originally posted by Lamprey the first response above will not be able to use an index do to the use of a function
You need to revise your informations regarding index usage when functions used, because not all functions prevent index usage, and in this specific case the optimizer will be able use the index if it exists. |
 |
|
|
DBA in the making
Aged Yak Warrior
638 Posts |
Posted - 2010-04-15 : 17:44:35
|
| See if you can get your hands on the original sp that returned a single name, and inline it into your own sp, or add it back to the database under a different name.------------------------------------------------------------------------------------Any and all code contained within this post comes with a 100% money back guarantee. |
 |
|
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2010-04-15 : 18:03:05
|
quote: Originally posted by malpashaa
quote: Originally posted by Lamprey the first response above will not be able to use an index do to the use of a function
You need to revise your informations regarding index usage when functions used, because not all functions prevent index usage, and in this specific case the optimizer will be able use the index if it exists.
You are correct, it might use an index by scanning the index. But, I'm not sure that is very effecient when it can be written as a seek. |
 |
|
|
sushant17284
Starting Member
12 Posts |
Posted - 2010-04-16 : 01:33:54
|
First of All, I would like to thank all of you for giving me so many ideas to resolve this problem.I really appreciate and would like to thank all of you with warm regards.I was able to try all of the ways mentioned here in the post.And thankfully hanbingl reply sorted it out for me.I am so happy......thanks to sql team and effort of all you guys who made your contributions.It makes me believe in this forum more than ever before.Now I am able to get the email like the following query :declare @SQLSTRING NVARCHAR(MAX);set @EMP_NAME = ''''+replace(ltrim(rtrim(@EMP_NAME)),' / ',''',''')+'''';SET @SQLSTRING = N'SELECT EMAIL FROM YOURTABLE WHERE NAME IN ('+@SQLSTRING+')';EXECUTE SP_EXECUTESQL @SQLSTRING;However there was a small problem with the query and that was that I had to change the SET @SQLSTRING line where name in ('+@SQLSTRING+')' to ('+@EMP_NAME+')'.This is the final result.email------------johnp@company.comgarym@company.comIT WORKS !!!!!!!!! WOWNow the only problem is how to get the email field as merged into one.I know I keep going round in circles.First I wanted to split the names to get the email and now I have to merge the emails back into one field with ";"(semicolon as delimiter)Can anyone tell me how to merge this email field into one row and not multiple rows ?Thanks alot to all of you once again.Cheers,Sushantquote: Originally posted by hanbingl 1st of all, BAD BAD client! I feel your pain. you can loop each name or you can generate a nvarchar statement string and use sqlexecute to run it.declare @SQLSTRING NVARCHAR(MAX);set @EMP_NAME = ''''+replace(ltrim(rtrim(@EMP_NAME)),' / ',''',''')+'''';SET @SQLSTRING = N'SELECT EMAIL FROM YOURTABLE WHERE NAME IN ('+@SQLSTRING+')';EXECUTE SP_EXECUTESQL @SQLSTRING;quote: Originally posted by sushant17284 Guys , I am facing a small problem to which I just can't seem to find any solution.I am stuck for the last 2 days please help.Here is the scenario.I have a user table which has 3 columns : id,name and email.Now I have an SP in which another SP is called which returns a name of the user on the basis of some criteria.My problem is to find the email ID of that User.I used this following SQL which is very simple.Select email from User where name=@EMP_NAMEHere @EMP_NAME is the name returned by the stored proc which is being called within the stored proc which finds this email Id.This works perfectly fine when @EMP_NAME returns only one name like "John,Powell"Till now everything is fine.The problem happened when my client changed their Stored Proc to return multiple names in the @EMP_NAME separated with a delimiter.Now I get the value of @EMP_NAME as "John ,Powell / Gary, Mak "Note that the actual delimiter is "/". Commas are already inserted in the name field.Now since I get multiple names here , my existing select query fails and return null because there is no name with that value of @EMP_NAME.I would like anyone of you to help me on how to resolve this.Now I want to retrieve the email id of both the name within the @EMP_NAME.How is it possible ??The other condition is I can't change client's SP in anyway, So would have to deal with it within my SP. I don;t know I am stuck I tried using Like as well as split but no luck.I don't want to hardcode the splitted names as well because there can be more than two names also in the @EMP_NAME field in the future.PLEASE HELP ME !!!!!!!!!!! You guys have always helped me out.I will really appreciate your help.It looks like it should be a small modification in the query but I just can't seem to get it done. :( Btw , I am using MS SQL server
|
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-04-16 : 02:32:31
|
| [code]declare @SQLSTRING NVARCHAR(MAX);set @EMP_NAME = ''''+replace(ltrim(rtrim(@EMP_NAME)),' / ',''',''')+'''';SET @SQLSTRING = N'SELECT EMAIL FROM YOURTABLE WHERE NAME IN ('+@EMP_NAME+')';EXECUTE SP_EXECUTESQL @SQLSTRING;[/code]Surely SQL injection risk there?Also requires the user to have underlying SELECT permissions on the table, rather than just Sproc execute permission (unless use impersonation ... which is a whole layer of complexity to be added if the O/P does not currently have that)I don't know how long these lists could be, but if they can be large then IN will be very inefficient.Best solution in my opinion would be to use a SPLIT function (as Lamprey said) to convert "xxx/yyy/zzz" formatted string into a pseudo table - i.e. a row for each valuye "xxx", "yyy", "zzz" and then JOIN this to the EMAIL table. That would look like this:[code]SELECT emailFROM MyTable AS T JOIN dbo.MySplitFunction(@EMP_NAME, '/') AS S ON S.SplitValue = T.[name][/code]this will optimally use any index on [NAME] column, and scale well with a large/huge MyTable and large numbers of names in the @EMP_NAME list.For a cheap-and-cheerful route then:[code]SELECT emailFROM MyTableWHERE '/' + @EMP_NAME + '/' LIKE '%/' + [name] + '/%'[/code]this is not very efficient (it will not use any index on [name] column, and thus requires a table scan) but for reasonable numbers of rows in MyTable (say thousands, maybe tens-of-thousands) and reasonable short @EMP_NAME list (say tens, up to a hundred), and if the requests are not too frequent, then performance will probably be acceptable and not put undue strain on other queries/databases on the same server.This does not have the permissions problems of dynamic SQL, not the SQL injection riskNOTE: if you delimiter is space padded - i.e. " / " rather than "/" - as per your initial example data, then some alteration is required. The user will have to use the delimiter exactly - either with one space, or not.For the SPLIT route this won't be necessary as the Split Function can TRIM the values to remove leading/trailing spaces. |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-04-16 : 02:52:19
|
Sample data:DECLARE @EMP_NAME varchar(1000)SET @EMP_NAME = 'John ,Powell/Gary, Mak/'');PRINT ''''''SQL Injection Attack!!''''''--'SELECT *INTO #MyDataFROM ( SELECT 'John ,Powell' AS [name], 'johnp@company.com' as [email] UNION ALL SELECT 'Gary, Mak', 'garym@company.com' UNION ALL SELECT 'Gary, MakXXX', 'garym3@company.com' UNION ALL SELECT 'Gary, Ma', 'garym2@company.com') AS TPRINT ''PRINT 'Method 1'SELECT emailFROM #MyDataWHERE CHARINDEX(name, @EMP_NAME) > 0PRINT ''PRINT 'Method 2'declare @SQLSTRING NVARCHAR(MAX);set @EMP_NAME = ''''+replace(ltrim(rtrim(@EMP_NAME)),'/',''',''')+'''';SET @SQLSTRING = N'SELECT EMAIL FROM #MyData WHERE NAME IN ('+@EMP_NAME+')';EXECUTE SP_EXECUTESQL @SQLSTRING;PRINT ''PRINT 'Method 3'SELECT emailFROM #MyDataWHERE '/' + @EMP_NAME + '/' LIKE '%/' + [name] + '/%'DROP TABLE #MyData |
 |
|
|
|
|
|
|
|