我使用OID作为具有自动增量的主键,但我想使Txn No也具有自动增量。有什么办法可以使其自动递增?我尝试使用循环,但似乎不起作用。
一次单击“保存”时,下一次应为Txn否“ 2”,但我想不起来,因为我使用OID进行自动递增,所以Txn否不能使用它。
这是我的代码:
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "Person.db";
public static final String TABLE_NAME = "Person_Table";
public static final String COL_1 = "OID";
public static final String COL_2 = "TxnNo";
public static final String COL_3 = "Name";
public static final String COL_4 = "Amount";
public static final String COL_5 = "Date";
public static final String COL_6 = "Description";
public static final String COL_7 = "Description2";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + " (OID INTEGER PRIMARY KEY AUTOINCREMENT," +
"TxnNo TEXT, Name TEXT, Amount INTEGER,Date TEXT, Description TEXT,Description2 TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public boolean insertData(String TxnNo, String Name, String Amount, String Date, String Description, String Description2) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_2, TxnNo);
contentValues.put(COL_3, Name);
contentValues.put(COL_4, Amount);
contentValues.put(COL_5, Date);
contentValues.put(COL_6, Description);
contentValues.put(COL_7, Description2);
long result = db.insert(TABLE_NAME, null, contentValues);
if (result == -1)
return false;
else
return true;
}
}
最佳答案
使用SQLite AUTOINCREMENT的第一件事实际上并没有增加ID,使用INTEGER PRIMARY KEY会产生几乎相同的结果,除了添加了9223372036854775807行之外。所有AUTOINCREMENT所做的就是强制增加数量(因此,当到达最大的rowid时,会发生SQLITE FULL异常),否则(没有AUTOINCREMENT)可以分配免费的较低数字,从而有可能规避SQLITE FULL异常。
实际上,INTEGER PRIMARY KEY(带有或不带有AUTOINCREMENT)的作用是使rowid的columnn别名(通常隐藏的列,具有唯一的64位带符号整数)。
规则之一是每个表只能对INTEGER PRIMARY KEY(或PRIMARY KEY)进行编码。这是您面临的问题。
一个办法
一种方法是使用插入新行时触发的TRIGGER,并使用该触发器以OID后缀的值更新插入的行。例如
CREATE TRIGGER IF NOT EXISTS increment_tax_number
AFTER INSERT ON Person_Table
BEGIN
UPDATE Person_Table SET TxnNo = 'Txn no '||new.OID WHERE OID = new.OID;
END;
INSERT INTO Person_Table VALUES(null,'not a valid tax number as yet','Fred',15000,'2018-01-01','blah','more blah');
INSERT INTO Person_Table VALUES(null,'not a valid tax number as yet','Bert',25000,'2018-03-04','blah','more blah');
SELECT * FROM Person_Table;
对于一个新表,以上结果为:
该解决方案可以通过以下方式合并:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + " (OID INTEGER PRIMARY KEY AUTOINCREMENT," +
"TxnNo TEXT, Name TEXT, Amount INTEGER,Date TEXT, Description TEXT,Description2 TEXT)");
db.execsql("CREATE TRIGGER If NOT EXISTS increment_tax_number AFTER INSERT ON Person_Table
BEGIN
UPDATE Person_Table SET TxnNo = 'Txn no '||new.OID WHERE OID = new.OID;
END");
}
您需要删除应用程序的数据,卸载应用程序或增加版本号(即使用
super(context, DATABASE_NAME, null, 2)
)。注意您将丢失任何现有数据。不丢失数据将更加复杂。更有效的解决方案
当然,还有一种选择是仅使用OID,因为您似乎希望将数字部分附加到Txn No,因此甚至不需要浪费一列。需要时可以生成Txn No 1,Txn No 2等。
例如以下将纯粹从OID列生成Txn No:
SELECT Name, 'Txn No '||OID AS txn_no,Amount,Description,Description2 FROM Person_Table;
导致 :-
要合并此解决方案,除了使用适当的查询外,您无需执行其他任何操作(尽管您可能希望删除TxnNo列)
有关AUTOINCREMENT的更多信息
使用AUTOINCREMENT会产生很少需要的开销。 SQLite文档包括:-
AUTOINCREMENT关键字强加了额外的CPU,内存,磁盘空间和
磁盘I / O开销,如果没有严格要求,则应避免。它是
通常不需要。
SQLite Autoincrement
开销是因为使用AUTOINCREMENT时,用于确定新rowid的算法增加了第二阶段,即从sqlite_sequence表中获取相应行,然后使用此表中的较高者和表中的最高rowid(不使用AUTOINCREMENT只是最高的rowid使用表格中的)。因此,必须为每个插入维护和访问此附加表的开销。
因此,使用以下任一方法来定义表会更有效:
CREATE TABLE IF NOT EXISTS Person_Table (OID INTEGER PRIMARY KEY,TxnNo TEXT, Name TEXT, Amount INTEGER,Date TEXT, Description TEXT,Description2 TEXT);
如果您决定使用TxnNo列
要么 :-
CREATE TABLE IF NOT EXISTS Person_Table (OID INTEGER PRIMARY KEY, Name TEXT, Amount INTEGER,Date TEXT, Description TEXT,Description2 TEXT);
如果使用派生的Txn No(更有效的解决方案)
关于java - 如何在Sqlite中使两列自动递增,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51997243/