Groups | Blog | Home
all groups > sql server programming > january 2004 >

sql server programming : Decimal Scale



Joe Celko
1/15/2004 4:01:50 PM
The basic principle of a tiered architecture is that display is handled
in the front end and data is handled in the back end. Pass a
"configuration table" to the front end and let it handle the display.

But if you insist on complex code that will be a bitch to maintain and
could lead to errors, put a CASE expression into every select list:

SELECT CASE C1.precision_parm
WHEN 1 THEN CAST (B AS DECIMAL(18,1))
WHEN 2 THEN CAST (B AS DECIMAL(18,2))
...
ELSE B END AS B,
...
FROM Foobar, Config AS C1
WHERE ..;


--CELKO--
===========================
Please post DDL, so that people do not have to guess what the keys,
constraints, Declarative Referential Integrity, datatypes, etc. in your
schema are.

*** Sent via Developersdex http://www.developersdex.com ***
Mark Norris
1/15/2004 10:42:51 PM
Hi

Hope someone can help me with this problem as it's driving me nuts!

We have an app where the user can define the number of decimals that they
want to use. We store the value (between 2 and 6) in a table. Let's call
it tblSetup and the column holding the number of decimals we'll call QtyDP
(int).

We have another table (tblData) where the data is stored. The table has two
columns - A (nvarchar(30) and B (decimal (18,6)). As you can see, the
decimal column can store data up to the maximum decimal scale allowed in the
app.

The user can view the data held in tblData via a view - vw_Data. My problem
is that I want the view to return column B according to the number of
decimals held in tblSetup. If I was hard coding the decimals, I could do
something like CAST(B AS decimal(18,2)), but I want the scale to come from
the table. Effectively what I want is CAST(B as decimal(18, @QtyDP)) - but
you can't have parameters in views (obviously).

Oh, and I can't use stored procedures as the data will be retrieved via
ODBC, and the app using the ODBC driver cannot execute stored procedures.

Many Thanks

Mark

Joe Celko
1/16/2004 8:00:15 AM
[quoted text, click to view]
otherwise I would handle this differently. <<

But that is the point; this should not be under your control because it
should not be in your specs. The overall systems architect has mixed
the tiers in the project specs.

Next "Mr. Pointy Hair" is going to have you maintaining hardware (too
low) or setting corporate policy (too high). Bad specs, rant, rant,
makes poor code, rant, rant.

--CELKO--
===========================
Please post DDL, so that people do not have to guess what the keys,
constraints, Declarative Referential Integrity, datatypes, etc. in your
schema are.

*** Sent via Developersdex http://www.developersdex.com ***
Joe Celko
1/16/2004 11:22:43 AM
[quoted text, click to view]
operator, there will be an implicit conversion to the type of the CASE
expression. <<

I am just looking to round/truncate on the back end beofre it goes to
the front end.

There is no way to pass different datatypes to a host program. The
really awful "solution" would be to make everything into strings, pass
those to the front end then parse them in there, picking whatever the
host language uses for each datatype. Arrrgh!

--CELKO--
===========================
Please post DDL, so that people do not have to guess what the keys,
constraints, Declarative Referential Integrity, datatypes, etc. in your
schema are.

*** Sent via Developersdex http://www.developersdex.com ***
Steve Kass
1/16/2004 12:59:08 PM
I don't believe this will work. A CASE expression in SQL must have a
fixed type, so despite the CAST operator, there will be an implicit
conversion to the type of the CASE expression.

SK

[quoted text, click to view]
Steve Kass
1/16/2004 1:00:52 PM
Mark,

It's a little messy, but one solution is below. You could also do it
a bit more simply (and avoid using a function) with STR, but since STR
converts to float before proceeding, it might cause rounding errors in
some rare cases:

create function titles_custom (
@d tinyint
) returns table as return
select
title_id,
case @d
when 0 then p0
when 1 then p1
when 2 then p2
when 3 then p3
when 4 then p4
when 5 then p5
when 6 then p6
else price end price
from (
select
title_id,
price,
cast(cast(price as decimal(10,0)) as sql_variant) as p0,
cast(cast(price as decimal(10,1)) as sql_variant) as p1,
cast(cast(price as decimal(10,2)) as sql_variant) as p2,
cast(cast(price as decimal(10,3)) as sql_variant) as p3,
cast(cast(price as decimal(10,4)) as sql_variant) as p4,
cast(cast(price as decimal(10,5)) as sql_variant) as p5,
cast(cast(price as decimal(10,6)) as sql_variant) as p6
from pubs..titles
) T
go

select * from titles_custom(3)

go
drop function titles_custom

SK

[quoted text, click to view]
Mark Norris
1/16/2004 2:14:38 PM
Thanks Joe.

The app that is displaying the data is not under my control - otherwise I
would handle this differently.

Mark
[quoted text, click to view]

Joe Celko
1/16/2004 4:26:55 PM
[quoted text, click to view]
variable or table column value: <<

Arrgh! Much better approach! I never think of ROUND() because it is not
Standard SQL, but every product has something like it.

--CELKO--
===========================
Please post DDL, so that people do not have to guess what the keys,
constraints, Declarative Referential Integrity, datatypes, etc. in your
schema are.

*** Sent via Developersdex http://www.developersdex.com ***
Steve Kass
1/16/2004 5:31:32 PM


[quoted text, click to view]
I see. That you could do with ROUND, since its second parameter can be
a variable or table column value:

create table T (
d int
)
insert into T values (5)
go

select
round(1.23465783498576,d,0), -- rounded
round(1.23465783498576,d,1) -- truncated
from T
go

drop table T

While ROUND (like many numeric features) isn't part of the standard,
it's not a completely weird proprietary thing.

SK

[quoted text, click to view]
Mark Norris
1/21/2004 12:35:53 PM
Thanks Steve
[quoted text, click to view]

AddThis Social Bookmark Button