I create a database containing 4 String columns in a separate class called CalDatabaseHelper:
public void onCreate(SQLiteDatabase db) {
updateDatabase(db,0,DATABASE_VERSION);
}
private static void updateDatabase(SQLiteDatabase db, int olderversion, int newerVersion){
if (olderversion < 1){
db.execSQL("CREATE TABLE CAL (_id TEXT PRIMARY KEY,"
+ "ACTIVITY1 TEXT, "
+ "ACTIVITY2 TEXT"
+ "ACTIVITY3 TEXT);");
}
}
private static void insertIntoDatabase(SQLiteDatabase db, String primaryKey, String activityOne, String activityTwo, String activityThree){
ContentValues values = new ContentValues();
values.put("_id",primaryKey);
values.put("ACTIVITY1",activityOne);
values.put("ACTIVITY2",activityTwo);
values.put("ACTIVITY3",activityThree);
db.insert("CAL",null,values);
}
I add data in an Activity called Appointments. For now, I just add to the _id (a String variable) and ACTIVITY1 (a String variable that comes from user input into and EditText) columns:
SQLiteOpenHelper sqLiteOpenHelper = new CalDatabaseHelper(Appointments.this);
SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
values.put("_id",primaryKey);
values.put("ACTIVITY1", activityOne);
db.insert("CAL", null, values);
db.close();
I attempt to retrieve this data in an Adapter Class. Once a widget is clicked, a database is opened, a Cursor finds the two columns(_id, ACTIVITY1) and the data is retrieved. This class contains the primaryKey data that I use to search the database:
SQLiteOpenHelper sqLiteOpenHelper = new CalDatabaseHelper(context);
db = sqLiteOpenHelper.getReadableDatabase();
cursor = db.query("CAL",
new String[]{"_id","ACTIVITY1"},
"_id = ?",
new String[]{month_day_year},
null, null, null);
if (cursor.moveToFirst()){
String actOne = cursor.getString(0);
activityOne.setText(actOne);
}else{
Toast.makeText(context, "NOTHING FOUND DURING OPEN", Toast.LENGTH_LONG).show();
}
cursor.close();
db.close();
Up until this point, everything works fine. I am able to retrieve the data from the first column (_id) by using cursor.getString(0).
When I go to retrieve the data from the 2nd column (ACTIVITY1), I keep getting an empty String. For example, cursor.getString(1) returns "". This should be the data that my user inputted in my Appointments Activity. The data is clearly placed in to ContentValues within that class and then put in to the database. Any idea why nothing is coming up there? Is it because I am using db.insert() instead of the method I created in my databaseHelper class called insertIntoDatabase()? How come the primary key is inserted then anyway? Thank you
Related
I'm new to Android Studio and can't seem to find what I'm asking for.
I want to have a database that stores the data of a few people, e.g.
Steve Hardy, 16 Somewhere Land, Colorado, U.S.A.
I would like this to have headings (Name, Address, City, Country).
I'm just struggling with how to format a table like this and how I would link a database to this.
In android, mostly use sqlite databases. I can give you 3 simple functions I use to create database and table, insert data to table, & to read database values. If there is any unclear thing or you want any clarification, ask. I can help you.
public class MainActivity extends AppCompatActivity {
//Assign below 3 variables as global variables where class start.
SQLiteDatabase db; //Assign as a global variable
String DBName = "MyDB"; //Assign as a global variable
String TableName = "PeopleData"; //Assign as a global variable
//Call 3 function inside oncreate method.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createDB_Table(); //calling 3 functions.
InsertDataToDB();
ReadDBData();
}
public void createDB_Table(){ //This function use to create database, table & columns.
db = this.openOrCreateDatabase(DBName, MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS " + TableName + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT, Address TEXT, City TEXT, Country TEXT);");
db.close();
}
public void InsertDataToDB(){ //This function use to inset values to database.
db = this.openOrCreateDatabase(DBName, MODE_PRIVATE, null);
ContentValues cv = new ContentValues();
cv.put("Name","Steve Hardy");
cv.put("Address","16 Somewhere Land");
cv.put("City","Colorado");
cv.put("Country","USA");
db.insert(TableName, null, cv);
db.close();
}
public void ReadDBData() { //This function use to read data from database.
db = this.openOrCreateDatabase(DBName, MODE_PRIVATE, null);
Cursor cursor = db.rawQuery("SELECT * FROM " + TableName, null);
if (cursor.getCount() > 0) { //check cursor is not empty.
cursor.moveToFirst();
String DName = cursor.getString(cursor.getColumnIndex("Name"));
String DAddress = cursor.getString(cursor.getColumnIndex("Address"));
String DCity = cursor.getString(cursor.getColumnIndex("City"));
String DCountry = cursor.getString(cursor.getColumnIndex("Country"));
//Got the values from database. Then you can set those values to text view or something you use.
}
cursor.close();
db.close();
}
}
I want to get a primary key of a saved object in a table in database I wrote a class to handle my database I want to add a function to it for getting the Id (I tried to give id to objects manually it didn't go well so I prefer the primary key id)so how should this function look like?and also if u see a thing that needs changing in my code please let me know.
public class DataBaseHandler extends SQLiteOpenHelper {
private static int _ID =0;
private int ID =0;
private ArrayList<marker_model> markerList=new ArrayList<>();
public DataBaseHandler(Context context) {
super(context, Constans.TABLE_NAME, null, Constans.DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+Constans.TABLE_NAME+
" ("+Constans.MARKER_ID+" INTEGER PRIMARY KEY, "+
Constans.MARKER_TITLE+" TEXT, " +Constans.MARKER_DESCRIPTION+" TEXT ,"+Constans.My_MARKER_ID+" INT );");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+Constans.TABLE_NAME);
onCreate(db);
}
public void AddMarker(marker_model marker){
marker.set_Id(_ID);
SQLiteDatabase db=this.getWritableDatabase();
ContentValues values=new ContentValues();
values.put(Constans.MARKER_TITLE,marker.getTitle());
values.put(Constans.My_MARKER_ID,marker.get_Id());
values.put(Constans.MARKER_DESCRIPTION,marker.getDescription());
db.insert(Constans.TABLE_NAME,null,values);
db.close();
Log.d(TAG, "AddMarker: Successfully added to DB");
_ID++;
}
public ArrayList<marker_model> getMarkers(){
markerList.clear();
SQLiteDatabase db =getReadableDatabase();
Cursor cursor=db.query(Constans.TABLE_NAME
,new String[]{Constans.My_MARKER_ID,Constans.MARKER_TITLE,
Constans.MARKER_DESCRIPTION},null,null,null,null,null);
if (cursor.moveToFirst()){
do {
ID=0;
marker_model model=new marker_model();
model.set_Id(_ID);
model.setDescription(cursor.getString(cursor.getColumnIndex(Constans.MARKER_DESCRIPTION)));
model.setTitle(cursor.getString(cursor.getColumnIndex(Constans.MARKER_TITLE)));
markerList.add(model);
ID++;
}while(cursor.moveToNext());
}
cursor.close();
db.close();
return markerList;
}
public int getMarkerPrimaryId(Marker marker){
}
}
Assuming that you want to get the _id (the primary key) from the database and that marker is an instance of a marker_model object AND that
marker_model has methods getTitle and getDescription that return a string with the respective values, then something along the lines of the following would work.
public long getMarkerPrimaryId(Marker marker){
long rv = 0;
SQLiteDatabase db = getReadableDatabase();
String[] columns = new String[]{Constans.My_MARKER_ID};
String whereclause = Constans.MARKER_TITLE + "=?" +
Constans.MARKER_DESCRIPTION + "=?";
String[] whereargs = new String[]{
marker.getTitile,
marker.getDescription
}
Cursor cursor = db.query(Constans.TABLE_NAME,
columns,
whereclause,
whereargs,
null,null,null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
rv = cursor.getLong(cursor.getColumnIndex(Constans.My_MARKER_ID);
}
cursor.close;
db.close;
return rv;
}
However, if your issue is that getMarkers is not setting the Id member appropriately (i.e. to match the id in the database), then changing model.set_Id(_ID);
to
model.set_Id(cursor.getLong(cursor.getColumnIndex(Constans.My_MARKER_ID));
would suffice.
If your expectation is that an automatically generated incrementing _id is to be used the addMarker is a little flawed. Simply by removing the line values.put(Constans.My_MARKER_ID,marker.get_Id()); will result in _id being automatically generated (which how _id's tend to be used).
The following (BACKGROUND paragraph mostly) explains much about automatically generated unique identifiers (even though it is about AUTOINCREMENT you likely DO NOT want to code AUTOINCREMENT).
Id suggest that rather than :-
if (cursor.moveToFirst()){
do {
...
}while(cursor.moveToNext());
using :-
while (cursor.moveToNext() {
....
}
is simpler (a cursor, when created, will be positioned to before the first row (moveToPosition(-1) has the same effect) , moveToNext() will move to the first row the first time, if there are no rows the loop will not be entered (you may wish to consider this and the state of returned markerlist)).
Note! the above has been written without testing, so there may be the odd mistake.
I want to search a column by using an id.
That function will return all the values in that particular row.
Here's my code and log.
LOG:
09-19 14:00:54.940 618-618/? **I/SqliteDatabaseCpp﹕ sqlite returned: error code = 1, msg = table IUBConnectivitydata already exists, db=/data/data/com.example.sivs.datacopy/databases/**
09-19 14:00:54.970 618-618/? E/SQLiteOpenHelper﹕ Couldn't open Database1 for writing (will try read-only):
Code:
public Cursor Rowdata(String a){
SQLiteDatabase db=this.getReadableDatabase();
Log.d("a4","aaa34");
Cursor cursor1=db.rawQuery("SELECT "+COL_3+", FROM" + TABLE_NAME + "where WBTSID==?",new String[] {a});
Log.d("a3","row");
return cursor1;
}
You added an extra comma before FROM, an extra = before ? and forgot 2 spaces around the table name.
Wrong:
db.rawQuery("SELECT "+COL_3+", FROM" + TABLE_NAME + "where WBTSID==?",new String[] {a});
Right:
db.rawQuery("SELECT "+COL_3+" FROM " + TABLE_NAME + " where WBTSID=?",new String[] {a});
try following,
if (c.moveToFirst()){
do{
id = c.getInt(c.getColumnIndex("_id"));
}while(cursor.moveToNext());
}
c is a cursor of all data.
I would recommend only one global database helper class instance, which can be located in the extended application class. The helper class itself must hold an instance of SQLiteDatabase, which is the actual database object.
It can look like this:
public MyClass extends Application {
private MyDBHelper db;
public MyDBHelper getDB() {
if (database == null) {
db = new MyDBHelper(this);
}
db.open(); // call getWritableDataBase internally
return db;
}
}
If you create the database in the SqlLiteHelpers onCreate() callback, then it should be only created the very first time you open the app after installation.
In the onOpen() callback of SqlLitehelper you can activate foreign key constraints with setForeignKeyConstrainsEnabled(true), which is an important safety feature. Of coure you have to declare foreign keys with REFERS() clauses.
EDIT: Creating a synchronized static instance is also possible (as stated in the comment below). Anyway you must ensure that there exists only one instance of your database helper class and only one instance of the database itself. (Which must be located in the database helper class)
I am developing my first application which contains an SQLite database, containing table ANIMAL which has the columns _id, animal_name, animal_bio.
The user is presented with animal names in a ListView; selecting an animal will bring him/her to a page where he/she can view the animals bio.
The problem I'm having is:
When I add the bio of each animal to the DB - no errors.
However, running the app causes the ListView (previously working) to display a blank screen.
My Insertion code:
public long populateDB(){
ContentValues initialValues = new ContentValues();
long[] rowIds = new long[animalName.length];
// Populate the animal table
for(int i = 0; i < animalName.length; i++){
initialValues.put(KEY_ANIMALNAME, animalName[i]);
initialValues.put(KEY_BIOGRAPHY, bio[i]);
rowIds[i] = qmDB.insert(ANIMAL_TABLE, null, initialValues);
}
return rowIds[0];
}
And the create database statement
private static final String DATABASE_CREATE =
"create table " + ANIMAL_TABLE +
" (_id integer primary key autoincrement, " +
"animal_name text not null, " +
"biography text not null);";
I cannot see anything wrong with this code, so if anyone has any suggestions, I'd be very grateful.
EDIT: Retrieving animals code
public Cursor retrieveAnnimals(){
return qmDB.query(ANIMAL_TABLE, new String[] {
KEY_ROWID,
KEY_ANIMALNAME,
},
null,
null,
null,
null,
ORDER_BY_NAME);
}
Calling the create and insert from application, this takes place in the ListActivity, called ListAnimals:
dbm = new MyDBManager();
dbm.open();
dbm.deleteTable();
dbm.populateTable();
myCursor = dbm.retrieveAnimals();
I got some problem with my database in my Android application. Perhaps, my application is working but let me explain you.
Here are just parts of the code from my app.. i don't want to paste the whole it's not needed.
private SQLiteStatement insertStmt;
private static final String INSERT = "insert into "
+ TABLE_NAME + "(name,surname) values (?,?)";
public DataHelper(Context context) {
this.context = context;
OpenHelper openHelper = new OpenHelper(this.context);
this.db = openHelper.getWritableDatabase();
this.insertStmt = this.db.compileStatement(INSERT);
}
public long insert(String name, String surname) {
this.insertStmt.bindString(1, name);
this.insertStmt.bindString(2, surname);
return this.insertStmt.executeInsert();
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, surname TEXT)");
}
So when i try to run my app i get Force close, but when i put manually :
dh.insert("test", "ooo");
..in the onCreate method in my main activity everything is fine and working.
So, the conclusion is that i must put some value for the first time i run the app so it can work properly. I thought maybe to update that row with the new informations that i insert later through some TextView's from the app but i'm wondering if there is smarter solution than this?
Obviously there is no error with your insert, at least it's not what crashes your App.
Since you're getting a CursorIndexOutOfBoundsException, it means you have somewhere a select query and try to move or set it before checking if it's has any rows at all.
This usually happens if you move the cursor to a non-existing index, i.e. cursor.moveToFirst() while your cursor is empty or cursor.move(n) where n is bigger than cursor.getCount()-1
Before moving or accessing a cursor you ALWAYS have to check if any rows are returned!
Cursor c = db.query(...);
if(c!=null && c.getCount()>0) {
c.moveToFirst(); // (or c.move(0))
// Do your cursor operations here!
}
Obviously your insert fails for some reason, you can easily check this, with:
long insertId = dh.insert("test", "ooo");
if(insertId > 0) {
// insert was successfull
} else {
// insert failed
}