Number formatting in Oracle using TO_CHAR

时间:2017-12-18 08:36:42

标签: sql oracle number-formatting

Proper way to format the numbers in ORACLE stored procedures.

I need to display currency fields with 2 decimals. Expected output is as follows:

  • 0 > 0.00
  • 5 > 5.00
  • 1253.6 > 1253.60
  • 1253.689 > 1253.69

Below worked for me:

public class RecyclerContactAdapter extends RecyclerView.Adapter<RecyclerContactAdapter.ViewHolder> {

    private List<MobileContact> contacts;
    private Context context;

    public RecyclerContactAdapter() {
        contacts = new ArrayList<>();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        this.context = parent.getContext();
        View view = LayoutInflater.from(context)
                .inflate(R.layout.item_recycler_contact, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        //set data for view
    }

    @Override
    public int getItemCount() {
        return contacts.size();
    }

    protected class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tvAlphabetHeader;
        private CircleImageView civAvatar;
        private TextView tvContactName;
        private TextView tvStatus;
        private CheckBox cbInvited;
        private RelativeLayout rlAlphabetHeader;
        private RelativeLayout rlContainer;

        protected ViewHolder(View itemView) {
            super(itemView);
            tvAlphabetHeader = itemView.findViewById(R.id.item_recycler_contact_tv_alphabet_header);
            civAvatar = itemView.findViewById(R.id.item_recycler_contact_civ_avatar);
            tvContactName = itemView.findViewById(R.id.item_recycler_contact_tv_name);
            tvStatus = itemView.findViewById(R.id.item_recycler_contact_tv_status);
            cbInvited = itemView.findViewById(R.id.item_recycler_contact_cb_contact);
            rlAlphabetHeader =  itemView.findViewById(R.id.item_recycler_contact_rl_alphabet);
            rlContainer = itemView.findViewById(R.id.item_recycler_contact_rl_contact);
        }
    }

    public void addAll(List<MobileContact> mobileContacts) {
        this.contacts.clear();
        this.contacts.addAll(mobileContacts);
        notifyDataSetChanged();
    }

    public void add(MobileContact mobileContact) {
        this.contacts.add(mobileContact);
    }

    public List<MobileContact> getContacts() {
        return this.contacts;
    }

}

But this has the issue of hard coding a bunch of 9s. If I give a larger number it will be displayed as "##############"

Is there any other way I can do this?

2 个答案:

答案 0 :(得分:2)

  

我需要显示2位小数的货币字段。

确保使用具有适合数据的比例和精度的数字数据类型,而不是使用没有比例和精度的NUMBER。如果你要存储美元/欧元/磅/等。那么Gross World Product在2014年大约为100,000,000,000,000美元。让我们假设你不会处理超过这个 [citation needed] 然后你的货币栏可以是:

NUMBER(17,2)

如果您获得的值大于此值,那么您需要对数据进行一次完整性检查,并考虑是否大于世界总产品的数量是有意义的。如果您要将价值存储为例如日元或津巴布韦元,则适当调整比例。

您甚至可以将包中的子类型定义为:

CREATE PACKAGE currencies_pkg IS
  SUBTYPE currency_type IS NUMBER(17,2);

  FUNCTION formatCurrency(
    amount IN CURRENCY_TYPE
  ) RETURN VARCHAR2;
END;
/

您的格式化代码可以是:

CREATE PACKAGE BODY currencies_pkg IS
  FUNCTION formatCurrency(
    amount IN CURRENCY_TYPE
  ) RETURN VARCHAR2
  IS
  BEGIN
    RETURN TO_CHAR( currency_value, 'FM999999999999990D00' );
  END;
END;
/

然后,如果您在存储过程/包中引用该子类型,则在没有引发异常的情况下,您将无法超过货币数据类型的最大大小。用于显示值的格式模型只需要在一个地方定义,并且由于输入仅限于货币子类型,因此格式化函数永远不会超过强加的比例/精度,并且无法输出# s

CREATE PROCEDURE your_procedure(
  in_value1 IN ACCOUNTS_TABLE.ACCOUNT_BALANCE%TYPE,
  in_value2 IN ACCOUNTS_TABLE.ACCOUNT_BALANCE%TYPE
)
IS
  v_value CURRENCIES_PKG.CURRENCY_TYPE;
BEGIN
  -- Do something
  v_value := in_value1 + in_value2;
  -- Output formatted value
  DBMS_OUTPUT.PUT_LINE( CURRENCIES_PKG.formatCurrency( v_value ) );
END;
/

答案 1 :(得分:1)

为什么&#34;硬编码一堆9s&#34;一个问题? (如果你计划使用TO_CHAR,那么你需要怎么做)

select to_char(9876.23 , 'fm9999999999999999999990D00') from dual;

PS;您可能需要考虑使用D而不是.(并非每个国家/地区都使用.作为小数点分隔符 - D对语言非常敏感且会使用相应的符号)