sqlite 数据库中的主键未正确返回
Primary key not returned correctly in sqlite database
我正在创建一个应用程序来理解 sqlite 数据库。
enter image description here
每当我单击添加按钮时,名称都会添加到 sqlite 数据库中
btnAdd.setOnClickListener(v -> {
DBHelper helper=new DBHelper(MainActivity.this, null, null, 1);
EmployeeData data=new EmployeeData(1, etName.getText().toString());
int id=helper.add(data);
data.setId(id);
Toast.makeText(MainActivity.this, Integer.toString(id), Toast.LENGTH_SHORT).show();
});
EmployeeData 仅包含参数的构造函数以及 getter 和 setter。
DBHelper 代码:
public int add(EmployeeData data){
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
db.insert(TABLE_NAME, null, cv);
String sql="SELECT * FROM "+TABLE_NAME+" WHERE "+NAME+" = "+"'"+data.getName()+"'";
Cursor c=db.rawQuery(sql, null);
int id;
if (c.moveToFirst()) {
id = c.getInt(c.getColumnIndex(ID));
}else {
id=-1;
}
c.close();
db.close();
return id;
}
假设我在编辑文本中输入“Aditya”,我收到祝酒消息 1。
但是当我将名称更改为“Adity”时,我仍然收到消息 1。
为什么第二条记录的主键没有变化?
我什至尝试添加 AUTOINCREMENT 但它不起作用。
有什么问题?
顺便说一句,员工数据构造函数中的 1
与主键无关
数据库创建:
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
db.execSQL(sql);
}
这是我在 SQLite 中使用的代码,当时我需要新的 auto_increment 主键:
int getId(){
ResultSet rs = statement.getGeneratedKeys();
if (rs.next()) {
id = rs.getLong(1);
return id;
}
}
where 语句是 PreparedStatement
如果你看看insert方法。它 returns 插入行的 id,作为 long,如果未插入该行,则为 -1。
- 理论上id可以是long,建议使用long而不是int。
假设id列是rowid
的别名。
- 根据您的 CREATE SQL 是。
您的代码可以更简单:-
public long add(EmployeeData data){
long id;
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
id = db.insert(TABLE_NAME, null, cv);
db.close();
return id;
}
但是关闭数据库效率低下-
- 关闭本身并没有那么低效,低效是再次打开数据库,相对昂贵。
- 这个 q/a 有一些关于这个 Best place to close database connection
的细节
我会建议更简单的:-
public long add(EmployeeData data) {
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
return db.insert(TABLE_NAME, null, cv);
}
例子
这是基于您的代码的示例代码(使用 logcat 以及 toast):-
数据库助手DBHelper
public class DBHelper extends SQLiteOpenHelper {
public static String DBNAME = "MYDB";
public static int DBVERSION = 1;
public static String TABLE_NAME = "mytable";
public static String ID = "_id";
public static String NAME = "_name";
public DBHelper(@Nullable Context context) {
super(context, DBNAME, null, DBVERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public long add(EmployeeData data) {
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
return db.insert(TABLE_NAME, null, cv);
}
}
正在调用Activity
- onClickListener 已替换为直接调用 2 个插入
- 除了使用toast之外,日志还用于记录id的插入
:-
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBHelper helper=new DBHelper(MainActivity.this);
EmployeeData data=new EmployeeData(1, "TestIt");
long id=helper.add(data);
data.setId(id);
Toast.makeText(MainActivity.this, Long.toString(id), Toast.LENGTH_SHORT).show();
Log.d("ADDEMP","ID of Employee was " + id);
data.setName("TestAnother");
data.setId(id =helper.add(data));
Toast.makeText(this,Long.toString(id),Toast.LENGTH_SHORT).show();
Log.d("ADDEMP","ID of Employee was " + id);
}
}
EmployeeDataclass(猜测):-
public class EmployeeData {
long id;
String name;
int something;
EmployeeData(int something, String name) {
this.id = -1;
this.name = name;
this.something = something;
}
public long getId() {
return id;
}
public int getSomething() {
return something;
}
public String getName() {
return name;
}
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setSomething(int something) {
this.something = something;
}
}
结果
当以上为运行确保不存在数据库后(通过设置从测试设备(模拟器)卸载App)
- 卸载应用程序会删除数据库,如果对架构进行了任何更改,则应进行卸载,否则将不会应用这些更改(不完全正确,因为您可以引入代码来进行此类更改)。
LogCat 显示:-
D/ADDEMP: ID of Employee was 1
D/ADDEMP: ID of Employee was 2
如果 运行 第二次显示 LogCat :-
D/ADDEMP: ID of Employee was 3
D/ADDEMP: ID of Employee was 4
根据评论补充
根据您的评论,您无意中使用了临时 database/in_memory 数据库,并且每次都将行添加到新数据库中,因此 ID 始终为 1。
以下是基于您的 GITHUB 代码的一些建议更改(请参阅代码中的注释)。
DBHelper
public class DBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "adityya425"; //<<<<<<<<<< SUGGESTED ADDITION
public static final int DB_VERSION = 1; //<<<<<<<<<< ADDED
final String TABLE_NAME="Employee";
final String ID="_id";
final String NAME="name";
/*
<<<<<<<<<< Replaced constructor with simpler to use (only requires the Context to be passed to the helper)
public DBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, null, version);
}
*/
public DBHelper(Context context) {
super(context,DB_NAME,null,DB_VERSION); //<<<<<<<<<< only context is passed
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long add(EmployeeData data){
long id;
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
id=db.insert(TABLE_NAME, null, cv);
//String sql="SELECT * FROM "+TABLE_NAME+" WHERE "+NAME+" = "+"'"+data.getName()+"'";
//Cursor c=db.rawQuery(sql, null);
// if (c.moveToFirst()) {
// id = c.getInt(c.getColumnIndex(ID));
// }else {
// id=-1;
// }
return id;
}
/*
<<<<<<<<<< NOT REQUIRED optional extra that will output all the existing rows to the log
e.g.
2021-03-23 18:21:01.749 4963-4963/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = harry
2021-03-23 18:21:01.749 4963-4963/a.a.adityya425 D/CURSORINFO: ID = 2 NAME = bert
*/
public void showALL(Context context) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(TABLE_NAME,null,null,null,null,null,null);
while (csr.moveToNext()) {
Log.d("CURSORINFO","ID = " + csr.getLong(csr.getColumnIndex(ID)) + " NAME = " + csr.getString(csr.getColumnIndex(NAME)));
}
csr.close();
}
}
主要Activity
public class MainActivity extends AppCompatActivity {
EditText etName;
Button btnAdd;
DBHelper helper; //<<<<<<<<<< Single helper with class scope
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = new DBHelper(this); //<<<<<<<< Instantiate Helper
etName=findViewById(R.id.etName);
btnAdd=findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(v -> {
//DBHelper helper=new DBHelper(MainActivity.this, "mydb", null, 1); <<<<<<<<<< REMOVED (no need)
EmployeeData data=new EmployeeData(etName.getText().toString());
long id=helper.add(data);
data.setId(id);
Toast.makeText(MainActivity.this, Long.toString(id), Toast.LENGTH_SHORT).show();
helper.showALL(MainActivity.this); //<<<<<<<<<< Optional (logcat is available longer)
});
}
}
测试
应用 运行 并添加了 3 名员工(Fred、Mary 和 Susan)。 logcat 显示:-
2021-03-23 18:40:15.495 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = Fred
2021-03-23 18:40:22.964 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = Fred
2021-03-23 18:40:22.964 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 2 NAME = Mary
2021-03-23 18:40:29.643 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = Fred
2021-03-23 18:40:29.643 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 2 NAME = Mary
2021-03-23 18:40:29.643 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 3 NAME = Susan
我正在创建一个应用程序来理解 sqlite 数据库。
enter image description here
每当我单击添加按钮时,名称都会添加到 sqlite 数据库中
btnAdd.setOnClickListener(v -> {
DBHelper helper=new DBHelper(MainActivity.this, null, null, 1);
EmployeeData data=new EmployeeData(1, etName.getText().toString());
int id=helper.add(data);
data.setId(id);
Toast.makeText(MainActivity.this, Integer.toString(id), Toast.LENGTH_SHORT).show();
});
EmployeeData 仅包含参数的构造函数以及 getter 和 setter。
DBHelper 代码:
public int add(EmployeeData data){
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
db.insert(TABLE_NAME, null, cv);
String sql="SELECT * FROM "+TABLE_NAME+" WHERE "+NAME+" = "+"'"+data.getName()+"'";
Cursor c=db.rawQuery(sql, null);
int id;
if (c.moveToFirst()) {
id = c.getInt(c.getColumnIndex(ID));
}else {
id=-1;
}
c.close();
db.close();
return id;
}
假设我在编辑文本中输入“Aditya”,我收到祝酒消息 1。
但是当我将名称更改为“Adity”时,我仍然收到消息 1。
为什么第二条记录的主键没有变化?
我什至尝试添加 AUTOINCREMENT 但它不起作用。
有什么问题?
顺便说一句,员工数据构造函数中的 1
与主键无关
数据库创建:
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
db.execSQL(sql);
}
这是我在 SQLite 中使用的代码,当时我需要新的 auto_increment 主键:
int getId(){
ResultSet rs = statement.getGeneratedKeys();
if (rs.next()) {
id = rs.getLong(1);
return id;
}
}
where 语句是 PreparedStatement
如果你看看insert方法。它 returns 插入行的 id,作为 long,如果未插入该行,则为 -1。
- 理论上id可以是long,建议使用long而不是int。
假设id列是rowid
的别名。
- 根据您的 CREATE SQL 是。
您的代码可以更简单:-
public long add(EmployeeData data){
long id;
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
id = db.insert(TABLE_NAME, null, cv);
db.close();
return id;
}
但是关闭数据库效率低下-
- 关闭本身并没有那么低效,低效是再次打开数据库,相对昂贵。
- 这个 q/a 有一些关于这个 Best place to close database connection 的细节
我会建议更简单的:-
public long add(EmployeeData data) {
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
return db.insert(TABLE_NAME, null, cv);
}
例子
这是基于您的代码的示例代码(使用 logcat 以及 toast):-
数据库助手DBHelper
public class DBHelper extends SQLiteOpenHelper {
public static String DBNAME = "MYDB";
public static int DBVERSION = 1;
public static String TABLE_NAME = "mytable";
public static String ID = "_id";
public static String NAME = "_name";
public DBHelper(@Nullable Context context) {
super(context, DBNAME, null, DBVERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public long add(EmployeeData data) {
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
return db.insert(TABLE_NAME, null, cv);
}
}
正在调用Activity
- onClickListener 已替换为直接调用 2 个插入
- 除了使用toast之外,日志还用于记录id的插入
:-
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBHelper helper=new DBHelper(MainActivity.this);
EmployeeData data=new EmployeeData(1, "TestIt");
long id=helper.add(data);
data.setId(id);
Toast.makeText(MainActivity.this, Long.toString(id), Toast.LENGTH_SHORT).show();
Log.d("ADDEMP","ID of Employee was " + id);
data.setName("TestAnother");
data.setId(id =helper.add(data));
Toast.makeText(this,Long.toString(id),Toast.LENGTH_SHORT).show();
Log.d("ADDEMP","ID of Employee was " + id);
}
}
EmployeeDataclass(猜测):-
public class EmployeeData {
long id;
String name;
int something;
EmployeeData(int something, String name) {
this.id = -1;
this.name = name;
this.something = something;
}
public long getId() {
return id;
}
public int getSomething() {
return something;
}
public String getName() {
return name;
}
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setSomething(int something) {
this.something = something;
}
}
结果
当以上为运行确保不存在数据库后(通过设置从测试设备(模拟器)卸载App)
- 卸载应用程序会删除数据库,如果对架构进行了任何更改,则应进行卸载,否则将不会应用这些更改(不完全正确,因为您可以引入代码来进行此类更改)。
LogCat 显示:-
D/ADDEMP: ID of Employee was 1
D/ADDEMP: ID of Employee was 2
如果 运行 第二次显示 LogCat :-
D/ADDEMP: ID of Employee was 3
D/ADDEMP: ID of Employee was 4
根据评论补充
根据您的评论,您无意中使用了临时 database/in_memory 数据库,并且每次都将行添加到新数据库中,因此 ID 始终为 1。
以下是基于您的 GITHUB 代码的一些建议更改(请参阅代码中的注释)。
DBHelper
public class DBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "adityya425"; //<<<<<<<<<< SUGGESTED ADDITION
public static final int DB_VERSION = 1; //<<<<<<<<<< ADDED
final String TABLE_NAME="Employee";
final String ID="_id";
final String NAME="name";
/*
<<<<<<<<<< Replaced constructor with simpler to use (only requires the Context to be passed to the helper)
public DBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, null, version);
}
*/
public DBHelper(Context context) {
super(context,DB_NAME,null,DB_VERSION); //<<<<<<<<<< only context is passed
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long add(EmployeeData data){
long id;
SQLiteDatabase db=getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(NAME, data.getName());
id=db.insert(TABLE_NAME, null, cv);
//String sql="SELECT * FROM "+TABLE_NAME+" WHERE "+NAME+" = "+"'"+data.getName()+"'";
//Cursor c=db.rawQuery(sql, null);
// if (c.moveToFirst()) {
// id = c.getInt(c.getColumnIndex(ID));
// }else {
// id=-1;
// }
return id;
}
/*
<<<<<<<<<< NOT REQUIRED optional extra that will output all the existing rows to the log
e.g.
2021-03-23 18:21:01.749 4963-4963/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = harry
2021-03-23 18:21:01.749 4963-4963/a.a.adityya425 D/CURSORINFO: ID = 2 NAME = bert
*/
public void showALL(Context context) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(TABLE_NAME,null,null,null,null,null,null);
while (csr.moveToNext()) {
Log.d("CURSORINFO","ID = " + csr.getLong(csr.getColumnIndex(ID)) + " NAME = " + csr.getString(csr.getColumnIndex(NAME)));
}
csr.close();
}
}
主要Activity
public class MainActivity extends AppCompatActivity {
EditText etName;
Button btnAdd;
DBHelper helper; //<<<<<<<<<< Single helper with class scope
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = new DBHelper(this); //<<<<<<<< Instantiate Helper
etName=findViewById(R.id.etName);
btnAdd=findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(v -> {
//DBHelper helper=new DBHelper(MainActivity.this, "mydb", null, 1); <<<<<<<<<< REMOVED (no need)
EmployeeData data=new EmployeeData(etName.getText().toString());
long id=helper.add(data);
data.setId(id);
Toast.makeText(MainActivity.this, Long.toString(id), Toast.LENGTH_SHORT).show();
helper.showALL(MainActivity.this); //<<<<<<<<<< Optional (logcat is available longer)
});
}
}
测试
应用 运行 并添加了 3 名员工(Fred、Mary 和 Susan)。 logcat 显示:-
2021-03-23 18:40:15.495 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = Fred
2021-03-23 18:40:22.964 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = Fred
2021-03-23 18:40:22.964 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 2 NAME = Mary
2021-03-23 18:40:29.643 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 1 NAME = Fred
2021-03-23 18:40:29.643 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 2 NAME = Mary
2021-03-23 18:40:29.643 5642-5642/a.a.adityya425 D/CURSORINFO: ID = 3 NAME = Susan