如何从列中检索值并将其应用于Android的SQLite中的下一行?

时间:2018-11-16 03:36:05

标签: android sqlite

我正在创建一个支票簿应用程序,并希望在应用交易后获取帐户的价值。然后,我想更新后续交易,以反映每次交易后的新金额。我在Android上使用SQLite。我想在时间轴的任何位置输入交易,如果以后出现任何交易,余额将被更新。这应该像网上银行的交易一样工作。

我尝试使用for循环,while循环等 我只是似乎无法访问正确的数据。

示例

Transaction 1.        $33.00.        Balance $33.00
Transaction 2.        $5.00.         Balance $38.00
Transaction 3.        $10.00.        Balance $48.00

这是我正在开发的第一个完整应用程序,相对于一般而言还比较新。

即使指向正确方向的指针也将不胜感激。

2 个答案:

答案 0 :(得分:1)

要在插入/更新/删除(甚至选择)时自动执行某些操作,可以使用将自动运行的TRIGGER。

SQL As Understood By SQLite - CREATE TRIGGER(建议您仔细阅读)

以下内容可能足够或作为基础。它可以处理您的测试数据(如下所示):-

CREATE TRIGGER IF NOT EXISTS adjust_balance_after_insert 
    AFTER INSERT ON transaction_table -- After an insert
        BEGIN
          -- Update the transaction table for this row (and any that are > (likely none))
            UPDATE transaction_table
                -- set the balance to be the new amount + the highest balance of the previous transaction
                SET balance = new.amount + (
                    SELECT
                        CASE 
                            WHEN
                                -- if no previous transaction then balance is 0 (may need to cater for a starting balance, although that could be the first transaction)
                                (SELECT max(balance) FROM transaction_table WHERE id = (new.id - 1) ORDER BY id DESC LIMIT 1) IS NULL THEN 0
                            ELSE
                                -- if there is a previous transaction then the balance is this amount + the balance (max(balance) could be just balance)
                                (SELECT max(balance) FROM transaction_table WHERE id = (new.id - 1) ORDER BY id DESC LIMIT 1)
                            END
                    )
            WHERE id >= new.id ;
        END;

以下是用于测试上述内容的SQL:-

DROP TABLE IF EXISTS transaction_table;
DROP TRIGGER IF EXISTS adjust_balanace_after_insert;
CREATE TABLE IF NOT EXISTS transaction_table (id INTEGER PRIMARY KEY AUTOINCREMENT, item TEXT, amount INTEGER, balance INTEGER);


-- The trigger
CREATE TRIGGER IF NOT EXISTS adjust_balanace_after_insert 
    AFTER INSERT ON transaction_table -- After an insert
        BEGIN
          -- Update the transaction table for this row (and any that are > (likely none))
            UPDATE transaction_table
                -- set the blanace to be the new amount + the highest balance of the previous transaction
                SET balance = new.amount + (
                    SELECT
                        CASE 
                            WHEN
                                -- if no previous transaction then balance is 0 (may need to cater for a starting balance, although that could be the first transaction)
                                (SELECT max(balance) FROM transaction_table WHERE id = (new.id - 1) ORDER BY id DESC LIMIT 1) IS NULL THEN 0
                            ELSE
                                -- if there is a previous transaction then the blanace is this amount + the blanace (max(balance) could be just balance)
                                (SELECT max(balance) FROM transaction_table WHERE id = (new.id - 1) ORDER BY id DESC LIMIT 1)
                            END
                    )
            WHERE id >= new.id ;
        END;

-- Test it
INSERT INTO transaction_table (item,amount) VALUES ('tv001',3300),('tv002',500),('tv003',1000);
SELECT * FROM transaction_table;

结果为:-

enter image description here

  • 注意使用了整数(长整数),有些人建议将其作为REAL使用(双精度/浮点数会导致精度问题)
  • 对于android,您将以与创建表相同的方式创建触发器,尽管稍微复杂一点。
  • 注意,它不处理已删除已更新的交易。
  • 注意,它假设将 ORDER BY LIMIT max(balance)结合使用的顺序编号只需使用更合适的 WHERE 子句(WHERE id < (new.id))。

答案 1 :(得分:0)

这是android更新所有余额(可以更改为从特定交易中更新)的另一种可能更简单的方法。

该示例使用带有列的名为** transaction_table *的表

  • 时间戳(YYYY:MM:DD HH:MM:DD)
  • 项目(交易说明)
  • 金额(交易金额,如果用于)
  • 余额(根据时间戳记,每个订单的余额)
    • 余额金额为整数(java长)(避免精度问题)

解决方案的症结是两种方法,它们用于获取先前的交易余额(getPreviousBalance)和基于检索到的先前的平衡更新所有余额(updateBalances)(如果没有先前的交易则为0)

SQLieOpenHelper(也称为Databasehelper)的子类是 TransactionHelper.java ,它是:-

public class TransactionHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "transaction.db";
    public static final int DBVERSION = 1;
    public static final String TB_TRANSACTION = "transaction_table";
    public static final String COL_TRANSACTION_TIMESTAMP = "timestamp";
    public static final String COl_TRANSACTION_ITEM = "item";
    public static final String COL_TRANSACTION_AMOUNT = "amount";
    public static final String COl_TRANSACTION_BALANCE = "balance";

    SQLiteDatabase mDB;
    public TransactionHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String crt_sql = "CREATE TABLE IF NOT EXISTS " + TB_TRANSACTION + "(" +
                COL_TRANSACTION_TIMESTAMP + " TEXT PRIMARY KEY DEFAULT CURRENT_TIMESTAMP, " +
                COl_TRANSACTION_ITEM + " TEXT, " +
                COL_TRANSACTION_AMOUNT + " INTEGER, " +
                COl_TRANSACTION_BALANCE + " INTEGER " +
                ")";
        db.execSQL(crt_sql);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1) {

    }

    public long insertTransaction(String item, long amount, String timestamp) {
        long rv = -1;
        ContentValues cv = new ContentValues();
        cv.put(COL_TRANSACTION_TIMESTAMP,timestamp);
        cv.put(COl_TRANSACTION_ITEM,item);
        cv.put(COL_TRANSACTION_AMOUNT,amount);
        rv = mDB.insert(TB_TRANSACTION,null,cv);
        updateBalances(); //<<<<<<<<<< Update the balances
        return rv;
    }

    public void logLedger(String description) {
        Cursor csr = mDB.query(TB_TRANSACTION,null,null,null,null, null,COL_TRANSACTION_TIMESTAMP + " ASC");
        Log.d("LEDGER", "Displaying Ledger - " + description);
        while (csr.moveToNext()) {
            Log.d(
                    "LEGDER",
                    "Date = " +
                            csr.getString(csr.getColumnIndex(COL_TRANSACTION_TIMESTAMP)) +
                            " Item = " +
                            csr.getString(csr.getColumnIndex(COl_TRANSACTION_ITEM)) +
                            " Amount = " +
                            String.valueOf(csr.getLong(csr.getColumnIndex(COL_TRANSACTION_AMOUNT))) +
                            " Balance = " +
                            String.valueOf(csr.getLong(csr.getColumnIndex(COl_TRANSACTION_BALANCE)))
            );
        }
        csr.close();
    }

    private void updateBalances() {
        String whereclause = COL_TRANSACTION_TIMESTAMP + "=?";
        String[] whereargs = new String[1];
        Cursor csr = mDB.query(TB_TRANSACTION,null,null,null,null,null,COL_TRANSACTION_TIMESTAMP + " ASC");
        mDB.beginTransaction();
        while (csr.moveToNext()) {
            long balance_to_apply = csr.getLong(csr.getColumnIndex(COL_TRANSACTION_AMOUNT)) + getPreviousBalance(csr.getString(csr.getColumnIndex(COL_TRANSACTION_TIMESTAMP)));
            ContentValues cv = new ContentValues();
            cv.put(COl_TRANSACTION_BALANCE,String.valueOf(balance_to_apply));
            whereargs[0] = csr.getString(csr.getColumnIndex(COL_TRANSACTION_TIMESTAMP));
            mDB.update(TB_TRANSACTION,cv,whereclause,whereargs);
        }
        csr.close();
        mDB.setTransactionSuccessful();
        mDB.endTransaction();
    }

    private long getPreviousBalance(String datetime) {
        long rv = 0;
        String[] columns = new String[]{COl_TRANSACTION_BALANCE};
        String whereclause = COL_TRANSACTION_TIMESTAMP + "<?";
        String[] whereargs = new String[]{datetime};
        Cursor csr = mDB.query(TB_TRANSACTION,columns,whereclause,whereargs,null,null,COL_TRANSACTION_TIMESTAMP + " DESC","1");
        if (csr.moveToFirst()) {
            rv = csr.getLong(csr.getColumnIndex(COl_TRANSACTION_BALANCE));
        }
        csr.close();
        return rv;
    }
}

根据活动 MainActivity.java 进行的测试:-

public class MainActivity extends AppCompatActivity {

    TransactionHelper mTAHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTAHlpr = new TransactionHelper(this);

        mTAHlpr.insertTransaction("T001",10000,"2018-01-01 10:30:00");
        mTAHlpr.insertTransaction("T002",20000,"2018-01-01 11:30:01");
        mTAHlpr.insertTransaction("T003",30000,"2018-01-01 12:30:45");


        mTAHlpr.logLedger("After 3 rows inserted");

        mTAHlpr.insertTransaction("T004",100000,"2017-01-01 09:00:00");
        mTAHlpr.logLedger("Another First row inserted");

        mTAHlpr.insertTransaction("T005",200000,"2018-01-01 10:32:00");
        mTAHlpr.logLedger("Row inserted after 2nd");

    }
}

结果(分类帐):-

11-16 22:32:41.630 1387-1387/so53291104.so53291104 D/LEDGER: Displaying Ledger - After 3 rows inserted
11-16 22:32:41.630 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 10:30:00 Item = T001 Amount = 10000 Balance = 10000
11-16 22:32:41.630 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 11:30:01 Item = T002 Amount = 20000 Balance = 30000
11-16 22:32:41.630 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 12:30:45 Item = T003 Amount = 30000 Balance = 60000
11-16 22:32:41.638 1387-1387/so53291104.so53291104 D/LEDGER: Displaying Ledger - Another First row inserted
11-16 22:32:41.638 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2017-01-01 09:00:00 Item = T004 Amount = 100000 Balance = 100000
11-16 22:32:41.638 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 10:30:00 Item = T001 Amount = 10000 Balance = 110000
11-16 22:32:41.638 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 11:30:01 Item = T002 Amount = 20000 Balance = 130000
11-16 22:32:41.638 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 12:30:45 Item = T003 Amount = 30000 Balance = 160000
11-16 22:32:41.646 1387-1387/so53291104.so53291104 D/LEDGER: Displaying Ledger - Row inserted after 2nd
11-16 22:32:41.646 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2017-01-01 09:00:00 Item = T004 Amount = 100000 Balance = 100000
11-16 22:32:41.646 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 10:30:00 Item = T001 Amount = 10000 Balance = 110000
11-16 22:32:41.646 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 10:32:00 Item = T005 Amount = 200000 Balance = 310000
11-16 22:32:41.646 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 11:30:01 Item = T002 Amount = 20000 Balance = 330000
11-16 22:32:41.646 1387-1387/so53291104.so53291104 D/LEGDER: Date = 2018-01-01 12:30:45 Item = T003 Amount = 30000 Balance = 360000