SQLite未插入数据

时间:2018-07-31 20:16:25

标签: android database sqlite datatables

我正在尝试创建至少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>

1 个答案:

答案 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方法,否则所做的任何更改都不会应用。

解决方法可能是执行以下操作之一:-

  1. 删除应用程序的数据(删除数据库)。
  2. 卸载应用程序(删除数据库)。
  3. 如果正确编写了onUpgrade方法,并将删除有问题的表,然后调用/调用onCreate方法,则增加作为第4个参数传递的数据库版本号SQLiteOpenHelper的构造函数(又名DatabaseHelper,它是SQLiteOpenHelper的子类)。

  4. 执行上述操作之一后,然后重新运行该应用程序。

请注意,所有现有数据都将丢失,这在开发应用程序时通常不是问题。如果需要保留数据,则需要一种替代方法。

其他

ID列

使用SQLite时,除非将表定义为不包含rowid的表(即具有WITHOUT ROWID关键字),否则每一行都有一个通常为 rowid 的隐藏列。

如果使用:-

定义了列
  1. ?? INTEGER PRIMARY KEY
  2. ?? INTEGER PRIMARY KEY AUTOINCREMENT
  3. ?? INTEGER, other_columns_if_any, PRIMARY KEY (??)
  4. ?? INTEGER, other_columns_if_any, PRIMARY KEY (??)

然后是列?? (表示任何可接受的列名( note ??不可接受))成为 rowid 列的别名。

SQLite通常将比其他索引更有效地处理 rowid (包括别名),因此,出于这个原因, id 作为 rowid < / strong>通常是个好主意。

SQLite是一个关系数据库,因此设计来处理相关数据,而 id 是关联数据的一种好方法。

使用示例表中的联系人,联系人的电子邮件和联系人的电话。如果每个联系人只有1封电子邮件,每个联系人只有1部电话,那么拥有三个表就没有意义了。一个带有4列(key_id,名称,电子邮件,电话)的表将很适合并且还可以减少多个表的开销。

但是,如果一个联系人可能有多部电话和多封电子邮件,那么相关数据将成为您的方式,并且您可能会有3张桌子。一种用于联系人,一种用于电子邮件,一种用于电话,它们彼此相关。

因此,使用此模型/场景,您可能会:-

  1. 具有列 key_id 名称
  2. 联系人
  3. 具有列电子邮件 contact_ref
  4. 电子邮件
  5. 一个电话表,其中包含电话列 phone contact_ref

因此可以使用以下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
  • 弗雷德(Fred)的key_id列为 1 ,其中有3封相关电子邮件
  • 玛丽的key_id很可能是 2 ,他有1条相关电子邮件

请考虑以下查询:-

SELECT * FROM contacts; -- List the rows in the contacts table
SELECT * FROM emails; -- List the rows in the emails table

结果将是:-

enter image description here

和:-

enter image description here

非常基本,但是请考虑以下查询:-

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
;

结果为:-

enter image description here

这显示了关联(联接表)数据的力量。

  • SELECT name,表示获取/输出 name 列(最后的逗号表示将跟随更多输出列)
  • group_concat(email,' - ')表示输出每组行中加在一起的所有电子邮件列,每行之间放置空格,连字符和空格
  • AS all_emails,命名输出列,否则将命名为 group_concat(email,'-'),再次用逗号表示更多输出列
  • count(email.rowid) AS emails,再次基于分组,并且将返回相应组中电子邮件表的 rowid 列数。
    • 请注意,我们使用的是通常隐藏的 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的相反,请确保自动生成的唯一ID大于生成的最后一个ID,而如果没有SQLite,则当可能的ID最高(9223372036854775807)达到最大值时,请尝试使用较低的免费值(使用AUTOINCREMENT时,达到此值将发出SQLITE_FULL异常)。

SQLite Autoincrement上有关于AUTOINCREMENT和rowid的更多信息