创建表后如何在SQLite数据库中设置主键?

时间:2019-07-03 13:34:49

标签: android-sqlite primary-key

在创建表后如何在SQLite中设置主键?

我正在使用SQLite创建一个项目,并且忘记了提供用户ID的主键,现在该如何设置?

下面是我的ContactContract类

public final class ContactContract {

    private ContactContract(){}


    public static class ContactEntry
    {
        public static final String TABLE_NAME="contact_info";
        public static final String KEY_P = "KEY";
        public static final String CONTACT_ID = "contact_id";
        public static final String NAME="name";
        public static final String EMAIL="email";

    }
}

下面是我的ContactDbHelper类

public class ContactDbHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "contact_db";
    public static final int DATABASE_VERSION = 1;

    public static final String CREATE_TABLE="create table "+ContactContract.ContactEntry.TABLE_NAME+
            "(" + ContactContract.ContactEntry.KEY_P +"INTEGER PRIMARY KEY," +ContactContract.ContactEntry.CONTACT_ID+" number,"+ContactContract.ContactEntry.NAME+" text,"+
            ContactContract.ContactEntry.EMAIL+" text);";

1 个答案:

答案 0 :(得分:0)

使用:-

 public static final String CREATE_TABLE="create table "+ContactContract.ContactEntry.TABLE_NAME+
            "(" + ContactContract.ContactEntry.KEY_P +"INTEGER PRIMARY KEY," +ContactContract.ContactEntry.CONTACT_ID+" number,"+ContactContract.ContactEntry.NAME+" text,"+
            ContactContract.ContactEntry.EMAIL+" text);";

由于:-

,将无法按预期工作
  1. 列名和INTEGER PRIMARY KEY,

    后没有空格
    • 列名将是 KEYINTEGER 而不是 KEY ,并且很可能会导致问题。
    • 该列不是主键,因此,如果省略了列值(通常是这种情况),该值将为null。
  2. 您不能有一个名为KEY的列(就像在INTEGER之前添加空格的情况一样),因为它是一个关键字。也许使用public static final String KEY_P = "KEYP";来克服这个问题。

就这样使用:-

public static final String KEY_P = "KEYP";
  • 或除=“ KEY”以外的其他非关键字

以及:-

 public static final String CREATE_TABLE="create table "+ContactContract.ContactEntry.TABLE_NAME+
            "(" + ContactContract.ContactEntry.KEY_P +" INTEGER PRIMARY KEY," +ContactContract.ContactEntry.CONTACT_ID+" number,"+ContactContract.ContactEntry.NAME+" text,"+
            ContactContract.ContactEntry.EMAIL+" text);";

已更正1和2。然后,如果您可以轻松地重新生成数据,则可以重新安装该应用以应用架构更改。


但是,因为您声明数据库已填充,并且如果无法轻松地重新生成数据,则可以完成该操作。

假设数据库当前有数据(例如,用于测试以下数据的部分数据):-

以下方法可用于更改架构以添加PRIMARY KEY列:-

private void addPrimaryKey() {
    String TAG = "ADDPRMRYKEY";
    Log.d(TAG,"Initiated adding the primary key.");
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor csr = db.query(
            "sqlite_master",
            null,
            "name =? AND instr(sql,'PRIMARY KEY') > 0",
            new String[]{ContactContract.ContactEntry.TABLE_NAME},
            null,null,null
    );
    if (csr.getCount() < 1) {
        Log.d(TAG," PRIMARY KEY clause not found for table " + ContactContract.ContactEntry.TABLE_NAME);
        if (CREATE_TABLE.indexOf("PRIMARY KEY") > 0) {
            Log.d(TAG,"PRIMARY KEY clause located in CREATE TABLE SQL so !!!!ALTERING!!!! table " + ContactContract.ContactEntry.TABLE_NAME);
            db.execSQL("ALTER TABLE " + ContactContract.ContactEntry.TABLE_NAME + " RENAME TO OLD" + ContactContract.ContactEntry.TABLE_NAME);
            Log.d(TAG,"RENAMED TABLE " + ContactContract.ContactEntry.TABLE_NAME + " to OLD" + ContactContract.ContactEntry.TABLE_NAME);
            db.execSQL(CREATE_TABLE);
            Log.d(TAG,"CREATED new version of table " + ContactContract.ContactEntry.TABLE_NAME + " !!!!INSERTING DATA EXTRACTED!!!! from old version");
            db.execSQL("INSERT INTO " + ContactContract.ContactEntry.TABLE_NAME + " SELECT null,* FROM OLD" + ContactContract.ContactEntry.TABLE_NAME);
        } else {
            Log.d(TAG,"PRIMARY KEY clause not found in the CREATE TABLE SQL so doing nothing.");
        }
    } else {
        Log.d(TAG,"PRIMARY KEY clause found for table " + ContactContract.ContactEntry.TABLE_NAME + " - Nothing to do!!!!");
    }
    csr.close();
}
  • 请注意,显然Log.d语句将被删除,它们已用于测试/解释。

上面的作品

  1. 查询sqlite_master表以提取用于创建表的SQL(如果它包含PRIMARY KEY子句)。

  2. 如果这样做,则该方法将不执行任何操作,因为已经定义了PRIMARY KEY。

  3. 检查潜在的新建/替换表create SQL,以查看其是否包含PRIMARY KEY子句。

  4. 如果不这样做,那么什么也不会做。

  5. 当前表已重命名。

  6. 根据创建表SQL创建具有原始名称的新表。

  7. 数据将从原始表复制到新表。

    • 请注意,您可能希望考虑删除重命名的原始表。尚未删除它,因为以防万一,更安全。

addPrimaryKey方法没有增加版本号,而是按照:-

并入了数据库帮助器的构造函数中。
public ContactDbHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    addPrimaryKey(); //<<<<<<<<<< ADDED to Convert
}
  • addPrimaryKey 方法每次都会运行,但仅在以下情况下尝试转换数据:
    • 该表没有PRIMARY KEY子句,
    • CREATE SQL包含PRIMARY KEY子句
    • 假设“ PRIMARY KEY”列是第一个定义的列,如果不是,则应相应地更改行db.execSQL("INSERT INTO " + ContactContract.ContactEntry.TABLE_NAME + " SELECT null,* FROM OLD" + ContactContract.ContactEntry.TABLE_NAME);

测试

设置

该应用使用以下命令运行(KEY_P被注释为当前状态):-

public static final String CREATE_TABLE = "create table " + ContactContract.ContactEntry.TABLE_NAME +
        "(" +
        //ContactContract.ContactEntry.KEY_P + " INTEGER PRIMARY KEY," + //<<<<<<<<<< comment out this line for first run to generate data
        ContactContract.ContactEntry.CONTACT_ID + " number," +
        ContactContract.ContactEntry.NAME + " text," +
        ContactContract.ContactEntry.EMAIL + " text" +
        ");";

始终使用的调用活动是:-

public class MainActivity extends AppCompatActivity {

    ContactDbHelper mDBHlpr;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDBHlpr = new ContactDbHelper(this);
        addSomeData();
        Cursor csr = mDBHlpr.getWritableDatabase().query(ContactContract.ContactEntry.TABLE_NAME,null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
        csr.close();

        /*
        DataBaseHelper mDBHlpr = DataBaseHelper.getInstance(this);
        Cursor csr = mDBHlpr.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
        */
    }

    /**
     * Add some data
     */
    private void addSomeData() {
        if (DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(), ContactContract.ContactEntry.TABLE_NAME) > 0 ) return;
        Random rnd = new Random();
        for (int i=0;i < 100; i++) {
            mDBHlpr.insertContact(rnd.nextInt(),"Aname" + String.valueOf(i),"Aname" + String.valueOf(i) + "@email.com");
        }
    }
}

此:-

  1. 实例化数据库助手
  2. 仅在不存在任何数据(带有随机生成的contactID的100行)时才添加一些数据,但这只是为了证明它是有效的。
  3. 提取所有行,按照
  4. 转储光标

:-

2019-07-04 15:52:03.813 7758-7758/aso.so56873021recopydb D/ADDPRMRYKEY: Initiated adding the primary key.
2019-07-04 15:52:03.830 7758-7758/aso.so56873021recopydb D/ADDPRMRYKEY:  PRIMARY KEY clause not found for table contact_info
2019-07-04 15:52:03.830 7758-7758/aso.so56873021recopydb D/ADDPRMRYKEY: PRIMARY KEY clause not found in the CREATE TABLE SQL so doing nothing.
2019-07-04 15:52:03.888 7758-7758/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@791f7af
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out:    contact_id=-1179778271
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out:    name=Aname0
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out:    email=Aname0@email.com
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: }
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out:    contact_id=1334348157
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out:    name=Aname1
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out:    email=Aname1@email.com
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: }
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: 2 {
2019-07-04 15:52:03.891 7758-7758/aso.so56873021recopydb I/System.out:    contact_id=1123604651
2019-07-04 15:52:03.891 7758-7758/aso.so56873021recopydb I/System.out:    name=Aname2
2019-07-04 15:52:03.891 7758-7758/aso.so56873021recopydb I/System.out:    email=Aname2@email.com

转化

从上面的输出可以看出,已经调用了addPrimaryKey方法,但是由于D/ADDPRMRYKEY: PRIMARY KEY clause not found in the CREATE TABLE SQL so doing nothing.

而没有执行任何操作

因此,只需更改CREATE SQL以将新列包括为:-

public static final String CREATE_TABLE = "create table " + ContactContract.ContactEntry.TABLE_NAME +
        "(" +
        ContactContract.ContactEntry.KEY_P + " INTEGER PRIMARY KEY," + //<<<<<<<<<< comment out this line for first run to generate data
        ContactContract.ContactEntry.CONTACT_ID + " number," +
        ContactContract.ContactEntry.NAME + " text," +
        ContactContract.ContactEntry.EMAIL + " text" +
        ");";
  • 即KEY_P列不再被注释掉,因此可以使用新的/所需的SQL。

结果如下:-

2019-07-04 15:56:47.170 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: Initiated adding the primary key.
2019-07-04 15:56:47.175 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY:  PRIMARY KEY clause not found for table contact_info
2019-07-04 15:56:47.176 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: PRIMARY KEY clause located in CREATE TABLE SQL so !!!!ALTERING!!!! table contact_info
2019-07-04 15:56:47.176 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: RENAMED TABLE contact_info to OLDcontact_info
2019-07-04 15:56:47.177 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: CREATED new version of table contact_info !!!!INSERTING DATA EXTRACTED!!!! from old version
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@791f7af
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out:    KEYP=1
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out:    contact_id=-1179778271
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    name=Aname0
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    email=Aname0@email.com
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: }
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    KEYP=2
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    contact_id=1334348157
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    name=Aname1
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    email=Aname1@email.com
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: }
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: 2 {
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    KEYP=3
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out:    contact_id=1123604651
2019-07-04 15:56:47.181 7979-7979/aso.so56873021recopydb I/System.out:    name=Aname2
2019-07-04 15:56:47.181 7979-7979/aso.so56873021recopydb I/System.out:    email=Aname2@email.com

即数据已保留,但引入了新列并分配了值。

相关问题