Store Big Price value in database along with Decimal Point in SQLite Database

前端 未结 1 1760
感动是毒
感动是毒 2021-01-20 23:11

May be my question is silly, But I didn\'t find any Solution for this. Actually, I want to Store Big Price Amount i.e.

9999999999.99

相关标签:
1条回答
  • 2021-01-20 23:48

    The defined column type affinity TEXT, REAL, NUMERIC, VARCHAR, RUMPLESTILTSKIN (yes it works), has little impact; the exception being if the type is either INTEGER PRIMARY KEY or INTEGER PRIMARY KEY AUTOINCREMENT in which case the column is an alias of the SQLITE column rowid and cannot be used. ROWIDs and the INTEGER PRIMARY KEY

    Basically any column, except a rowid, can store any type of value as per

    Any column in an SQLite version 3 database, except an INTEGER PRIMARY KEY column, may be used to store a value of any storage class. Datatypes In SQLite Version 3

    The link also explains how column types are converted to one of the 5 column types :-

    • TEXT,
    • INTEGER,
    • REAL,
    • BLOB or
    • NUMERIC.

    RuMpleStilskin (case independent) will be converted to NUMERIC, as per :-

    • (a) it doesn't contain INT (if so INTEGER affinity)
    • (b) it doesn't conatain TEXT, CHAR or CLOB (if so TEXT affinity unless previously handled)
    • (c) it doesn't contain BLOB (if so BLOB affinity unless previously handled)
    • (d) it doesn't contain REAL, FLOA, or DOUB (if so REAL affinity unless previously handled)
    • (e) if none of the above NUMERIC <<<< Rumplestilskin gets here.

    What is of primary importance is how you retrieve the data, although the column's affinity can affect how the data is stored (the storage class) as per :-

    A column with TEXT affinity stores all data using storage classes NULL, TEXT or BLOB. If numerical data is inserted into a column with TEXT affinity it is converted into text form before being stored.

    A column with NUMERIC affinity may contain values using all five storage classes. When text data is inserted into a NUMERIC column, the storage class of the text is converted to INTEGER or REAL (in order of preference) if such conversion is lossless and reversible. For conversions between TEXT and REAL storage classes, SQLite considers the conversion to be lossless and reversible if the first 15 significant decimal digits of the number are preserved. If the lossless conversion of TEXT to INTEGER or REAL is not possible then the value is stored using the TEXT storage class. No attempt is made to convert NULL or BLOB values.

    A string might look like a floating-point literal with a decimal point and/or exponent notation but as long as the value can be expressed as an integer, the NUMERIC affinity will convert it into an integer. Hence, the string '3.0e+5' is stored in a column with NUMERIC affinity as the integer 300000, not as the floating point value 300000.0.

    A column that uses INTEGER affinity behaves the same as a column with NUMERIC affinity. The difference between INTEGER and NUMERIC affinity is only evident in a CAST expression.

    A column with REAL affinity behaves like a column with NUMERIC affinity except that it forces integer values into floating point representation. (As an internal optimization, small floating point values with no fractional component and stored in columns with REAL affinity are written to disk as integers in order to take up less space and are automatically converted back into floating point as the value is read out. This optimization is completely invisible at the SQL level and can only be detected by examining the raw bits of the database file.)

    A column with affinity BLOB does not prefer one storage class over another and no attempt is made to coerce data from one storage class into another. Datatypes In SQLite Version 3

    For floating point or double you should retrieve the data using the Cursor methods getFloat or getDouble and then format the result, if converting it to a string, accordingly. Note! this assumes that the flaws/loss of precision with double or float are not relevant. If you store the value as a string and the column affinity is TEXT or BLOB then the result is loss-less and is perhaps the best way to store large (see results to determine what is large) numbers.


    Consider a table with 5 columns defined with column types/affinities REAL, TEXT, INTEGER, NUMERIC and BLOB

    as per :-

    CREATE TABLE prices (
        _id INTEGER PRIMARY KEY, 
        PRICE1 REAL, 
        PRICE2 TEXT,
        PRICE3 INTEGER, 
        PRICE4 NUMERIC, 
        PRICE5 BLOB
    )
    
    • The ID column isn't of significance.

    Now consider these 3 basic methods to - a) insert a double value into all 5 PRICE? columns - b) insert a string value into all 5 PRICE? columns - c) get all rows as a cursor :-

    public void insertRowFromDouble(double price) {
        ContentValues cv = new ContentValues();
        cv.put(PRICES_PRICE1_COL,price);
        cv.put(PRICES_PRICE2_COL,price);
        cv.put(PRICES_PRICE3_COL,price);
        cv.put(PRICES_PRICE4_COl,price);
        cv.put(PRICES_PRICE5_COL,price);
        mDB.insert(TBNAME,null,cv);
    }
    
    public void insertRowFromString(String price) {
        ContentValues cv = new ContentValues();
        cv.put(PRICES_PRICE1_COL,price);
        cv.put(PRICES_PRICE2_COL,price);
        cv.put(PRICES_PRICE3_COL,price);
        cv.put(PRICES_PRICE4_COl,price);
        cv.put(PRICES_PRICE5_COL,price);
        mDB.insert(TBNAME,null,cv);
    }
    
    public Cursor getAllRows() {
        return mDB.query(TBNAME,null,null,null,null,null,null);
    }
    

    and then consider the following code, which :-

    • a) Creates a DecimalFormat
    • b) Instantiates a Databasehelper
    • c) Deletes all existing rows (for rerun-ability)
    • d) Inserts 5 rows using the insertRowfromDouble method with varying values, each row having all 5 columns populated with the same value even though they each have a different column type.
    • e) does the same as d) but using the insertRowFromString method and within different but close values.
    • f) obtains a cursor with all 10 rows.
    • g) loops through the cursor output the resultant data using the getDouble method formatted according to the DecimalFormat and then the getString method.

    :-

        final DecimalFormat df = new DecimalFormat("#0.000000");
        mDBPricesHlpr = new PriceDBHelper(this);
        mDBPricesHlpr.getWritableDatabase().delete(PriceDBHelper.TBNAME,null,null);
        mDBPricesHlpr.insertRowFromDouble(999999999999999999999999999999999999999.99);
        mDBPricesHlpr.insertRowFromDouble(12345678901.123456);
        mDBPricesHlpr.insertRowFromDouble(9999999999.99);
        mDBPricesHlpr.insertRowFromDouble(0.01);
        mDBPricesHlpr.insertRowFromDouble(45678.45);
        mDBPricesHlpr.insertRowFromString("999999999999999999999999999999999999999999999999999999999999999999999999999.99");
        mDBPricesHlpr.insertRowFromString("12345678901.123456");
        mDBPricesHlpr.insertRowFromString("8888888888.88");
        mDBPricesHlpr.insertRowFromString("0.02");
        mDBPricesHlpr.insertRowFromString("56789.56");
        Cursor csr = mDBPricesHlpr.getAllRows();
        while (csr.moveToNext()) {
            Log.d("PRICEINFO_GETDBL"," Processing Row " + csr.getPosition() +
                    "\n\tPRICE1=" + df.format(csr.getDouble(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE1_COL))) +
                            "\n\tPRICE2=" + df.format(csr.getDouble(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE2_COL))) +
                            "\n\tPRICE3=" + df.format(csr.getDouble(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE3_COL))) +
                            "\n\tPRICE4=" + df.format(csr.getDouble(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE4_COl))) +
                            "\n\tPRICE5=" + df.format(csr.getDouble(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE5_COL)))
            );
            Log.d("PRICEINFO_GETSTR", " Processing Row " + csr.getPosition() +
                    "\n\tPRICE1=" + csr.getString(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE1_COL)) +
                            "\n\tPRICE2=" + csr.getString(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE2_COL)) +
                            "\n\tPRICE3=" + csr.getString(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE3_COL)) +
                            "\n\tPRICE4=" + csr.getString(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE4_COl)) +
                            "\n\tPRICE5=" + csr.getString(csr.getColumnIndex(PriceDBHelper.PRICES_PRICE5_COL))
            );
        }
    

    The resultant output is :-

    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 0
                                                        PRICE1=1000000000000000000000000000000000000000.000000
                                                        PRICE2=1000000000000000000000000000000000000000.000000
                                                        PRICE3=1000000000000000000000000000000000000000.000000
                                                        PRICE4=1000000000000000000000000000000000000000.000000
                                                        PRICE5=1000000000000000000000000000000000000000.000000
    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 0
                                                        PRICE1=1e+39
                                                        PRICE2=1.0e+39
                                                        PRICE3=1e+39
                                                        PRICE4=1e+39
                                                        PRICE5=1e+39
    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 1
                                                        PRICE1=12345678901.123500
                                                        PRICE2=12345678901.123500
                                                        PRICE3=12345678901.123500
                                                        PRICE4=12345678901.123500
                                                        PRICE5=12345678901.123500
    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 1
                                                        PRICE1=1.23457e+10
                                                        PRICE2=12345678901.1235
                                                        PRICE3=1.23457e+10
                                                        PRICE4=1.23457e+10
                                                        PRICE5=1.23457e+10
    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 2
                                                        PRICE1=9999999999.990000
                                                        PRICE2=9999999999.990000
                                                        PRICE3=9999999999.990000
                                                        PRICE4=9999999999.990000
                                                        PRICE5=9999999999.990000
    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 2
                                                        PRICE1=1e+10
                                                        PRICE2=9999999999.99
                                                        PRICE3=1e+10
                                                        PRICE4=1e+10
                                                        PRICE5=1e+10
    01-11 10:39:30.626 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 3
                                                        PRICE1=0.010000
                                                        PRICE2=0.010000
                                                        PRICE3=0.010000
                                                        PRICE4=0.010000
                                                        PRICE5=0.010000
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 3
                                                        PRICE1=0.01
                                                        PRICE2=0.01
                                                        PRICE3=0.01
                                                        PRICE4=0.01
                                                        PRICE5=0.01
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 4
                                                        PRICE1=45678.450000
                                                        PRICE2=45678.450000
                                                        PRICE3=45678.450000
                                                        PRICE4=45678.450000
                                                        PRICE5=45678.450000
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 4
                                                        PRICE1=45678.4
                                                        PRICE2=45678.45
                                                        PRICE3=45678.4
                                                        PRICE4=45678.4
                                                        PRICE5=45678.4
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 5
                                                        PRICE1=1000000000000000000000000000000000000000000000000000000000000000000000000000.000000
                                                        PRICE2=1000000000000000000000000000000000000000000000000000000000000000000000000000.000000
                                                        PRICE3=1000000000000000000000000000000000000000000000000000000000000000000000000000.000000
                                                        PRICE4=1000000000000000000000000000000000000000000000000000000000000000000000000000.000000
                                                        PRICE5=1000000000000000000000000000000000000000000000000000000000000000000000000000.000000
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 5
                                                        PRICE1=1e+75
                                                        PRICE2=999999999999999999999999999999999999999999999999999999999999999999999999999.99
                                                        PRICE3=1e+75
                                                        PRICE4=1e+75
                                                        PRICE5=999999999999999999999999999999999999999999999999999999999999999999999999999.99
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 6
                                                        PRICE1=12345678901.123500
                                                        PRICE2=12345678901.123500
                                                        PRICE3=12345678901.123500
                                                        PRICE4=12345678901.123500
                                                        PRICE5=12345678901.123500
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 6
                                                        PRICE1=1.23457e+10
                                                        PRICE2=12345678901.123456
                                                        PRICE3=1.23457e+10
                                                        PRICE4=1.23457e+10
                                                        PRICE5=12345678901.123456
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 7
                                                        PRICE1=8888888888.880000
                                                        PRICE2=8888888888.880000
                                                        PRICE3=8888888888.880000
                                                        PRICE4=8888888888.880000
                                                        PRICE5=8888888888.880000
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 7
                                                        PRICE1=8.88889e+09
                                                        PRICE2=8888888888.88
                                                        PRICE3=8.88889e+09
                                                        PRICE4=8.88889e+09
                                                        PRICE5=8888888888.88
    01-11 10:39:30.630 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 8
                                                        PRICE1=0.020000
                                                        PRICE2=0.020000
                                                        PRICE3=0.020000
                                                        PRICE4=0.020000
                                                        PRICE5=0.020000
    01-11 10:39:30.634 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 8
                                                        PRICE1=0.02
                                                        PRICE2=0.02
                                                        PRICE3=0.02
                                                        PRICE4=0.02
                                                        PRICE5=0.02
    01-11 10:39:30.634 3680-3680/? D/PRICEINFO_GETDBL:  Processing Row 9
                                                        PRICE1=56789.560000
                                                        PRICE2=56789.560000
                                                        PRICE3=56789.560000
                                                        PRICE4=56789.560000
                                                        PRICE5=56789.560000
    01-11 10:39:30.634 3680-3680/? D/PRICEINFO_GETSTR:  Processing Row 9
                                                        PRICE1=56789.6
                                                        PRICE2=56789.56
                                                        PRICE3=56789.6
                                                        PRICE4=56789.6
                                                        PRICE5=56789.56
    

    So :-

    • For row 0 (999999999999999999999999999999999999999.99 stored via a double) using getDouble the column type is insignificant, but for getString there is a subtle difference when the column type is TEXT. However, precision loses the value (see caveat above).

    • For row 1 (12345678901.123500 stored via a double) getDouble is fine for 15 significant figures. With getString all but the TEXT column lose out due to precision loss.

    • For row 2 (9999999999.99 stored via a double) is very much the same findings as for row 1.

    • For row 3 (0.01 stored via a double) is fine.

    • For row 4 (45678.45 stored via double) precision loss is an issue for getString except when it is a TEXT column.

    • For rows 5-9 the data is stored via a string, TEXT and BLOB columns accurately store the value in all cases with no precision loss. Otherwise the results are similar.

    0 讨论(0)
提交回复
热议问题