我正在尝试创建至少3个表来存储用户名,电话号码和电子邮件,但是当用户单击“保存”时,我得到了这个奇怪的错误,它无法存储数据,但仍然会通过所有方法...我能够使用一个数据表存储数据,但是当我尝试使用两个数据表时,我只会遇到很多错误……有人有任何解释吗?
数据库管理器活动
private static final String DATABASE_NAME = "contact.db";
private static final int DATA_VERSION = 1;
//table names
private static final String TABLE_NAME = "name";
private static final String TABLE_PHONE = "phone";
private static final String TABLE_EMAIL = "email";
//ID
private static final String KEY_ID = "id";
//col
private static final String USER_NAME = "username";
private static final String PHONE_NUMBER = "phonenumber";
private static final String USER_EMAIL = "email";
//create tables
private static final String create_username_table = " CREATE TABLE "+ TABLE_NAME + " ( "+ KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "+ USER_NAME + " TEXT )";
private static final String create_phoneNumber_table = " CREATE TABLE "+ TABLE_PHONE + " ( "+ KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "+ PHONE_NUMBER + " TEXT )";
private static final String create_email_table = " CREATE TABLE "+ TABLE_EMAIL + " ( "+ KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "+ USER_EMAIL + " TEXT ) ";
public DataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATA_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sq) {
sq.execSQL(create_username_table);
sq.execSQL(create_phoneNumber_table);
sq.execSQL(create_email_table);
Log.d("OPERATION: ", "DATA TABLE(S) CREATED");
}
public void addData(String name, String number, String email){
SQLiteDatabase sq = this.getWritableDatabase();
//add to name table
ContentValues name_values = new ContentValues();
name_values.put(USER_NAME,name);
sq.insert(TABLE_NAME, null, name_values);
//add to phone table
ContentValues phone_values = new ContentValues();
phone_values.put(PHONE_NUMBER, number);
sq.insert(TABLE_PHONE, null, phone_values);
//add to email table
ContentValues email_value = new ContentValues();
email_value.put(USER_EMAIL, email);
sq.insert(TABLE_EMAIL, null, email_value);
Log.d("OPERATION: " ,"SUCCESS");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS '" + TABLE_NAME + "'");
db.execSQL("DROP TABLE IF EXISTS '" + TABLE_PHONE + "'");
db.execSQL("DROP TABLE IF EXISTS '" + TABLE_EMAIL + "'");
onCreate(db);
}
}
维护性
public class MainActivity extends AppCompatActivity {
EditText Name, email, num;
String StrName, StrNum, StrEmail;
Button savebtn;
Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Initialize();
setSavebtn();
}
public void Initialize(){
Name = (EditText) findViewById(R.id.EditTextName);
email = (EditText)findViewById(R.id.EditTextEmail);
num = (EditText)findViewById(R.id.EditTextNumber);
savebtn = (Button)findViewById(R.id.Save);
}
public void setSavebtn (){
savebtn.setOnClickListener(new View.OnClickListener() {
DataBaseHelper db = new DataBaseHelper(ctx);
@Override
public void onClick(View view) {
StrName = Name.getText().toString();
StrNum = num.getText().toString();
StrEmail = email.getText().toString();
if (Name.length() == 0 && num.length() == 0 && email.length() == 0){
toast("Please fill entries!");
}else{
db.addData(StrName,StrNum,StrEmail);
toast("Data Added!");
Name.setText("");
num.setText("");
email.setText("");
}
}
});
}
LogCat:
7-31 15:05:47.834 18015-18015/com.example.daniel.contacts E/SQLiteLog: (1) no such table: name
07-31 15:05:47.845 18015-18015/com.example.daniel.contacts E/SQLiteDatabase: Error inserting username=Dan
android.database.sqlite.SQLiteException: no such table: name (code 1): , while compiling: INSERT INTO name(username) VALUES (?)
#################################################################
Error Code : 1 (SQLITE_ERROR)
Caused By : SQL(query) error or missing database.
(no such table: name (code 1): , while compiling: INSERT INTO name(username) VALUES (?))
#################################################################
如果有人想要mainActivity的xml布局...在这里
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/Save"
android:text="Save Contact"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/EditTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Contact Name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.427"
tools:layout_editor_absoluteX="0dp" />
<EditText
android:id="@+id/EditTextNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Phone Number"
android:inputType="phone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="@id/EditTextName"
app:layout_constraintVertical_bias="0.349"
tools:layout_editor_absoluteX="0dp" />
<EditText
android:id="@+id/EditTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="@id/EditTextNumber"
app:layout_constraintVertical_bias="0.502"
tools:layout_editor_absoluteX="0dp" />
</android.support.constraint.ConstraintLayout>
答案 0 :(得分:-1)
该问题的线索位于日志中的消息中。
7-31 15:05:47.834 18015-18015/com.example.daniel.contacts E/SQLiteLog: (1) no such table: name
07-31 15:05:47.845 18015-18015/com.example.daniel.contacts E/SQLiteDatabase: Error inserting username=Dan
android.database.sqlite.SQLiteException: no such table: name (code 1): , while compiling: INSERT INTO name(username) VALUES (?)
#################################################################
Error Code : 1 (SQLITE_ERROR)
Caused By : SQL(query) error or missing database.
(no such table: name (code 1): , while compiling: INSERT INTO name(username) VALUES (?))
#################################################################
该表名称不存在。
最可能/常见的原因是您在创建数据库后已将表的创建添加到onCreate
方法中。在应用程序的生命周期内(因此在两次运行之间)仅创建一次数据库。 App的后续运行不会创建数据库,因为该数据库已经存在,因此onCreate
方法仅运行一次。除非删除数据库或否则调用onCreate
方法,否则所做的任何更改都不会应用。
解决方法可能是执行以下操作之一:-
如果正确编写了onUpgrade
方法,并将删除有问题的表,然后调用/调用onCreate
方法,则增加作为第4个参数传递的数据库版本号SQLiteOpenHelper的构造函数(又名DatabaseHelper,它是SQLiteOpenHelper的子类)。
执行上述操作之一后,然后重新运行该应用程序。
请注意,所有现有数据都将丢失,这在开发应用程序时通常不是问题。如果需要保留数据,则需要一种替代方法。
使用SQLite时,除非将表定义为不包含rowid的表(即具有WITHOUT ROWID
关键字),否则每一行都有一个通常为 rowid 的隐藏列。
如果使用:-
定义了列?? INTEGER PRIMARY KEY
或?? INTEGER PRIMARY KEY AUTOINCREMENT
或?? INTEGER, other_columns_if_any, PRIMARY KEY (??)
或?? INTEGER, other_columns_if_any, PRIMARY KEY (??)
然后是列?? (表示任何可接受的列名( note ??不可接受))成为 rowid 列的别名。
SQLite通常将比其他索引更有效地处理 rowid (包括别名),因此,出于这个原因, id 作为 rowid < / strong>通常是个好主意。
SQLite是一个关系数据库,因此设计来处理相关数据,而 id 是关联数据的一种好方法。
使用示例表中的联系人,联系人的电子邮件和联系人的电话。如果每个联系人只有1封电子邮件,每个联系人只有1部电话,那么拥有三个表就没有意义了。一个带有4列(key_id,名称,电子邮件,电话)的表将很适合并且还可以减少多个表的开销。
但是,如果一个联系人可能有多部电话和多封电子邮件,那么相关数据将成为您的方式,并且您可能会有3张桌子。一种用于联系人,一种用于电子邮件,一种用于电话,它们彼此相关。
因此,使用此模型/场景,您可能会:-
因此可以使用以下SQL创建以上内容:-
CREATE TABLE IF NOT EXISTS contacts (key_id INTEGER, name, PRIMARY KEY (key_id AUTOINCREMENT));
CREATE TABLE IF NOT EXISTS emails (email TEXT, contact_ref INTEGER);
CREATE TABLE IF NOT EXISTS phones (phone TEXT, contact_ref INTEGER);
可以使用:-
添加数据-- Add 4 contacts
INSERT INTO contacts (name) VALUES
('Fred'), -- id will be 1
('Mary'), -- id will likely be 2
('Tom'), -- id will likely be 3
('Jane') -- id will likely be 4
;
-- add a varying number of emails per contact
INSERT INTO emails VALUES
('Fred@Fredmail.com',1),('Fred@FredOtherEmail.com',1),('Fred@hotmail.com',1),
('Mary@m.com',2),
('Tom@tommail.net',3),('PipersonTom@nurserychrmes.org',3),
('Jane@tarzan.com',4),('ayrej@books.co.uk',4),('seymour_j@thecourtofhenryviii.gov.uk',4),('jf@keepfit.co',4)
;
-- no need to bother with phones as same principle applies
请考虑以下查询:-
SELECT * FROM contacts; -- List the rows in the contacts table
SELECT * FROM emails; -- List the rows in the emails table
结果将是:-
和:-
非常基本,但是请考虑以下查询:-
SELECT name,
group_concat(email,' - ') AS all_emails,
count(emails.rowid) AS email_count
FROM contacts JOIN emails ON emails.contact_ref = contacts.key_id GROUP BY key_id
ORDER BY email_count DESC
;
结果为:-
这显示了关联(联接表)数据的力量。
SELECT name,
表示获取/输出 name 列(最后的逗号表示将跟随更多输出列)group_concat(email,' - ')
表示输出每组行中加在一起的所有电子邮件列,每行之间放置空格,连字符和空格AS all_emails,
命名输出列,否则将命名为 group_concat(email,'-'),再次用逗号表示更多输出列count(email.rowid) AS emails
,再次基于分组,并且将返回相应组中电子邮件表的 rowid 列数。
FROM contacts
表示要使用联系人表JOIN emails ON emails.contact_ref = contacts.key_id
的意思是为当前联系人和电子邮件表中的每一行的每个组合创建一个潜在的组合输出行,其中电子邮件表的contact_ref列与联系人表的当前key_id列匹配。 / li>
GROUP BY key_id
表示所有具有相同key_id的行都将被分组为1,这是聚合函数的值(group_concat,count确定)ORDER BY email_count DESC
按照指定列的降序对输出进行排序(升序为ASC)。使用AUTOINCREMENT关键字通常是有害的,几乎不需要。在SQLite中,它的用法有所不同,其他使用它的关系数据库说它会自动生成一个ID,“ INTEGER PRIMARY KEY”对SQLite会这样做。
针对SQLite的
在SQLite Autoincrement上有关于AUTOINCREMENT和rowid的更多信息