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.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Comparisons: Is the order guaranteed?

Author  Topic 

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2009-10-30 : 08:15:38
Hi All.

Is the order of comparators (= <> IS ... etc) guaranteed in cases such as this:

(This is an example to show the question -- I don't care about any more efficient way to do this)....

DECLARE @digits INT SET @digits = 4

DECLARE @foo TABLE (
[staffNumber] VARCHAR(255)
)

INSERT @foo ([staffNumber])
SELECT '000123'
UNION SELECT '123'
UNION SELECT 'x123312'
UNION SELECT '1123~'
UNION SELECT '000001'
UNION SELECT '2131231231'

SELECT
'PROBLEM CASE' AS [Validation]
, [staffNumber]
FROM
@foo
WHERE
LEN([staffNumber]) <> @digits
AND (
[staffNumber] LIKE '%[^0123456789]%'
OR
CAST([staffNumber] AS INT) <> CAST(RIGHT([staffNUmber], @digits) AS INT)
)

Here I want to find any [staffNumber] That could not be justified to 4 places -- (so either adding 0's or removing 0's from the set as long as the meaning of the [staffNumber] is retained.

Am I right in thinking that

1) The LEN([staffNumber]) <> @digits is checked first -- only if it passes this then the next comparison is done?

2) As above inside the () The check for non numerals is checked before the CAST?

If it isn't in some circumstance (if the CAST is ever done first) then some of the [staffNumber] rows will throw an error (they can't be converted to INT because of the non numeral characters).

This sql works in my testing but I need to know if I can rely on this behaviour or if, in some circumstance, the order of comparison will not be guaranteed.

Cheers.
Charlie.





Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2009-10-30 : 09:03:59
no, you can not rely on this.

http://blogs.msdn.com/sqlprogrammability/archive/2006/05/12/596401.aspx
Go to Top of Page

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2009-10-30 : 09:33:53
Cheers. I kinda suspected not.

I like this comment from the link:
quote:

# re: Predicate ordering is not guaranteed
Or, better, how about designing tables with properly typed columns so as to avoid bad data issues to begin with?
Friday, May 19, 2006 4:24 PM by AdamMachanic

Properly typed columns when the database was designed by java programmers? A man can dream. A man can dream.....


[NB]Hell, I may as well wish for some constraints as well...... sigh
Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2009-10-30 : 11:31:25
LOL.
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2009-10-30 : 11:51:11
Use a CASE when tests have to be evaluated in sequence.
declare @digits int
set @digits = 4

Select
*
from
( -- Test Data
select staffNumber = '01234' union all
select staffNumber = '00123' union all
select staffNumber = '51234' union all
select staffNumber = '012a4' union all
select staffNumber = '1234'
) a
where
1 =
case
when [staffNumber] LIKE '%[^0123456789]%'
then 1
when CAST([staffNumber] AS INT) <> CAST(RIGHT([staffNUmber], @digits) AS INT)
then 1
else 0 end

Results:
staffNumber 
-----------
51234
012a4

(2 row(s) affected)



CODO ERGO SUM
Go to Top of Page

parody
Posting Yak Master

111 Posts

Posted - 2009-10-30 : 12:48:02
each OR () is tested independently, I think you just need to specify only [staffNumber] LIKE '%[0123456789]%' is attempted casting -i.e. ([staffNumber] LIKE '%[0123456789]%' AND CAST([staffNumber] AS INT) <> CAST(RIGHT([staffNUmber], @digits) AS INT))

alternatively tidy the data and remove any rogue characters from the string first. I just posted a way of changing groups of characters in a string to 0 here you could change it to be blanks instead
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=135147

By the way easier way of saying '%[0123456789]%' is '%[0-9]%', '%[^0-9]%', '%[a-z]%' etc etc
Go to Top of Page
   

- Advertisement -