August 28, 2013 at 4:08 am
Hi
I run the same query against two DB, one is the publisher and other is the subscriber.
The two DB should be identical but the subscriber raise the "Divide By Zero" error while the publisher return the correct result.[/b]
Of course.... NONE OF THE RETURNED ROWS HAVE A ZERO in the relevant fields!!!
:w00t:
This is the query
SELECT
CASE
WHEN
BAL_IN.FK_CURR = 'EUR' then 1.0 -- If the currency is EURO the exchange rate is one
ELSE -- Otherwise calculate it.
BAL_IN.LEDGER_BAL_ORG_AMT/ BAL_IN.AC_FUNC_AMT -- HERE RAISE THE DIVIDE BY ZERO ERROR
END AS Exchange_Rate ,
CASE
WHEN
BAL_IN.FK_CURR = 'EUR' THEN DET_IN.DTL_AMT
ELSE
DET_IN.DTL_AMT/(BAL_IN.LEDGER_BAL_ORG_AMT/BAL_IN.AC_FUNC_AMT) -- This statement is similar but DO NOT Raise the Error(!!?)
END AS Exchanged_amount,
BAL_IN.AC_FUNC_AMT ,
BAL_IN.LEDGER_BAL_ORG_AMT,
DET_IN.DTL_AMT,
FROM
SICSNTPC.AC_LEDGER_DETAIL AS DET_IN ,
SICSNTPC.AC_LEDGER_BALANCE AS BAL_IN
WHERE
Where conditions......
I've found a kind of bypass using this statement
WHEN (ABS(BAL_IN.AC_FUNC_AMT)) <> 0 then ABS(BAL_IN.LEDGER_BAL_ORG_AMT)/ ABS(BAL_IN.AC_FUNC_AMT)
The problem has appeared lately but I can't imagine the origin of that.
Someone has ideas of what could be the reason of this disconcerting behaviour ?
Many thanks for the help
🙂
Giuliano
August 29, 2013 at 8:09 am
I don't actually have a solid answer for why the values in rows are different between publisher and subscriber, but I have a couple of suggestions for troubleshooting further:
I've found a kind of bypass using this statement
WHEN (ABS(BAL_IN.AC_FUNC_AMT)) <> 0 then ABS(BAL_IN.LEDGER_BAL_ORG_AMT)/ ABS(BAL_IN.AC_FUNC_AMT)
My first thought is that your bypass solution could actually be considered a best practice; i.e. whenever doing division in the data layer I would wrap that in a CASE to ensure that a Divide By Zero doesn't occur in run time.
SELECT
CASE
WHEN
BAL_IN.FK_CURR = 'EUR' then 1.0 -- If the currency is EURO the exchange rate is one
ELSE -- Otherwise calculate it.
BAL_IN.LEDGER_BAL_ORG_AMT/ BAL_IN.AC_FUNC_AMT -- HERE RAISE THE DIVIDE BY ZERO ERROR
END AS Exchange_Rate ,
CASE
WHEN
BAL_IN.FK_CURR = 'EUR' THEN DET_IN.DTL_AMT
ELSE
DET_IN.DTL_AMT/(BAL_IN.LEDGER_BAL_ORG_AMT/BAL_IN.AC_FUNC_AMT) -- This statement is similar but DO NOT Raise the Error(!!?)
END AS Exchanged_amount,
As to why you get a Divide By Error in the earlier column but not the latter, I'm guessing that that's b/c the engine will only throw the first exception; once it encounters one Divide By Zero it throws an exception and stops processing - so it doesn't evaluate the second expression.
As to why the values are different (assuming that there is some difference on the subscriber side), it's possible for rows to get out of sync. In 2008+ there's a utility that can help identify this issue called tablediff but I don't think it's available for 2005: http://technet.microsoft.com/en-us/library/ms162843.aspx. But it shouldn't be hard to do a column by column comparison of the two rows to see what values are different. You don't mention what type of replication you're using. I use transactional w/ updateable subscriptions and this model adds a column called msrepl_tran_version (maybe this gets added in all models?). If the values for this column are different then the rows are not considered in sync and changes to one may not replicate to the other. I've been able to fix this by updating one side's value to match the other's, but this is usually a sign that you have deeper issues that are not being addressed.
Not sure if this helps, but good luck with your troubleshooting.
August 31, 2013 at 3:51 am
Hi Steve
thanks for the kind answer, sometimes just exchanging ideas helps to clarify themselves.
🙂
And then..... we have some more info
My first thought is that your bypass solution could actually be considered a best practice;
i.e. whenever doing division in the data layer I would wrap that in a CASE to ensure that a
Divide By Zero doesn't occur in run time.
Yep this was also my first thought but then in the situation where the denominator were really
zero I had to handle the Exchange_Rate returning null because none of the WHEN/ELSE where
satisfied.....
but again I'was puzzled because none of the fields returned by the query were zero.
As to why you get a Divide By Error in the earlier column but not the latter, I'm guessing
that that's b/c the engine will only throw the first exception; once it encounters one Divide
By Zero it throws an exception and stops processing - so it doesn't evaluate the second
expression.
I tried to reverse the CASE and the error moved to the second (formerly first) CASE!
I posted the same append in the section Programming of this forum and john.rees-894283 replied this:
http://www.sqlservercentral.com/Forums/Topic1489248-338-1.aspx
A possible reason for this error is that the division expressions are being evaluated for some
rows before those rows are excluded by the WHERE clause.
The same problem is often observed
when CASTing datatypes, and using a WHERE clause to filter only those rows where the CAST would succeed.
This can happen because the optimiser is free to evaluate your SELECT expressions either
before or after filtering by the WHERE clause. Even if the data in your two databases is the
same, other factors (indexing, server resources...) may affect the optimser.
Then I counted the rows in the table where this field/denominator was zero and, surprise, there are some rows where IT IS zero.
It should not be zero but it is....
So at the end.... May be I'll have to leave a piece of wrong code to remedy a piece of bad data !!:hehe:
Viewing 3 posts - 1 through 2 (of 2 total)
You must be logged in to reply to this topic. Login to reply