May 7, 2009 at 12:07 am
Jeff Moden (5/6/2009)
I can only hope that gserdijn got it from me. 😛
Off course!
When you rewrite a cursor to be set based, don't make the same error in logic.
Right again. I humbly admit that I wouldn't have thought of your solution. But the main issue was to write a set-based solution - however bad performing - in order to convince Manie that cursors can be re-written.
(Ah, the beauty of SQL. Just scored my first coffee and already learned something.)
May 7, 2009 at 11:26 am
Jeff Moden (5/6/2009)
[font="Courier New"] USE AdventureWorks
;WITH cteNames AS
(
SELECT FirstName + ' ' + LastName AS FullName
FROM AdventureWorks.Person.Contact
WHERE FirstName + ' ' + LastName LIKE '%[^- .''A-Z]%'
)
SELECT n.FullName,
SUBSTRING(n.FullName,t.N,1) AS BadChar,
t.n AS BadCharPosition,
ASCII(SUBSTRING(n.FullName,t.N,1)) AS BadCharNum
FROM cteNames n
CROSS JOIN Util.dbo.Tally t
WHERE t.N <= LEN(n.FullName)
AND SUBSTRING(n.FullName,t.N,1) LIKE '[^- .''A-Z]'[/font]
I was playing around with this and can't figure out why the "-" in the where clause has to come before all the other individual characters. If I move it after the . it doesn't produce the same results.
May 7, 2009 at 11:35 am
gserdijn (5/7/2009)
Jeff Moden (5/6/2009)
I can only hope that gserdijn got it from me. 😛
Off course!
When you rewrite a cursor to be set based, don't make the same error in logic.
Right again. I humbly admit that I wouldn't have thought of your solution. But the main issue was to write a set-based solution - however bad performing - in order to convince Manie that cursors can be re-written.
(Ah, the beauty of SQL. Just scored my first coffee and already learned something.)
Thanks for the feedback. Please don't think that I was badmouthing your good code. You did exactly right and your heart was definitely in the right place with the way you jumped in to help Manie. It was just a prime opportunity for me to state something obvious. 🙂
--Jeff Moden
Change is inevitable... Change for the better is not.
May 7, 2009 at 11:36 am
ben.rosato (5/7/2009)
Jeff Moden (5/6/2009)
[font="Courier New"] USE AdventureWorks
;WITH cteNames AS
(
SELECT FirstName + ' ' + LastName AS FullName
FROM AdventureWorks.Person.Contact
WHERE FirstName + ' ' + LastName LIKE '%[^- .''A-Z]%'
)
SELECT n.FullName,
SUBSTRING(n.FullName,t.N,1) AS BadChar,
t.n AS BadCharPosition,
ASCII(SUBSTRING(n.FullName,t.N,1)) AS BadCharNum
FROM cteNames n
CROSS JOIN Util.dbo.Tally t
WHERE t.N <= LEN(n.FullName)
AND SUBSTRING(n.FullName,t.N,1) LIKE '[^- .''A-Z]'[/font]
I was playing around with this and can't figure out why the "-" in the where clause has to come before all the other individual characters. If I move it after the . it doesn't produce the same results.
The reason why is because the dash character is also used to define ranges of characters such as A-Z. The only place it can be included without jumping through a hoop is in the very first character position.
--Jeff Moden
Change is inevitable... Change for the better is not.
May 7, 2009 at 11:37 am
ben.rosato (5/7/2009)
I was playing around with this and can't figure out why the "-" in the where clause has to come before all the other individual characters. If I move it after the . it doesn't produce the same results.
Because if the "-" comes after a character it is being used to specify a range like the "A-Z" section.
May 7, 2009 at 11:38 am
Simple enough reason. Thanks.
May 9, 2009 at 12:37 am
Thanks to all for jumping in to help me but that was not quite the reason for me posting the code. I thought Ha! let's see how they figure this one out and was convinced that no-one would be able to do it. Well, with my hat in my hand I have to humbly say: It can be done! Well done gserdijn and Jeff and Jeff, you taught me something today again! I am a bit puzzled with your code though and maybe you can clear something for me.
LIKE '[^- .''A-Z]'
You only put A-Z and not also a-z. How does that work?
I have another cursor that I would like to change to set based and this code might help me to that. I might come back here to ask for some help.
:-PManie Verster
Developer
Johannesburg
South Africa
I can do all things through Christ who strengthens me. - Holy Bible
I am a man of fixed and unbending principles, the first of which is to be flexible at all times. - Everett Mckinley Dirkson (Well, I am trying. - Manie Verster)
May 9, 2009 at 1:18 am
Thanks to all for jumping in to help me but that was not quite the reason for me posting the code. I thought Ha! let's see how they figure this one out and was convinced that no-one would be able to do it. Well, with my hat in my hand I have to humbly say: It can be done! Well done gserdijn and Jeff and Jeff, you taught me something today again! I am a bit puzzled with your code though and maybe you can clear something for me.
LIKE '[^- .''A-Z]'
You only put A-Z and not also a-z. How does that work?
I have another cursor that I would like to change to set based and this code might help me to that. I might come back here to ask for some help.
:-PManie Verster
Developer
Johannesburg
South Africa
I can do all things through Christ who strengthens me. - Holy Bible
I am a man of fixed and unbending principles, the first of which is to be flexible at all times. - Everett Mckinley Dirkson (Well, I am trying. - Manie Verster)
May 9, 2009 at 5:27 am
Manie Verster (5/9/2009)
Thanks to all for jumping in to help me but that was not quite the reason for me posting the code. I thought Ha! let's see how they figure this one out and was convinced that no-one would be able to do it. Well, with my hat in my hand I have to humbly say: It can be done! Well done gserdijn and Jeff and Jeff, you taught me something today again! I am a bit puzzled with your code though and maybe you can clear something for me.LIKE '[^- .''A-Z]'
You only put A-Z and not also a-z. How does that work?
I have another cursor that I would like to change to set based and this code might help me to that. I might come back here to ask for some help.
Text comparisons in SQL are done by the rules of a collation...the default collation on installation is case insensitive, so A-Z will also match lowercase characters. You can specify a collation at the server, database and column level as well as override it in comparisons performed in your queries. If you have two fields that have a different collation you have to specify which collation rules to follow while doing the compare. Any indexes not matching the collation used in the comparison cannot be utilized during that comparison and will not be able to help you to speed up the operation. Obviously it is best to stick to one collation and make exceptions only where they are functionally required.
It's worth checking books online on the subject of collations for anyone that has not done so already!
I hope this answer satisfies your question 🙂
May 9, 2009 at 9:23 am
Manie Verster (5/9/2009)
You only put A-Z and not also a-z. How does that work?
Peter gave a pretty good description as to why. To simplify, the default for SQL Server installations is "case insensitive". That means that looking of A-Z, a-z, A-z, or a-Z will all do the same thing. If you have a "case sensitive" installation (ack!) or a case sensitive column (much better), then you'd need for my little LIKE clause to say...
LIKE '[^- .''A-Z[font="Arial Black"]a-z[/font]]'
--Jeff Moden
Change is inevitable... Change for the better is not.
May 10, 2009 at 11:47 am
Thanks Jeff and Peter,
That explains it and I also looked it up on books online and now understands it better now.
:-PManie Verster
Developer
Johannesburg
South Africa
I can do all things through Christ who strengthens me. - Holy Bible
I am a man of fixed and unbending principles, the first of which is to be flexible at all times. - Everett Mckinley Dirkson (Well, I am trying. - Manie Verster)
May 10, 2009 at 3:31 pm
Very cool. Thanks for the feedback, Manie.
--Jeff Moden
Change is inevitable... Change for the better is not.
June 10, 2009 at 7:39 am
This thread is very educational, and it puts me into trouble: I'm busy looking at all the loops used and trying to make them SET-based. Challencing, but there is more important work to be done.
A question though. I have run Jeff's script against Adventureworks and get Frank Martjnez back. From the WHERE clause I figure that this bad character is outside the scope of the LIKE clause. If I would want to include characters with CHARCODE of 161, 162 and-so-on, how would I add those to the LIKE clause? Just adding something like 'íó'? And while we're at this, can some1 explain how this LIKE clause works? This value: 'nnn''nnn', I would think is not acceptable, it's 2 values (between each pair '') without a comma seperation.
Any1 care to explain this to me?
EDIT: I am awaiting eagerly Barry's next installment of this series!
Greetz,
Hans Brouwer
June 15, 2009 at 4:04 pm
It's sorely tempting to rewrite every cursor into pure SQL (the ETL I inherited is rife with them), but the key is to focus on the "long pole in the tent": only optimize what's hampering business value. Otherwise you're afflicted with CTD -- "Compulsive Tuning Disorder" (a term devised by Gaja Krishna Vaidyanatha in 2001).
http://searchoracle.techtarget.com/news/interview/0,289202,sid41_gci1075628,00.html#
The "curse of the cursors" is the bane of every RDBMS, not just SQL Server!
http://it.toolbox.com/blogs/data-ruminations/the-curse-of-the-cursor-31851
July 29, 2009 at 2:15 am
This was shaping to be a magnificent series, but is part 3 on the way? I really hope so.
The import routines we use for our crm system all use cursors and we have severe performance problems with housekeeping jobs and imports running almost 24*7. I'd love to convert them all and was hoping this brilliantly clearly written series would teach me how.
Viewing 15 posts - 181 through 195 (of 316 total)
You must be logged in to reply to this topic. Login to reply