Android Studio - 使用多列创建数据库

时间:2015-04-09 18:31:19

标签: android sqlite android-studio

我想创建一个包含3列(兴趣点,经度和纬度的名称)的数据库。由于我对数据库完全陌生,我使用的是我在网上找到的一个例子,并尝试将其更改为我的案例。问题是它适用于1列,但如果我添加其他2列则会中断。这是我的代码:

  

TaskContract

import android.provider.BaseColumns;

public class TaskContract {
    public static final String DB_NAME = "com.example.TodoList.db.tasks";
    public static final int DB_VERSION = 1;
    public static final String POI_NAMES = "tasks";
    public static final String LONGITUDES = "longs";
    public static final String LATITUDES = "lats";


    public class Columns {
        public static final String POI = "task";
        public static final String _ID = BaseColumns._ID;
        public static final String LONGITUDE = "long";
        public static final String LATITUDE = "lat";
    }
}
  

TaskDBHelper

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


public class TaskDBHelper extends SQLiteOpenHelper {

    public TaskDBHelper(Context context) {
        super(context, TaskContract.DB_NAME, null, TaskContract.DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqlDB) {
        String sqlQuery =
                String.format("CREATE TABLE %s (" +
                        "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                        "%s TEXT" + " %s LONGITUDE" + "%s LATITUDE)",
                        TaskContract.POI_NAMES, TaskContract.Columns.POI,
                        TaskContract.LONGITUDES, TaskContract.Columns.LONGITUDE,
                        TaskContract.LATITUDES, TaskContract.Columns.LATITUDE);

        Log.d("TaskDBHelper","Query to form table: "+sqlQuery);
        sqlDB.execSQL(sqlQuery);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqlDB, int i, int i2) {
        sqlDB.execSQL("DROP TABLE IF EXISTS "+TaskContract.POI_NAMES+TaskContract.LONGITUDES+TaskContract.LATITUDES);
        onCreate(sqlDB);
    }
}

这是我将新值添加到列中的主要活动:

public class MainActivity extends ListActivity {
    private ListAdapter listAdapter;
    private TaskDBHelper helper;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        updateUI();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_add_task:
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Add a new point of interest");

                LinearLayout layout = new LinearLayout(this);
                layout.setOrientation(LinearLayout.VERTICAL);
                final TextView inputString1 = new TextView(this); inputString1.setText("Enter name:");
                final TextView inputString2 = new TextView(this); inputString2.setText("Enter longitude:");
                final TextView inputString3 = new TextView(this); inputString3.setText("Enter latitude:");
                final TextView inputString4 = new TextView(this); inputString4.setText("Enter a new point of interest:");

                final EditText inputField1 = new EditText(this);
                final EditText inputField2 = new EditText(this);
                final EditText inputField3 = new EditText(this);
                layout.addView(inputString4);
                layout.addView(inputString1);
                layout.addView(inputField1);
                layout.addView(inputString2);
                layout.addView(inputField2);
                layout.addView(inputString3);
                layout.addView(inputField3);
                builder.setView(layout);


                builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        String poi = inputField1.getText().toString();
                        String longit = inputField2.getText().toString();
                        String lat = inputField3.getText().toString();

                        helper = new TaskDBHelper(MainActivity.this);
                        SQLiteDatabase db = helper.getWritableDatabase();


                        ContentValues values = new ContentValues();
                        values.clear();
                        values.put(TaskContract.Columns.POI,poi);
                        db.insertWithOnConflict(TaskContract.POI_NAMES,null,values,SQLiteDatabase.CONFLICT_IGNORE);


                        values.put(TaskContract.Columns.LONGITUDE,longit);
                        db.insertWithOnConflict(TaskContract.LONGITUDES,null,values,SQLiteDatabase.CONFLICT_IGNORE);

                        values.put(TaskContract.Columns.LATITUDE,lat);
                        db.insertWithOnConflict(TaskContract.LATITUDES,null,values,SQLiteDatabase.CONFLICT_IGNORE);


                        updateUI();
                    }
                });

                builder.setNegativeButton("Cancel",null);

                builder.create().show();
                return true;

            default:
                return false;
        }
    }

    private void updateUI() {
        helper = new TaskDBHelper(MainActivity.this);
        SQLiteDatabase sqlDB = helper.getReadableDatabase();
        Cursor cursor = sqlDB.query(TaskContract.POI_NAMES,
                new String[]{TaskContract.Columns._ID, TaskContract.Columns.POI},
                null, null, null, null, null);

        listAdapter = new SimpleCursorAdapter(
                this,
                R.layout.task_view,
                cursor,
                new String[]{TaskContract.Columns.POI},
                new int[]{R.id.taskTextView},
                0
        );

        this.setListAdapter(listAdapter);
    }

    public void onDoneButtonClick(View view) {
        View v = (View) view.getParent();
        TextView taskTextView = (TextView) v.findViewById(R.id.taskTextView);
        String poi = taskTextView.getText().toString();

        String sql = String.format("DELETE FROM %s WHERE %s = '%s'",
                        TaskContract.POI_NAMES,
                        TaskContract.Columns.POI,
                        poi);


        helper = new TaskDBHelper(MainActivity.this);
        SQLiteDatabase sqlDB = helper.getWritableDatabase();
        sqlDB.execSQL(sql);
        updateUI();
    }
}

我认为问题是当我在TaskContract中声明 LONGITUDES LATITUDES 时,就像我改变它们一样:

  

public static final String POI_NAMES =" tasks&#34 ;;

     

public static final String LONGITUDES =" tasks&#34 ;;

     

public static final String LATITUDES =" tasks&#34 ;;

它有效,但它将所有内容放在同一列中。

有人可以解释分配价值的确切含义"任务"我的字符串?

1 个答案:

答案 0 :(得分:0)

您的代码中存在一些错误 - 为了将来参考,您可以检查每种方法的作用here

String.format("CREATE TABLE %s (" +
                        "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                        "%s TEXT" + " %s LONGITUDE" + "%s LATITUDE)",
                        TaskContract.POI_NAMES, TaskContract.Columns.POI,
                        TaskContract.LONGITUDES, TaskContract.Columns.LONGITUDE,
                        TaskContract.LATITUDES, TaskContract.Columns.LATITUDE);

这里“TEXT”指的是SQLite数据类型TEXT。 SQLite没有数据类型LONGITUDE / LATITUDE。所有数据类型的列表均可用here。在你的情况下你可以使用REAL作为浮点数或TEXT如果你想将坐标存储为字符串(在你插入字符串的那一刻,所以我将举例说明它,但请记住,REAL通常是更好的方法)。此外,您只有4个占位符,但提供6个参数。尝试这样的事情:

String.format("CREATE TABLE %s (" +
                            "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                            "%s TEXT" + " %s TEXT" + "%s TEXT)",
                            TaskContract.POI_NAMES, TaskContract.Columns.POI,
                            TaskContract.Columns.LONGITUDE, TaskContract.Columns.LONGITUDE);

这也需要改变:

sqlDB.execSQL("DROP TABLE IF EXISTS "+TaskContract.POI_NAMES+TaskContract.LONGITUDES+TaskContract.LATITUDES);

删除表时,只需指定其名称 - 在您的情况下,这是TaskContract.POI_NAMES。添加列名只会使SQL代码不正确,您的语句将被拒绝(即返回错误)。像这样:

sqlDB.execSQL("DROP TABLE IF EXISTS " + TaskContract.POI_NAMES);

这里也有一些问题:

ContentValues values = new ContentValues();
                        values.clear();
                        values.put(TaskContract.Columns.POI,poi);
                        db.insertWithOnConflict(TaskContract.POI_NAMES,null,values,SQLiteDatabase.CONFLICT_IGNORE);


                        values.put(TaskContract.Columns.LONGITUDE,longit);
                        db.insertWithOnConflict(TaskContract.LONGITUDES,null,values,SQLiteDatabase.CONFLICT_IGNORE);

                        values.put(TaskContract.Columns.LATITUDE,lat);
                        db.insertWithOnConflict(TaskContract.LATITUDES,null,values,SQLiteDatabase.CONFLICT_IGNORE);

调用insertWithOnConflict时,您提供了一个表名和一组代表每个列的键值。简而言之,您需要为要插入的每个记录调用insertWithOnConflict一次(而不是对于此记录中的每一列)。试试这段代码:

ContentValues values = new ContentValues();
values.put(TaskContract.Columns.POI,poi);
values.put(TaskContract.Columns.LONGITUDE,longit);
values.put(TaskContract.Columns.LATITUDE,lat);
db.insertWithOnConflict(TaskContract.POI_NAMES,null,values,SQLiteDatabase.CONFLICT_IGNORE);

完成这些更改后,您可以删除这些字段 - 不需要它们:

public static final String LONGITUDES = "longs";
public static final String LATITUDES = "lats";

让我知道它是否有效或您需要更多帮助! :)