简体   繁体   English

sqlite 数据库中未正确返回主键

[英]Primary key not returned correctly in sqlite database

I am creating an app to understand sqlite database.我正在创建一个应用程序来了解 sqlite 数据库。

enter image description here在此处输入图像描述

Whenever I click add button the name would be added in sqlite database每当我单击添加按钮时,名称都会添加到 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 just contains constructor and getters and setters for the arguments. EmployeeData 只包含 arguments 的构造函数、getter 和 setter。

DBHelper code: 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;
    }

Consider I am entering "Aditya" in the edit text, I am getting a toast message of 1.考虑我在编辑文本中输入“Aditya”,我收到 1 的 toast 消息。

But when I change the name as "Adity" I am still getting a toast message of 1.但是当我将名称更改为“Adity”时,我仍然收到 1 的敬酒消息。

Why isn't primary key of second record changing?为什么第二条记录的主键没有改变?

I even tried adding AUTOINCREMENT but it doesn't work.我什至尝试添加 AUTOINCREMENT 但它不起作用。

What is the problem?问题是什么?

Btw the 1 in employee data constructor has no relation to the primary key顺便说一句,员工数据构造函数中的1与主键无关

Database creation:数据库创建:

@Override
    public void onCreate(SQLiteDatabase db) {
        String sql="CREATE TABLE "+TABLE_NAME+" ( "+ID+" INTEGER PRIMARY KEY, "+NAME+" VARCHAR2(25))";
        db.execSQL(sql);
    }

This is the code I used in SQLlite when I needed the new auto incremented primary key:这是我在需要新的自动递增主键时在SQLlite中使用的代码:

 int getId(){
    ResultSet rs = statement.getGeneratedKeys();
    if (rs.next()) {
        id = rs.getLong(1);
        return id;
    }
}

where statement is a PreparedStatement where 语句是PreparedStatement

If you look at the insert method.如果你看一下插入方法。 It returns the id, as a long, of the inserted row else -1 if the row was not inserted.它返回插入行的 id,如果没有插入,则返回 -1。

  • In theory the id can be a long, as such it is recommended that long instead of int is used.理论上,id 可以是 long,因此建议使用 long 而不是 int。

Assuming that the id column is an alias of the rowid .假设 id 列是rowid的别名。

  • according to your CREATE SQL it is.根据您的 CREATE SQL 它是。

Your code could be the simpler:-您的代码可能更简单:-

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;
}

However, it is inefficient to close the database -但是,关闭数据库效率低下-

I would suggest the even simpler:-我会建议更简单的: -

public long add(EmployeeData data) {
    SQLiteDatabase db=getWritableDatabase();
    ContentValues cv=new ContentValues();
    cv.put(NAME, data.getName());
    return db.insert(TABLE_NAME, null, cv);
}

Example例子

Here's the code of an example based upon your code (using the logcat as well as the toast):-这是基于您的代码的示例代码(使用 logcat 和 toast):-

The DatabaseHelper DBHelper数据库助手 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);
    }
}

The invoking Activity调用活动

  • the onClickListener has been replaced with direct invocation of 2 inserts onClickListener 已替换为直接调用 2 个插入
  • in addition to using the toast the log has been used to record the id's inserted除了使用 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);
    }
}

The EmployeeData class (guessed):- EmployeeData class(猜测):-

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;
    }
}

Results结果

When the above is run after ensuring that no database already exists (the App is uninstalled from the test device (Emulator) via settings)在确保不存在数据库后运行上述操作时(通过设置从测试设备(模拟器)卸载应用程序)

  • Uninstalling the App deletes the database and should be undertaken if any changes to the schema have been made, otherwise those changes will not be applied (not entirely true as you could introduce code to make such changes).卸载应用程序会删除数据库,如果对架构进行了任何更改,则应进行卸载,否则将不会应用这些更改(不完全正确,因为您可以引入代码来进行此类更改)。

The LogCat shows:- LogCat 显示:-

D/ADDEMP: ID of Employee was 1
D/ADDEMP: ID of Employee was 2

If run a second time the LogCat shows:-如果再次运行 LogCat 显示:-

D/ADDEMP: ID of Employee was 3
D/ADDEMP: ID of Employee was 4


Additional as per comments根据评论补充

As per the comments you issue was that you were inadvertently using a temporary database/in_memory database and rows were being added to a new database each time and hence the id was always 1.根据您发布的评论,您无意中使用了临时数据库/in_memory 数据库,并且每次都将行添加到新数据库中,因此 id 始终为 1。

The following are some suggested changes (see comments in the code) based upon your GITHUB code.以下是基于您的 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();
    }
}

MainActivity主要活动

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)
        });
    }
}

Testing测试

The App was run and 3 Employees were added (Fred, Mary and Susan).该应用程序已运行并添加了 3 名员工(Fred、Mary 和 Susan)。 The logcat shows:- 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM