SQLite table 用户函数

Sqlite table user function

我正在尝试创建一个需要用户登录的应用程序。我创建了两个 tables user_reg 和 user_info。第一个是空的,包含学生 ID、电子邮件、密码列。第二个 table 有三列用户名、学生 ID、课程,每列都有我已经插入的 10 个值。我正在尝试编写一个函数,以便仅当输入的学生 ID 与第二个 table 中的任何一个学生 ID 匹配时,才将值插入第一个 table。我在游标中使用原始查询从第二个 table 中选择学生 ID。第二个光标用于让用户插入学生 ID。然后if循环看结果是否匹配。我认为这是错误的。正确的做法是什么?

这是我 table 创建和插入值的代码。我知道这是错误的,我可能应该使用循环来查询用户信息 table。任何有关如何正确执行此操作的帮助将不胜感激。

public static final String SQL_TABLE_USERS = " CREATE TABLE " + TABLE_USERS
            + " ( "
            + KEY_ID + " INTEGER PRIMARY KEY, "
            + KEY_EMAIL + " TEXT, "
            + KEY_SID + " INTEGER, "
            + KEY_PASSWORD + " TEXT"
            + " ) ";

    //SQL for creating user info table
    public static final String SQL_TABLE_USERINFO = " CREATE TABLE " + TABLE_USERINFO
            + " ( "
            + KEY_ID + "INTEGER PRIMARY KEY, "
            + KEY_SID + " INTEGER, "
            + KEY_NAME + "TEXT, "
            + KEY_COURSE + " TEXT "
            + " ) ";


    public SqliteHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        //Create Table when oncreate gets called
        sqLiteDatabase.execSQL(SQL_TABLE_USERS);
        sqLiteDatabase.execSQL(SQL_TABLE_USERINFO);
        sqLiteDatabase.execSQL("INSERT INTO TABLE_USERINFO VALUES('01','45207160010','Mary James','TYBSCIT')");
        sqLiteDatabase.execSQL("INSERT INTO TABLE_USERINFO VALUES('02','45207160020','Amelia John','FYBCOM')"); ```


And this is my function for matching student id:-
public boolean isSIDmatches(String sid) {
        SQLiteDatabase db = this.getReadableDatabase();
        String sidmatch = "SELECT KEY_SID FROM TABLE_USERINFO";
        Cursor cursor = db.rawQuery(sidmatch, new String[]{""});
        Cursor cursor1 = db.query(TABLE_USERS,// Selecting Table
                new String[]{KEY_ID, KEY_EMAIL, KEY_SID, KEY_PASSWORD},//Selecting columns want to query
                KEY_SID + "=?",
                new String[]{sid},//Where clause
                null, null, null);
        if (cursor != null && cursor.moveToFirst()&& cursor.getCount()>0 && cursor==cursor1) {
            return true;
        }
        else {
            return false;
        }
    }




一种方法是合并一个外键(不是说你需要打开外键处理,因为它默认是关闭的)。

基本上,外键引入了一个约束,即只有当应用于 child 的值存在于 parent 中时,才能添加 child。

Child 和 parent 是 table/column(或列)组合。

正如你所说 user_info table 中的值必须存在于 user_reg table 中 user_reg 将是 parent 和 user_info 将是列名称中的 child 是 studentid.

因此,您可以使用 :-

定义外键
CREATE TABLE IF NOT EXISTS user_info (studentid INTEGER PRIMARY KEY REFERENCES user_reg(studentid), email TEXT, password TEXT);
  • 注意,假设一个学生只有一个 studentid

但是,由于外键必须指向 parent 中的唯一行,这将限制 user_reg table 每个学生只有 1 个条目,即可能不受欢迎。

这突出了一个潜在的问题,您基本上是以错误的方式看待 schema/structure,因为您可能专注于从课程的角度来看待结构。

建议用户的单数方面,他们的姓名、ID、电子邮件等属于 user_info table,每个学生一行,并且 user_reg table(在课程中注册)被认为是学生注册的一个或多个课程,因此单个学生可以注册多次(在单独的课程中),因此这应该实际上是 child 而 user_info 应该是 parent.

因此,也许您应该使用 :-

CREATE TABLE IF NOT EXISTS user_info (studentid INTEGER PRIMARY KEY, email TEXT, password TEXT, username TEXT);
CREATE TABLE IF NOT EXISTS user_reg (studentid INTEGER REFERENCES user_info, course TEXT);

然后您首先将学生添加到 user_info table,然后将学生添加到 course/courses,例如:-

INSERT INTO user_info VALUES
    (1,'Fred@email.mail','fredismypassword','UserFred'),
    (2,'Mary@email.mail','maryismypassword','UserMary'),
    (3,'Sue@email.mail','sureismypassword','UserSue')
;

INSERT INTO user_reg VALUES
    (1,'English'),(1,'Woodwork'),(1,'Chemistry'),
    (2,'Geography'),
    (3,'Chemistry')
;
  • 所以 Fred 注册了 3 门课程,Mary 和 Sue 各注册了一门

例如,查询可以是:-

SELECT * FROM user_reg JOIN user_info ON user_reg.studentid = user_info.studentid ORDER BY course;

这将导致:-

正在尝试添加 non-existent 学生,例如使用 :-

INSERT INTO user_reg VALUES (10,'English') -- Oooops no such student ID

会导致

INSERT INTO user_reg VALUES (10,'English') -- Oooops no such student ID
> FOREIGN KEY constraint failed

示例使用 Android

把所有的放在一起(在Android上复制上面的代码)然后代码可以是

StudentDBHelper.java(数据库助手)

public class StudentDBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "studentdb";
    public static final int DBVERSION = 1;
    public static final String TBl_USERINFO = "user_info";
    public static final String TBL_USERREG = "user_reg";

    public static final String COL_USERINFO_STUDENTID = "student_id";
    public static final String COL_USERINFO_USERNAME = "username";
    public static final String COL_USERINFO_EMAIL = "email";
    public static final String COL_USERINFO_PASSWORD = "password";

    public static final String COL_USERREG_STUDENT_ID = "student_id";
    public static final String COL_USERREG_COURSE = "course";

    private final String crtUserInfo = "CREATE TABLE IF NOT EXISTS " + TBl_USERINFO + "(" +
            COL_USERINFO_STUDENTID + " INTEGER PRIMARY KEY, " +
            COL_USERINFO_USERNAME + " TEXT, " +
            COL_USERINFO_EMAIL + " TEXT," +
            COL_USERINFO_PASSWORD + " TEXT" +
            ")";

    private final String drpUerInfo = "DROP TABLE IF EXISTS " + TBl_USERINFO;

    private final String crtUserReg = "CREATE TABLE IF NOT EXISTS " + TBL_USERREG + "(" +
            COL_USERREG_STUDENT_ID + " INTEGER REFERENCES " + TBl_USERINFO + "(" + COL_USERINFO_STUDENTID + ")," +
            COL_USERREG_COURSE + " TEXT " +
            ")";

    private final String drpUserReg = " DROP TABLE If EXISTS " + TBL_USERREG;

    SQLiteDatabase mDB;



    public StudentDBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase(); //<<<<<<<<<< will force create when constructing if DB doesn't exist
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(crtUserInfo);
        db.execSQL(crtUserReg);
    }

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        db.setForeignKeyConstraintsEnabled(true); //<<<<<<<<<< TURN ON FOREIGN KEY HANDLING
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(drpUserReg); //<<<<<<<<<< must be done before UserInfo
        db.execSQL(drpUerInfo);
    }

    public long addUserInfo(String userName, String email, String password) {
        ContentValues cv = new ContentValues();
        cv.put(COL_USERINFO_USERNAME,userName);
        cv.put(COL_USERINFO_EMAIL,email);
        cv.put(COL_USERINFO_PASSWORD,password);
        return mDB.insert(TBl_USERINFO,null,cv);
    }

    public long addUserReg(long studentId, String course) {
        ContentValues cv = new ContentValues();
        cv.put(COL_USERREG_STUDENT_ID,studentId);
        cv.put(COL_USERREG_COURSE,course);
        return mDB.insert(TBL_USERREG,null,cv);
    }

    public void logStudentsInCourses() {
        String tbl = TBL_USERREG +
                " JOIN " + TBl_USERINFO + " ON " +
                TBl_USERINFO + "." + COL_USERINFO_STUDENTID +
                " = " +
                TBL_USERREG + "." + COL_USERREG_STUDENT_ID;
        Cursor csr = mDB.query(tbl,null,null,null,null,null,COL_USERREG_COURSE);
        while (csr.moveToNext()) {
            Log.d(
                    "DBINFO",
                    "Row " + String.valueOf(csr.getPosition() + 1) +
                            "\n\t Student UserName = " + csr.getString(csr.getColumnIndex(COL_USERINFO_USERNAME)) +
                            "\n\tStudent Email = " + csr.getString(csr.getColumnIndex(COL_USERINFO_EMAIL)) +
                            "\n\tStudent password = " + csr.getString(csr.getColumnIndex(COL_USERINFO_PASSWORD)) +
                            "\n\tEnrolled in Course " + csr.getString(csr.getColumnIndex(COL_USERREG_COURSE))
            );
        }
    }
}

##MainActivity.java(调用 activity)

public class MainActivity extends AppCompatActivity {

    StudentDBHelper mDBHlpr;
    Context mContext;

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

        mDBHlpr = new StudentDBHelper(this);

        mDBHlpr.addUserInfo("Fred","fred@email.com","fredpassword"); //<<<<<<<<<< will return 1 as this will be the generated value (first run only)
        mDBHlpr.addUserInfo("Mary","mary@email.com","marypassword");
        mDBHlpr.addUserInfo("Sue","sue@email.com","suepassword");

        mDBHlpr.addUserReg(1,"English"); 
        mDBHlpr.addUserReg(1,"Wooodwork");
        mDBHlpr.addUserReg(1,"Chemistry");
        mDBHlpr.addUserReg(2,"Geography");
        mDBHlpr.addUserReg(3,"Chemistry");
        mDBHlpr.addUserReg(10,"Chemistry"); //<<<<<<<<< Ooops won't insert return will be -1
        mDBHlpr.logStudentsInCourses();
    }
}
  • 注意以上仅设计为运行一次

结果

以上,当运行第一次时会输出如下内容到log中:-

2019-02-03 13:57:09.829 15640-15640/so.cdfa E/SQLiteDatabase: Error inserting student_id=10 course=Chemistry
    android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
        at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1564)
        at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1433)
        at so.cdfa.StudentDBHelper.addUserReg(StudentDBHelper.java:80)
        at so.cdfa.MainActivity.onCreate(MainActivity.java:37)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 1
         Student UserName = Fred
        Student Email = fred@email.com
        Student password = fredpassword
        Enrolled in Course Chemistry
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 2
         Student UserName = Sue
        Student Email = sue@email.com
        Student password = suepassword
        Enrolled in Course Chemistry
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 3
         Student UserName = Fred
        Student Email = fred@email.com
        Student password = fredpassword
        Enrolled in Course English
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 4
         Student UserName = Mary
        Student Email = mary@email.com
        Student password = marypassword
        Enrolled in Course Geography
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 5
         Student UserName = Fred
        Student Email = fred@email.com
        Student password = fredpassword
        Enrolled in Course Wooodwork
  • 注意异常不是运行 time/fatal异常,并没有停止处理,它只是报告由于外键冲突导致插入失败。