为什么Android仍然在SQLite中的NOT NULL列中输入空/空字符串?

时间:2013-10-29 15:06:22

标签: android sqlite

我在SQLite中创建了一个表'PLAN'并且将'NAME'列设置为TEXT NOT NULL,我尝试使用EditText中的值插入该表。当EditText没有值并且我单击提交时,该值将作为空字符串插入到列中。发生什么事?我已经创建了如下的简单数据验证,但仍然插入了空值。我使用ContentValues来执行查询。

DatabaseHelper

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DatabaseHelper extends SQLiteOpenHelper {
// Logcat tag
public static final String LOG = "SODatabaseHelper";

// Database Version
public static final int DATABASE_VERSION = 1;

// Database Name
public static final String DATABASE_NAME = "Planner.db";

// Table Names - column names
public static final String TABLE_PLAN = "Plan";
public static final String TABLE_CATEGORY = "Category";
public static final String TABLE_GEAR = "Gear";
public static final String TABLE_GEARSET = "GearSet";
public static final String TABLE_GEARSETSHAVEGEAR = "GearSetsHaveGear";
public static final String TABLE_PLANHAVEGEAR = "PlanHaveGear";

// PLAN Table - column names
public static final String KEY_PLANID = "planID";
public static final String COLUMN_PLANCATID = "planCatID";
public static final String COLUMN_PLANNAME = "planName";
public static final String COLUMN_PLANLOCATION = "planLocation";
public static final String COLUMN_DATECREATED = "planCreated";
public static final String COLUMN_PLANSUMMARY = "planSummary";
public static final String COLUMN_DATESTART = "planStart";
public static final String COLUMN_DATEEND = "planEnd";

// CATEGORY - column names
public static final String KEY_CATID = "catID";
public static final String COLUMN_CATNAME = "catName";
public static final String COLUMN_CATDESC = "catDescription";

// GEAR Table - column names
public static final String KEY_GEARID = "gearID";
public static final String COLUMN_GEARNAME = "gearName";
public static final String COLUMN_GEARDESC = "gearDescription";

// GEARSET Table - column names
public static final String KEY_GEARSETID = "gearSetID";
public static final String COLUMN_GEARSETNAME = "gearSetName";
public static final String COLUMN_GEARSETDESC = "gearSetDescription";

// PLANHAVEGEARSET Table - column names
public static final String KEY_PHG_PLANID = "phgPlanID";
public static final String KEY_PHG_GEARSETID = "phgGearSetID";

// GEARSETHAVEGEAR Table - column names
public static final String KEY_GHG_GEARSETID = "ghgGearSetID";
public static final String KEY_GHG_GEARID = "ghgGearID";

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

// TABLE CREATIONS
private static final String CREATE_TABLE_PLAN = "CREATE TABLE "
        + TABLE_PLAN + "("
        + KEY_PLANID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + COLUMN_PLANCATID + " INTEGER NOT NULL, "
        + COLUMN_PLANNAME + " TEXT NOT NULL, "
        + COLUMN_PLANLOCATION + " TEXT NULL, "
        + COLUMN_DATECREATED + " STRING NOT NULL, "
        + COLUMN_PLANSUMMARY + " TEXT NULL, "
        + COLUMN_DATESTART + " STRING NULL, "
        + COLUMN_DATEEND + " STRING NULL" + ")";

private static final String CREATE_TABLE_CATEGORY = "CREATE TABLE "
        + TABLE_CATEGORY + "("
        + KEY_CATID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + COLUMN_CATNAME + " TEXT NOT NULL, "
        + COLUMN_CATDESC + " TEXT NULL" + ")";

private static final String CREATE_TABLE_GEAR = "CREATE TABLE "
        + TABLE_GEAR + "("
        + KEY_GEARID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + COLUMN_GEARNAME + " TEXT NOT NULL, "
        + COLUMN_GEARDESC + " TEXT NULL" + ")";

private static final String CREATE_TABLE_GEARSET = "CREATE TABLE "
        + TABLE_GEARSET + "("
        + KEY_GEARSETID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + COLUMN_GEARSETNAME + " TEXT NOT NULL, "
        + COLUMN_GEARSETDESC + "TEXT NULL" + ")";

private static final String CREATE_TABLE_GEARSETHAVEGEAR = "CREATE TABLE "
        + TABLE_GEARSETSHAVEGEAR + "("
        + KEY_GHG_GEARID + " INTEGER NOT NULL, "
        + KEY_GHG_GEARSETID + " INTEGER NOT NULL" + ")";

private static final String CREATE_TABLE_PLANHAVEGEARSET = "CREATE TABLE "
        + TABLE_PLANHAVEGEAR + "("
        + KEY_PHG_PLANID + " INTEGER NOT NULL, "
        + KEY_PHG_GEARSETID + " INTEGER NOT NULL" + ")";

@Override
public void onCreate(SQLiteDatabase db) {
    // creating required tables
    db.execSQL(CREATE_TABLE_PLAN);
    db.execSQL(CREATE_TABLE_CATEGORY);
    db.execSQL(CREATE_TABLE_GEAR);
    db.execSQL(CREATE_TABLE_GEARSET);
    db.execSQL(CREATE_TABLE_PLANHAVEGEARSET);
    db.execSQL(CREATE_TABLE_GEARSETHAVEGEAR);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    Log.w(DatabaseHelper.class.getName(),
            "UPDATING DATABASE FROM VERSION " + oldVersion + " TO VERSION " + newVersion
                    + " WHICH DESTROY ALL DATA.");

    // on upgrade drop older tables
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_PLAN);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_CATEGORY);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_GEAR);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_GEARSET);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_GEARSETSHAVEGEAR);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_PLANHAVEGEAR);

    // create new tables
    onCreate(db);
}
// TODO: Create each object data source class
}

规划数据源类

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;

import org.joda.time.DateTime;

import java.util.ArrayList;
import java.util.List;

public class PlanDataSource {
private SQLiteDatabase db;
private DatabaseHelper databaseHelper;
private String[] allColumns = {
        DatabaseHelper.KEY_PLANID,
        DatabaseHelper.COLUMN_PLANCATID,
        DatabaseHelper.COLUMN_PLANNAME,
        DatabaseHelper.COLUMN_PLANLOCATION,
        DatabaseHelper.COLUMN_DATECREATED,
        DatabaseHelper.COLUMN_PLANSUMMARY,
        DatabaseHelper.COLUMN_DATESTART,
        DatabaseHelper.COLUMN_DATEEND
};

/**
 * PlanDataSource constructor
 * @param context Context
 */
public PlanDataSource(Context context) {
    databaseHelper = new DatabaseHelper(context);
}

public void open() throws SQLException {
    db = databaseHelper.getWritableDatabase();
}

public void close() {
    databaseHelper.close();
}

/**
 * Method for inserting new plan to the database
 * @param newPlan plan class object, as Plan
 * @return true if the plan successfully inserted to database
 * @throws android.database.SQLException if there are invalid input
 */
public Boolean insertPlan(Plan newPlan) {
    ContentValues contentPlan = new ContentValues();

    contentPlan.put(DatabaseHelper.COLUMN_PLANCATID, newPlan.getCatId());
    contentPlan.put(DatabaseHelper.COLUMN_PLANNAME, newPlan.getName());
    contentPlan.put(DatabaseHelper.COLUMN_PLANLOCATION, newPlan.getDestination());
    contentPlan.put(DatabaseHelper.COLUMN_DATECREATED, newPlan.getCreated().toString());
    contentPlan.put(DatabaseHelper.COLUMN_PLANSUMMARY, newPlan.getSummary());

    if (newPlan.getStart() != null) {
        contentPlan.put(DatabaseHelper.COLUMN_DATESTART,
                newPlan.getStart().toString());
    }

    if (newPlan.getEnd() != null) {
        contentPlan.put(DatabaseHelper.COLUMN_DATEEND,
                newPlan.getEnd().toString());
    }

    try {
        db.insert(DatabaseHelper.TABLE_PLAN, null, contentPlan);
        return true;

    } catch (SQLiteException ex) {
        throw new SQLiteException("Error performing insertPlan()");
    } finally {
        db.close();
    }
}

/**
 * Method for deleting one plan based on its id
 * @param planId primary key of the plan
 * @return true if plan is successfully deleted
 * @throws android.database.SQLException if there is an error
 */
public Boolean deletePlan(int planId) {
    try {
        /** try delete from TABLE_PLAN */
        db.delete(
                DatabaseHelper.TABLE_PLAN,
                DatabaseHelper.KEY_PLANID + "=" + planId,
                null);

        /** returning true value is the action is success */
        return true;
    } catch (SQLException ex) {
        /** throw the exception */
        throw new SQLException("Error performing deletePlan()");
    } finally {
        /** close the database connection */
        db.close();
    }
}

/**
 * Method to get all plan from the database
 * @return List of all Plan from the database
 */
public List<Plan> getAllPlans() {
    List<Plan> planList = new ArrayList<Plan>();

    Cursor cursor = db.query(DatabaseHelper.TABLE_PLAN,
            allColumns, null, null, null, null, null);

    cursor.moveToFirst();
    while (!cursor.isAfterLast()) {
        Plan plan = cursorToPlan(cursor);
        planList.add(plan);
        cursor.moveToNext();
    }

    /** closing the database connection */
    cursor.close();

    /** return the list */
    return planList;
}

public Plan getPlan(int planId) {
    Plan plan = null;
    Cursor cursor = db.query(
            DatabaseHelper.TABLE_PLAN,
            allColumns,
            DatabaseHelper.KEY_PLANID + "=?",
            new String[]{String.valueOf(planId)},
            null, null, null, "1");

    cursor.moveToFirst();
    if (!cursor.isAfterLast()) {
        plan = cursorToPlan(cursor);
    }

    /** closing the database connection */
    db.close();
    cursor.close();

    /** return the plan */
    return plan;
}

/**
 * Method to convert from cursor object to Plan object
 * @param cursor the database query adapter
 * @return Plan class object based information from the cursor
 */
private Plan cursorToPlan(Cursor cursor) {
    return new Plan(
            cursor.getInt(0),
            cursor.getInt(1),
            cursor.getString(2),
            cursor.getString(3),
            new DateTime(cursor.getString(4)),
            cursor.getString(5),
            new DateTime(cursor.getString(6)),
            new DateTime(cursor.getString(7))
    );
}
}

这是从视图中检索值

case R.id.action_planeditor_saveplan:
            planDataSource = new PlanDataSource(PlanEditorActivity.this);
            planDataSource.open();

            try {
                Plan newPlan = new Plan(
                    Integer.valueOf(
                            planCategorySpinner.getSelectedItem().toString()),
                    planNameEditText.getText().toString(),
                    planLocationEditText.getText().toString(),
                    DateTime.now(),
                    planSummaryEditText.getText().toString(),
                    startDate,
                    endDate);

                planDataSource.insertPlan(newPlan);
                Toast.makeText(PlanEditorActivity.this, "Success", Toast.LENGTH_SHORT).show();
                setResult(1, null);
                finish();
                return true;

            } catch (SQLiteException ex) {
                Toast.makeText(getBaseContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
                return false;
            } finally {
                planDataSource.close();
            }


public void setName(String name) {
    if (name.trim().equals("") || name.isEmpty())
        this.name = null;
    this.name = name;
}

请帮忙。

2 个答案:

答案 0 :(得分:1)

您始终仍在接受参数String name

当给出空名称时,您在this.name上设置NULL,但之后继续this.name = name;不过。

你应该尝试在if / else结构中添加适当的括号,以使自己和他人更清楚;

你想要的是这样的

public void setName(String name) {
    if(name.trim().equals("") || name.isEmpty()){
       this.name = null;
     }else{
       this.name = name;
    }
}

答案 1 :(得分:0)

您的列NAME被定义为NOT NULL。因此,当您的EditText没有值时,您别无选择,只能将其存储为空字符串。

如果您打算将空字符串存储为NULL,则需要从列定义中删除NOT NULL。然后,在设置ContentValues时,请检查要保存的字符串。如果它为null或为空,请改为使用:

contentPlan.putNull(DatabaseHelper.COLUMN_PLANNAME);

另请注意,就SQLite而言,空字符串不是空值。空字符串仍然是一个字符串,并计为文本。使用NOT NULL只是意味着你不能按照上面的语句将它设置为NULL,或者在插入时不给它任何值。