在创建表后如何在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);";
答案 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);";
由于:-
,将无法按预期工作列名和INTEGER PRIMARY KEY,
您不能有一个名为KEY的列(就像在INTEGER之前添加空格的情况一样),因为它是一个关键字。也许使用public static final String KEY_P = "KEYP";
来克服这个问题。
就这样使用:-
public static final String KEY_P = "KEYP";
以及:-
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();
}
上面的作品
查询sqlite_master表以提取用于创建表的SQL(如果它包含PRIMARY KEY子句)。
如果这样做,则该方法将不执行任何操作,因为已经定义了PRIMARY KEY。
检查潜在的新建/替换表create SQL,以查看其是否包含PRIMARY KEY子句。
如果不这样做,那么什么也不会做。
当前表已重命名。
根据创建表SQL创建具有原始名称的新表。
数据将从原始表复制到新表。
addPrimaryKey方法没有增加版本号,而是按照:-
并入了数据库帮助器的构造函数中。public ContactDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
addPrimaryKey(); //<<<<<<<<<< ADDED to Convert
}
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");
}
}
}
此:-
:-
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" +
");";
结果如下:-
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
即数据已保留,但引入了新列并分配了值。