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