我想创建一个包含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 ;;
它有效,但它将所有内容放在同一列中。
有人可以解释分配价值的确切含义"任务"我的字符串?
答案 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";
让我知道它是否有效或您需要更多帮助! :)