简体   繁体   中英

Using SELECT in CAST function of SQL

I am working on an order management web project in C# which can be provided to multiple clients.

In 'orders' table, I have a field 'Qty' of 4 decimals. Now not all clients may require 4 decimal places, so I have a table 'Config' which holds this value in field 'QtyDecimal'.

Presently what I am doing to show the correct number of decimals is something like this:

string xQtyDec = getQtyDecimalFromConfig();
sqlCommand = "Select CAST(Qty as numeric(18," + xQtyDec + ")) [Quantity] from orders";
...

I was wondering if this could be accomplished in SQL itself, something like

SELECT CAST(Qty as numeric(18, (SELECT QtyDecimal FROM config))) [Quantity] from orders

Is this possible?

According to Sql sever syntax , see https://msdn.microsoft.com/en-us/library/ms174979.aspx data type parameters (precision and scale) must be literals. They couldn't be expressions. You'd better do things like that on client side. Alternatively use round(), cast result to max possible scale (4) and strip extra zeroes from string representation

declare @s int = 2; -- scale config parameter, = 0..4

select t.col, substring(calc.v, 1, len(calc.v) -(4-@s))
from (--- sample data
      values (12345.06789) 
        , (8765000.1)
     ) t(col)
cross apply (
    select v = cast(cast(round(col, @s) as numeric (18,4)) as varchar(20))
    ) calc  

In SQL Server,you need to build a dynamic query to achieve the result.

DECLARE @Scale NVARCHAR(50)
SELECT  @scale= QtyDecimal FROM config
DECLARE @sql NVARCHAR(500)='SELECT CAST(Qty as numeric(18, ' +@scale+')) [Quantity] from orders'
EXEC (@sql)

Yes, that is possible, but you should rewrite your query as:

SELECT CAST(orders.Qty as numeric(18, (config.QtyDecimal))) AS [Quantity] from orders, config
WHERE {some selection on config table to get the correct QtyDecimal}

The best option is not to do this, but rather to do it in C# at the point where you convert the dataset for display or download. However if you need to do it in SQL you can use one of these approaches.

Approach 1:

Select CAST(CASE (select xQtyDecimal from Config)
   WHEN 1 then CAST(FieldName as NUMERIC(10,1)
   WHEN 2 then CAST(FieldName as NUMERIC(10,2)
   WHEN 3 then CAST(FieldName as NUMERIC(10,3)
   WHEN 4 then CAST(FieldName as NUMERIC(10,4)
   WHEN 5 then CAST(FieldName as NUMERIC(10,5)
   ELSE FieldName END AS NUMERIC(10,6)) As FieldNameAlias
From TableName
  • Pro: Control behaviour in each case exactly
  • Con: Each case must be written out.

Approach 2:

SELECT CAST(CAST(FieldName * POWER(10, (select xQtyDec from config)) as BIGINT) AS NUMERIC(20,10))/POWER(10, (select xQtyDec from config))
FROM TableName
  • Pro: Any number of decimal places can be coped with
  • Con: Rounds down, can't control eg banker's rounding.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM