0

我的应用程序有问题。我的应用程序所做的是:从几个编辑文本中获取一些数据(每行 3 个,动态创建)并将它们放入数据库中。

我希望数据库做的是:取product name, thequantity和 theprice并将它们放在表中。名称应该是UNIQUE(它将用于为自动完成提供动力,它必须是唯一的,不能在 AC 列表中重复).数据库中的价格必须是该产品的最后插入价格(例如,如果Cheese插入 3$,然后Cheese在数据库中插入 2.5$,我们将找到 2.5$)。数量必须相加(如果我在数据库中输入数量 3 的奶酪,然后再次输入数量为 4 的奶酪,我们将找到 7)。

现在,我的问题:假设我在我的购物清单中输入了这个:

 1.     Hhhh    4   2.5
 2.     Dddd    3   1
 3.     Eeee    2   2
 4.     Aaaa    5   3.5

在我的数据库中,我会找到这个:

4.      Aaaa    4   2.5
2.      Dddd    3   1
3.      Eeee    2   2
1.      Hhhh    5   3.5

所以,问题是它按字母顺序排列产品名称列,但其他列保持相同的顺序,即我在编辑文本中输入的顺序。我做了一些测试,如果我UNIQUE从产品名称列中删除,它会按原样输入,但当然,它会创建重复项,我不需要。我不明白,怎么了?为什么会UNIQUE触发这个?

这是我的代码:

我的表创建:

public class SQLiteCountryAssistant extends SQLiteOpenHelper {
private static final String DB_NAME = "usingsqlite.db";
private static final int DB_VERSION_NUMBER = 1;
private static final String DB_TABLE_NAME = "countries";
private static final String DB_COLUMN_1_NAME = "country_name";
private static final String DB_COLUMN_2_NAME = "country_counter";
private static final String DB_COLUMN_3_NAME = "country_price";


private static final String DB_CREATE_SCRIPT = "create table "
        + DB_TABLE_NAME
        + " (_id INTEGER PRIMARY KEY,country_name text unique, country_quantity REAL DEFAULT '0',country_price REAL);) ";

private SQLiteDatabase sqliteDBInstance = null;

public SQLiteCountryAssistant(Context context) {
    super(context, DB_NAME, null, DB_VERSION_NUMBER);
}

@Override
public void onCreate(SQLiteDatabase sqliteDBInstance) {
    Log.i("onCreate", "Creating the database...");
    sqliteDBInstance.execSQL(DB_CREATE_SCRIPT);
}

我的插入方法:

public void insertCountry(String countryName, String countryPrice,
        String countryQuantity) {

    sqliteDBInstance.execSQL("INSERT OR IGNORE INTO " + DB_TABLE_NAME
            + "(country_name, country_quantity, country_price) VALUES('"
            + countryName + "','0', '" + countryPrice + "')");

    sqliteDBInstance.execSQL("UPDATE " + DB_TABLE_NAME
            + " SET country_name='" + countryName
            + "', country_quantity=country_quantity+'" + countryQuantity
            + "' WHERE country_name='" + countryName + "';");

    sqliteDBInstance.execSQL("UPDATE " + DB_TABLE_NAME
            + " SET country_name='" + countryName + "', country_price='"
            + countryPrice + "' WHERE country_name='" + countryName + "';");
}

这就是我调用插入方法的方式:

    for (int g = 0; g < allcant.size() - 1; g++) {
        if (prod[g] != "0.0") {
            sqlliteCountryAssistant.insertCountry(prod[g],pret[g],cant[g]);
        }

另外,请原谅我乱七八糟的代码,一个月前我开始学习没有编程背景的android。我刚获得社会学学士学位,所以是的,我是一个绝对的初学者。如果有办法做得更好我做到了,我很确定有,请给我指路,呵呵。

谢谢,祝你有美好的一天!

编辑:Aaa 和整个 db 类:

public class SQLiteCountryAssistant extends SQLiteOpenHelper {
private static final String DB_NAME = "usingsqlite.db";
private static final int DB_VERSION_NUMBER = 1;
private static final String DB_TABLE_NAME = "countries";
private static final String DB_COLUMN_1_NAME = "country_name";
private static final String DB_COLUMN_2_NAME = "country_counter";
private static final String DB_COLUMN_3_NAME = "country_price";

private static final String DB_CREATE_SCRIPT = "create table "
        + DB_TABLE_NAME
        + " ( id INTEGER PRIMARY KEY AUTOINCREMENT,country_name text unique, country_quantity REAL DEFAULT '0',country_price REAL)";

private SQLiteDatabase sqliteDBInstance = null;

public SQLiteCountryAssistant(Context context) {
    super(context, DB_NAME, null, DB_VERSION_NUMBER);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // TODO: Implement onUpgrade

}

@Override
public void onCreate(SQLiteDatabase sqliteDBInstance) {
    Log.i("onCreate", "Creating the database...");
    sqliteDBInstance.execSQL(DB_CREATE_SCRIPT);
}

public void openDB() throws SQLException {
    Log.i("openDB", "Checking sqliteDBInstance...");
    if (this.sqliteDBInstance == null) {
        Log.i("openDB", "Creating sqliteDBInstance...");
        this.sqliteDBInstance = this.getWritableDatabase();

    }
}

public void closeDB() {
    if (this.sqliteDBInstance != null) {
        if (this.sqliteDBInstance.isOpen())
            this.sqliteDBInstance.close();
    }
}

public void insertCountry(String countryName, String countryPrice,
        String countryQuantity) {
    ContentValues cv = new ContentValues();
    cv.put("country_name", countryName);
    cv.put("country_price", countryPrice);
    sqliteDBInstance.insertWithOnConflict(DB_TABLE_NAME, null, cv, sqliteDBInstance.CONFLICT_IGNORE);

    // Increment the quantity field (there isn't a good way to do this with sql.update() )
    sqliteDBInstance.execSQL("UPDATE " + DB_TABLE_NAME + " SET country_quantity=country_quantity+? WHERE country_name=?",
      new Object[] { new Long(countryQuantity), countryName }); 








    /*sqliteDBInstance.execSQL("INSERT OR IGNORE INTO " + DB_TABLE_NAME
            + "(country_name) VALUES('" + countryName + "')");

    sqliteDBInstance.execSQL("UPDATE " + DB_TABLE_NAME
            + " SET country_quantity=country_quantity+" + countryQuantity
            + " WHERE country_name='" + countryName + "';");

    sqliteDBInstance.execSQL("UPDATE " + DB_TABLE_NAME
            + " SET country_price=" + countryPrice
            + " WHERE country_name='" + countryName + "';");*/
}

public boolean removeCountry(String countryName) {
    int result = this.sqliteDBInstance.delete(DB_TABLE_NAME,
            "country_name='" + countryName + "'", null);

    if (result > 0)
        return true;
    else
        return false;
}

public long updateCountry(String oldCountryName, String newCountryName) {
    ContentValues contentValues = new ContentValues();
    contentValues.put(DB_COLUMN_1_NAME, newCountryName);
    return this.sqliteDBInstance.update(DB_TABLE_NAME, contentValues,
            "country_name='" + oldCountryName + "'", null);
}

public String[] getAllCountries() {
    Cursor cursor = this.sqliteDBInstance.query(DB_TABLE_NAME,
            new String[] { DB_COLUMN_1_NAME }, null, null, null, null,
            DB_COLUMN_1_NAME + " ASC");

    if (cursor.getCount() > 0) {
        String[] str = new String[cursor.getCount()];
        // String[] strpri = new String[cursor.getCount()];
        int i = 0;

        while (cursor.moveToNext()) {
            str[i] = cursor.getString(cursor
                    .getColumnIndex(DB_COLUMN_1_NAME));
            // strpri[i] = cursor.getString(cursor
            // .getColumnIndex(DB_COLUMN_2_NAME));
            i++;
        }
        return str;
    } else {
        return new String[] {};
    }
}

}
4

2 回答 2

2

我还没有弄清楚疯狂的顺序,但我发现了两件事甚至可以澄清一些事情:

  1. 您的创建表 sql 有一个右括号太多(删除分号后的那个)
  2. 你的插入方法真的很乱:)我会把它分成两种方法。

一般的方法是创建一个 insertOrUpdate 方法来查询数据库中的条目(在您的情况下是 countryName)。如果条目存在,它将被更新,否则将被插入。由于您是初学者,因此自己完成这项任务可能是一项不错的任务,您应该在不同的问题中获得关于 SO 的基本代码。

最后的提示(您可能已经看过):使用参数版本和/或数据库中的真实更新/插入方法。

db.insert(TABLE_NAME, null, contentValues); // see class ContentValues for details

根据execSQL()方法,您不应将其用于任何 SELECT/INSERT/UPDATE/DELETE 语句:

执行不是 SELECT/INSERT/UPDATE/DELETE 的单个 SQL 语句。

现在我的问题哪个答案可能对我有所帮助:
我还想知道您如何验证数据库内容的顺序?您是否在您的 android 代码中创建了一个查询来查询内容,或者您​​是否使用 SQLite 管理器工具打开了 db 文件?如果您查询,您是否也可以在您的问题中包含您的查询/显示代码?

于 2013-07-09T00:10:10.463 回答
2

在@WarrenFaith 的出色建议中添加了几件事。我同意错误可能出现在您未显示的代码中。

  1. UPDATE SQL 中增量值的引号是错误的。应该是例如quantity=quantity+42,不是quantity=quantity+'42'
  2. 您需要使用参数转义(问号?)来避免包括对您的应用程序的 SQL 插入攻击在内的问题。
  3. 插入逻辑非常复杂。也许这就是问题所在。

你想要这样的东西:

// Insert or ignore.
ContentValues cv = new ContentValues();
cv.put("country_name", country_name);
cv.put("country_price", country_price);
sql.insertWithOnConflict(DB_TABLE_NAME, null, cv, CONFLICT_IGNORE);

// Increment the quantity field (there isn't a good way to do this with sql.update() )
sql.execSQL("UPDATE " + DB_TABLE_NAME + " SET country_quantity=country_quantity+? WHERE country_name=?",
  new Object[] { new Long(country_quantity), country_name }); 

而且您没有提到 LogCat 是否干净。它必须至少显示关于引号问题的数据库错误。还建议您确保在调试运行之间删除并重建表。

于 2013-07-09T04:09:04.720 回答