Currently my SQLite database is working great, I have read up on various methods such as this one to achieve this, though currently I am having issues with setting up the Date constructor and also how to define the data for use in putting it to the database (and getting it back!)
So far I have used static final String to define my data variables, notsure which is the correct way to use Date.
I'm not concerned with the time, just the date the entry was created.
Below is my java class:
import java.sql.Date;
import java.text.SimpleDateFormat;
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.SQLiteOpenHelper;
public class Stats {
public static final String KEY_ROWID = "_id";
public static final String KEY_WEIGHT = "weight";
public static final String KEY_WAIST = "waist";
public static final String KEY_CHEST = "chest";
public static final String KEY_LEGS = "legs";
public static final String KEY_ARMS = "arms";
public static final String KEY_DATE = "date";
private static final String DATABASE_NAME = "statsDB";
private static final String DATABASE_TABLE = "personalStats";
private static final int DATABASE_VERSION = 3;
private DbHelper ffHelper;
private final Context ffContext;
private SQLiteDatabase ffDatabase;
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" + KEY_ROWID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_WEIGHT
+ " TEXT NOT NULL, " + KEY_WAIST + " TEXT NOT NULL, "
+ KEY_CHEST + " TEXT NOT NULL, " + KEY_LEGS
+ " TEXT NOT NULL, " + KEY_ARMS + " TEXT NOT NULL, "
+ KEY_DATE + " TEXT NOT NULL);");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
public Stats(Context c) {
ffContext = c;
}
public Stats open() throws SQLException {
ffHelper = new DbHelper(ffContext);
ffDatabase = ffHelper.getWritableDatabase();
return this;
}
public void close() {
ffHelper.close();
}
public long createEntry(String weight, String waist, String chest, String legs, String arms) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
ContentValues cv = new ContentValues();
cv.put(KEY_WEIGHT, weight);
cv.put(KEY_WAIST, waist);
cv.put(KEY_CHEST, chest);
cv.put(KEY_LEGS, legs);
cv.put(KEY_ARMS, arms);
cv.put("date_created", dateFormat.format(date));
return ffDatabase.insert(DATABASE_TABLE, null, cv);
}
public String getData() {
String[] columns = new String[] { KEY_ROWID, KEY_WEIGHT, KEY_WAIST, KEY_CHEST, KEY_LEGS, KEY_ARMS, KEY_DATE };
Cursor c = ffDatabase.query(DATABASE_TABLE, columns, null, null, null,
null, null);
String result = "";
int iRow = c.getColumnIndex(KEY_ROWID);
int iWeight = c.getColumnIndex(KEY_WEIGHT);
int iWaist = c.getColumnIndex(KEY_WAIST);
int iChest = c.getColumnIndex(KEY_CHEST);
int iLegs = c.getColumnIndex(KEY_LEGS);
int iArms = c.getColumnIndex(KEY_ARMS);
int iDate = c.getColumnIndex(KEY_DATE);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
result = result + c.getString(iRow) + " " + c.getString(iWeight)
+ " " + c.getString(iWaist)
+ " " + c.getString(iChest)
+ " " + c.getString(iLegs)
+ " " + c.getString(iArms)
+ " " + c.getString(iDate)+ "\n";
}
return result;
}
}
Obviously any time Date is mentioned is where I have attempted to add this extra functionality.
You may put date like string in database, but this string must have good format.
For SQLite it is:
YYYY-MM-dd
YYYY-MM-dd hh:mm
YYYY-MM-dd hh:mm:ss
YYYY-MM-dd hh:mm:ss.sss
YYYY-MM-DDThh:mm
YYYY-MM-DDThh:mm:ss
YYYY-MM-DDThh:mm:ss.sss
hh:mm
hh:mm:ss
hh:mm:ss.sss
Like Yoann write you can convert date to string with:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateForinsert = dateFormat(new GregorianCalendar(2013, GregorianCalendar.MAY, 5).getTime());
"Now" you can set with:
String dateForinsert = dateFormat(new GregorianCalendar().getTime());
Related
Im trying to store a particular columns data in a method and call that method in another classes String [] where a spinner will access that array to display the columns rows for the user to select which will then get stored in another database.
Im getting nulpointerexception and when I try and open() the database the database gets locked. Sorry for sounding like a complete amateur, relatively new to android. Thank you in advance for any help.
Here is my code when I call getInstance() and getCPnames() in my main class
String[] carParks = CarParkDb.getInstance().getCpnames();
Here is my code for the database:
package com.example.parkangel;
import java.util.ArrayList;
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.SQLiteOpenHelper;
public class CarParkDb {
public static final String KEY_ID = "_id";
public static final String KEY_CPNAME = "cpname";
public static final String KEY_COST = "cost";
private static final String DATABASE_NAME = "CPDB";
private static final String DATABASE_TABLE = "CPTable";
private static final int DATABASE_VERSION = 1;
private CPDbHelper cpdbHelper;
private Context ourContext;
private SQLiteDatabase ourDatabase;
private static CarParkDb instance;
private static class CPDbHelper extends SQLiteOpenHelper{
public CPDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_CPNAME + " TEXT NOT NULL, " + KEY_COST + " TEXTNOT NULL);");
db.execSQL("INSERT INTO " + DATABASE_TABLE + " Values('1','LearningResource Center','2');");
db.execSQL("INSERT INTO " + DATABASE_TABLE + " Values ('2','ParkandRide','1');");
db.execSQL("INSERT INTO " + DATABASE_TABLE + " Values ('3','deHavilland Campus','2');");
db.execSQL("INSERT INTO " + DATABASE_TABLE + " Values('4','MultiStorey Building','2');");
db.execSQL("INSERT INTO " + DATABASE_TABLE + " Values('5','Reception','2');");
}
public void onOpen(final SQLiteDatabase db) {
super.onOpen(db);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
public CarParkDb (final Context c)
{
this.cpdbHelper= new CPDbHelper(c);
establishDb();
//ourContext = c;
}
public void establishDb()
{
if (this.ourDatabase == null)
{
this.ourDatabase = this.cpdbHelper.getWritableDatabase();
}
}
public CarParkDb() {
// TODO Auto-generated constructor stub
}
public CarParkDb open() throws SQLException
{
System.out.println ("running open");
cpdbHelper = new CPDbHelper(ourContext);
ourDatabase = cpdbHelper.getWritableDatabase();
return this;
}
public void close()
{
ourDatabase.close();
}
/*public long createEntry(String cpname, String cost){
ContentValues cv = new ContentValues();
cv.put(KEY_CPNAME, cpname);
cv.put(KEY_COST, cost);
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}*/
public String getData() {
// TODO Auto-generated method stub
//open();
String[] columns = new String[] {KEY_ID, KEY_CPNAME, KEY_COST};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, null,null,null, null, null);
String result = " ";
int iRow = c.getColumnIndexOrThrow(KEY_ID);
int iCpname = c.getColumnIndexOrThrow(KEY_CPNAME);
int iCost = c.getColumnIndexOrThrow(KEY_COST);
for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
result = result + c.getString(iRow) + " " +c.getString(iCpname) + " " + c.getString(iCost) + " " + "\n";
c.close();
ourDatabase.close();
}
return result;
}
public static CarParkDb getInstance()
{
synchronized(CarParkDb.class)
{
if (instance == null)
{
instance = new CarParkDb();
}
return instance;
}
}
public String[] getCpnames()
{
//open();
if (ourDatabase == null) System.out.println ("is null");
Cursor c = null;
ArrayList<String> list = new ArrayList<String>();
ourDatabase = cpdbHelper.getReadableDatabase();
//SQLiteDatabase db = cpdbHelper.getReadableDatabase();
String query = "SELECT " + KEY_CPNAME + " FROM " + DATABASE_TABLE;
{
c = this.ourDatabase.rawQuery(query, null);
int iCpname = c.getColumnIndexOrThrow(KEY_CPNAME);
if (c.moveToFirst())
{
do
{
list.add(c.getString(iCpname));;
}
while (c.moveToNext());
}
if (c != null && !c.isClosed())
{
c.close();
ourDatabase.close();
}
return list.toArray(new String[]{});
}
}
}
**LogCat**
03-12 01:32:39.759: E/AndroidRuntime(4176): Caused by:java.lang.NullPointerException
03-12 01:32:39.759: E/AndroidRuntime(4176):
at com.example.parkangel.CarParkDb.getCpnames(CarParkDb.java:191)
03-12 01:32:39.759: E/AndroidRuntime(4176):
at com.example.parkangel.BookTicket.<init>(BookTicket.java:22)
03-12 01:32:39.759: E/AndroidRuntime(4176):
at java.lang.Class.newInstanceImpl(Native Method)
03-12 01:32:39.759: E/AndroidRuntime(4176):
at java.lang.Class.newInstance(Class.java:1208)
The database doesn't get locked. The "locked" thinkg is just a NPE in a method called getDatabaseLocked() and it's caused by a null Context passed to SQLiteOpenHelper in constructor that manifests itself with getWritableDatabase() or getReadableDatabase().
To fix the NPE in getDatabaseLocked(), make sure ourContext in open() is not null. As of now, you've never initialized ourContext and it's always null. Uncomment the //ourContext = c; in constructor and move it above the establishDb(), remove the other no-argument constructor and pass in a Context for example as suggested by Merlevede.
The NPE stacktrace in your question is when you call getCpNames() with open() commented out and are trying to call a method on a null ourDatabase object reference. Uncomment the open() there once it's fixed. The stacktrace also says you're trying to call getCpNames() in object initialization phase e.g. when initializing a member variable. That might be too early, for example an activity cannot be used as a Context until onCreate().
Some other things in your code you'd hit next:
in onCreate(): + KEY_COST + " TEXTNOT NULL) - add space between TEXT and NOT
in getData(): you're closing the cursor and database in the loop where you're accessing the cursor. Do it after the loop. The code shouldn't compile as you're not returning anything from a non-void function in case moveToFirst() returns false.
Try updating your getInstance() code with this:
public static CarParkDb getInstance(Context c) // <-- added context as parameter
{
synchronized(CarParkDb.class)
{
if (instance == null)
{
instance = new CarParkDb(c); // <-- used context in constructor
}
return instance;
}
}
The problem seems to be that you're using a constructor (for CarParkDb) that does nothing. You have another constructor that takes a Context as parameter and initializes some of the objects that you're using later.
I am writing an Android application that queries a database with 170,000 dictionary words. (It has 31 columns: _id, word, sortedWord, length, and count_A, count_B, count_C, ... count_Z)
Here is the code for my Dictionary database helper
public class DictionaryDbHelper extends SQLiteOpenHelper {
private static final String TAG = "DataBaseHelper";
// The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.rabbitfighter.wordsleuth/databases/";
// Database name
private static String DB_NAME = "dictionary.db";
// Database, and context
private SQLiteDatabase myDataBase;
private final Context myContext;
// Table name
public static final String TABLE_NAME = "dictionary";
// Table columns
public static final String UID = "_id";
// Word
public static final String COLUMN_NAME_WORD = "word";
// Length
public static final String COLUMN_NAME_WORD_LENGTH = "length";
// For all the letters, A-Z.
public static final String COLUMN_NAME_COUNT_A = "count_A";
public static final String COLUMN_NAME_COUNT_B = "count_B";
public static final String COLUMN_NAME_COUNT_C = "count_C";
public static final String COLUMN_NAME_COUNT_D = "count_D";
public static final String COLUMN_NAME_COUNT_E = "count_E";
public static final String COLUMN_NAME_COUNT_F = "count_F";
public static final String COLUMN_NAME_COUNT_G = "count_G";
public static final String COLUMN_NAME_COUNT_H = "count_H";
public static final String COLUMN_NAME_COUNT_I = "count_I";
public static final String COLUMN_NAME_COUNT_J = "count_J";
public static final String COLUMN_NAME_COUNT_K = "count_K";
public static final String COLUMN_NAME_COUNT_L = "count_L";
public static final String COLUMN_NAME_COUNT_M = "count_M";
public static final String COLUMN_NAME_COUNT_N = "count_N";
public static final String COLUMN_NAME_COUNT_O = "count_O";
public static final String COLUMN_NAME_COUNT_P = "count_P";
public static final String COLUMN_NAME_COUNT_Q = "count_Q";
public static final String COLUMN_NAME_COUNT_R = "count_R";
public static final String COLUMN_NAME_COUNT_S = "count_S";
public static final String COLUMN_NAME_COUNT_T = "count_T";
public static final String COLUMN_NAME_COUNT_U = "count_U";
public static final String COLUMN_NAME_COUNT_V = "count_V";
public static final String COLUMN_NAME_COUNT_W = "count_W";
public static final String COLUMN_NAME_COUNT_X = "count_X";
public static final String COLUMN_NAME_COUNT_Y = "count_Y";
public static final String COLUMN_NAME_COUNT_Z = "count_Z";
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* #param context
*/
public DictionaryDbHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/* ------------------------ */
/* --- Override Methods --- */
/* ------------------------ */
/**
* On creation
* #param db - the database
*/
public void onCreate(SQLiteDatabase db) {
//Nothing to do here
}
/**
* On upgrade
* #param db - the database
* #param oldVersion - the old database version int
* #param newVersion - the new database version int
*/
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Database " + db + " version " + oldVersion + " upgraded to " + newVersion);
}
/**
* On downgrade
* #param db - the database
* #param oldVersion - the old database version int
* #param newVersion - the new database version int
*/
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Database " + db + " version " + oldVersion + " downgraded to " + newVersion);
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException{
if(checkDataBase()){
//do nothing - database already exist
Log.i(TAG, "Database already exists... Nothing to do.");
}else{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
Log.i(TAG, "Successfully copied database");
} catch (IOException e) {
Log.i(TAG, "Error copying");
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database doesn't exist yet.
Log.i(TAG, "Database doesn't exist yet");
}
// Check for null db
if(checkDB != null){
checkDB.close();
Log.i(TAG, "Closed dict database");
}
// Return null or not null
return checkDB != null;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException {
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
#Override
public synchronized void close() {
if(myDataBase != null) {
Log.i(TAG, "Closing dictionary database");
myDataBase.close();
}
super.close();
}
/* -------------------------- */
/* --- Database retrieval --- */
/* -------------------------- */
/**
* Get the Anagrams in the database
* #return the number of anagrams
*/
public ArrayList<Result> getMatches(
// Params. Yeah, I know...
int count_A, int count_B, int count_C, int count_D, int count_E, int count_F,
int count_G, int count_H, int count_I, int count_J, int count_K, int count_L,
int count_M, int count_N, int count_O, int count_P, int count_Q, int count_R,
int count_S, int count_T, int count_U, int count_V, int count_W, int count_X,
int count_Y, int count_Z, int count_WILDCARDS
) {
// Get the database helper to get access to everything...
SQLiteDatabase db = this.getWritableDatabase();
// List to hold matches
ArrayList<Result> resultList = new ArrayList<>();
// Here are the columns we care about in our search
String[] columns = {
UID,
COLUMN_NAME_WORD,
COLUMN_NAME_WORD_LENGTH,
COLUMN_NAME_COUNT_A,
COLUMN_NAME_COUNT_B,
COLUMN_NAME_COUNT_C,
COLUMN_NAME_COUNT_D,
COLUMN_NAME_COUNT_E,
COLUMN_NAME_COUNT_F,
COLUMN_NAME_COUNT_G,
COLUMN_NAME_COUNT_H,
COLUMN_NAME_COUNT_I,
COLUMN_NAME_COUNT_J,
COLUMN_NAME_COUNT_K,
COLUMN_NAME_COUNT_L,
COLUMN_NAME_COUNT_M,
COLUMN_NAME_COUNT_N,
COLUMN_NAME_COUNT_O,
COLUMN_NAME_COUNT_P,
COLUMN_NAME_COUNT_Q,
COLUMN_NAME_COUNT_R,
COLUMN_NAME_COUNT_S,
COLUMN_NAME_COUNT_T,
COLUMN_NAME_COUNT_U,
COLUMN_NAME_COUNT_V,
COLUMN_NAME_COUNT_W,
COLUMN_NAME_COUNT_X,
COLUMN_NAME_COUNT_Y,
COLUMN_NAME_COUNT_Z,
};
String[] selectionArgs = null;
// The selection (WHERE ...)
String selection =
COLUMN_NAME_COUNT_A +"<="+ count_A + " AND " +
COLUMN_NAME_COUNT_B +"<="+ count_B + " AND " +
COLUMN_NAME_COUNT_C +"<="+ count_C + " AND " +
COLUMN_NAME_COUNT_D +"<="+ count_D + " AND " +
COLUMN_NAME_COUNT_E +"<="+ count_E + " AND " +
COLUMN_NAME_COUNT_F +"<="+ count_F + " AND " +
COLUMN_NAME_COUNT_G +"<="+ count_G + " AND " +
COLUMN_NAME_COUNT_H +"<="+ count_H + " AND " +
COLUMN_NAME_COUNT_I +"<="+ count_I + " AND " +
COLUMN_NAME_COUNT_J +"<="+ count_J + " AND " +
COLUMN_NAME_COUNT_K +"<="+ count_K + " AND " +
COLUMN_NAME_COUNT_L +"<="+ count_L + " AND " +
COLUMN_NAME_COUNT_M +"<="+ count_M + " AND " +
COLUMN_NAME_COUNT_N +"<="+ count_N + " AND " +
COLUMN_NAME_COUNT_O +"<="+ count_O + " AND " +
COLUMN_NAME_COUNT_P +"<="+ count_P + " AND " +
COLUMN_NAME_COUNT_Q +"<="+ count_Q + " AND " +
COLUMN_NAME_COUNT_R +"<="+ count_R + " AND " +
COLUMN_NAME_COUNT_S +"<="+ count_S + " AND " +
COLUMN_NAME_COUNT_T +"<="+ count_T + " AND " +
COLUMN_NAME_COUNT_U +"<="+ count_U + " AND " +
COLUMN_NAME_COUNT_V +"<="+ count_V + " AND " +
COLUMN_NAME_COUNT_W +"<="+ count_W + " AND " +
COLUMN_NAME_COUNT_X +"<="+ count_X + " AND " +
COLUMN_NAME_COUNT_Y +"<="+ count_Y + " AND " +
COLUMN_NAME_COUNT_Z +"<="+ count_Z;
String groupBy = null;
String having = null;
String orderBy = null;
// Query the database
Cursor cursor = db.query(
TABLE_NAME, // Table name
columns, // Columns
selection, // Selection
selectionArgs, // Selection arguments
groupBy, // Group by...
having, // having
orderBy // Order by
);
while (cursor.moveToNext()) {
int columnResult = cursor.getColumnIndex(COLUMN_NAME_WORD);
// Add the result to the list to return
resultList.add(new Result(cursor.getString(columnResult)));
}
cursor.close();
// Return the list
return resultList;
}
}//EOF
And here is where I query the Dictionary in another class:
How can I query for wildcards given my current setup? I am new to sql, so any suggestions would be greatly appreciated... I am looking for a parameter for the WHERE clause to allow for up to 2 wildcards, each of which could be anything from A-Z.
Here is an example of how i'm doing a lookup now, from my search service:
DictionaryDbHelper helper = DictionaryDbHelper(this);
ArrayList<Result> matches = helper.getMatches(
this.getQuery().getCount_A(), this.getQuery().getCount_B(),
this.getQuery().getCount_C(), this.getQuery().getCount_D(),
this.getQuery().getCount_E(), this.getQuery().getCount_F(),
this.getQuery().getCount_G(), this.getQuery().getCount_H(),
this.getQuery().getCount_I(), this.getQuery().getCount_J(),
this.getQuery().getCount_K(), this.getQuery().getCount_L(),
this.getQuery().getCount_M(), this.getQuery().getCount_N(),
this.getQuery().getCount_O(), this.getQuery().getCount_P(),
this.getQuery().getCount_Q(), this.getQuery().getCount_R(),
this.getQuery().getCount_S(), this.getQuery().getCount_T(),
this.getQuery().getCount_U(), this.getQuery().getCount_V(),
this.getQuery().getCount_W(), this.getQuery().getCount_X(),
this.getQuery().getCount_Y(), this.getQuery().getCount_Z(),0 // wildcards not in use yet
)
I have a table with two columns first is date and the second is a counter. I do not have a primary key but the date acts as one. So my code checks if the current date exists in the table, if so it will only increment the counter other wise it will add a new entry. The existence of the current date is only possible at the last row. here is the code:
SQLiteOpenHelper implementation:
public class SqliteHelperInstance extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "app_stats";
public static final String TABLE_NAME = "day_stats";
public static final String COLUMN_DATE = "date";
public static final String COLUMN_CIGCOUNT = "cigcount";
public static final int DATABASE_VERSION = 1;
private static final String CREATE_DB = "create table " + TABLE_NAME + " ( " + COLUMN_DATE + " text, "
+ COLUMN_CIGCOUNT + " integer );";
public SqliteHelperInstance(Context context){
super(context,DATABASE_NAME , null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(CREATE_DB);
}
}
The implementation of database manager:
public class DbManager {
private SqliteHelperInstance sqlHelper;
private SQLiteDatabase database;
private String[] columns = { SqliteHelperInstance.COLUMN_DATE, SqliteHelperInstance.COLUMN_CIGCOUNT};
public DbManager(Context context){
sqlHelper = new SqliteHelperInstance(context);
}
public void addEntry(Calendar cal){
ContentValues values = new ContentValues();
String dateEntry = dateFormatter(cal);
Cursor cursor = database.query(SqliteHelperInstance.TABLE_NAME, null, null, null, null, null,
SqliteHelperInstance.COLUMN_DATE + " DESC LIMIT 1");
//check if the last entered date is equal to the current date
if(cursor.moveToFirst()){
String lastDate = cursor.getString(0);
if(lastDate.equalsIgnoreCase(dateEntry)){
//the cigNum should be updated for the current date
int cigNum = cursor.getInt(1);
cigNum ++;
values.put(SqliteHelperInstance.COLUMN_DATE,lastDate);
values.put(SqliteHelperInstance.COLUMN_CIGCOUNT, cigNum);
int i = database.update(SqliteHelperInstance.TABLE_NAME, values,SqliteHelperInstance.COLUMN_DATE + " = " + lastDate , null);
if(i == 0){
Log.d("Tag", "No row is affected");
}
}
else{
//the last date is different than current day so we need to add a new entry
DbEntry newEntry = new DbEntry();
newEntry.setDate(dateEntry);
values.put(SqliteHelperInstance.COLUMN_DATE, dateEntry);
values.put(SqliteHelperInstance.COLUMN_CIGCOUNT, newEntry.getCigNum());
database.insert(SqliteHelperInstance.TABLE_NAME, null, values);
}
}
else{
//its the first time that the application is loading
DbEntry newEntry = new DbEntry();
newEntry.setDate(dateEntry);
newEntry.setCignum(1);
values.put(SqliteHelperInstance.COLUMN_DATE, dateEntry);
values.put(SqliteHelperInstance.COLUMN_CIGCOUNT, newEntry.getCigNum());
Log.i(null, "values are set");
database.insert(SqliteHelperInstance.TABLE_NAME, null, values);
}
}
But when I run the application, I keep getting 0 row affected by the update function.I assume the comparison in the where clause is not returning any particular row. can anyone help me with this issue?
Try getting the lastDate like this:
String lastDate = cursor.getString(cursor.getColumnIndex(SqliteHelperInstance.COLUMN_DATE));
Also, you should use parameterized queries:
int i = database.update(SqliteHelperInstance.TABLE_NAME, values,SqliteHelperInstance.COLUMN_DATE + " = ?", new String[]{ lastDate });
Other than that, I'm not sure what could be wrong.
I am trying to insert into my database table using the database helper class.
this is where I create the object to insert.
Item item1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
db = new MyDBAdapter(this);
db.insertEntry(item1 = new Item("Bathtub", "Bathroom", "Typical", "Clean", "fill, wash", "Round, deep", "Bathroom", "Toilet, Bathroom", R.drawable.ic_launcher));
Log.i("item", "item: " + item1.toString());
And this is the Item class
public class Item {
//private variables
int _id;
String _item_name;
String _item_classification;
String _group;
String _use;
String _action;
String _properties;
String _location;
String _association;
int _img_id;
//Empty constructor
public Item(){
}
//constructor
public Item (int _id, String _item_name, String _group, String _item_classification, String _use, String _action, String _properties, String _location, String _association, int _img_id) {
this._id = _id;
this._item_name = _item_name;
this._item_classification = _item_classification;
this._group = _group;
this._use = _use;
this._action = _action;
this._properties = _properties;
this._location = _location;
this._association = _association;
this._img_id = _img_id;
}
public Item (String _item_name, String _group, String _item_classification, String _use, String _action, String _properties, String _location, String _association, int _img_id) {
this._item_name = _item_name;
this._item_classification = _item_classification;
this._group = _group;
this._use = _use;
this._action = _action;
this._properties = _properties;
this._location = _location;
this._association = _association;
this._img_id = _img_id;
with getters and setters of course.Now when i use the insert method for my database helper i get an error that is saying syntax error near "group". Why is my insert failing?
public class MyDBAdapter {
private static final String DATABASE_NAME = "myDatabase.db";
private static final String DATABASE_TABLE = "mainTable";
private static final int DATABASE_VERSION = 1;
//main table columns
public static final String KEY_ITEM = "item_name";
public static final String KEY_GROUP = "group";
public static final String ITEM_CLASSIFICATION = "classification";
public static final String KEY_USE = "use";
public static final String KEY_ACTION = "action";
public static final String KEY_PROPERTIES = "properties";
public static final String KEY_ASSOCIATION = "association";
public static final String KEY_IMG_ID = "img_id";
// The index (key) column name for use in where clauses.
public static final String KEY_ID="_id";
// The name and column index of each column in your database.
public static final int NAME_COLUMN = 1;
public static final int GROUP_COLUMN = 2;
public static final int CLASSIFICATION_COLUMN = 3;
public static final int USE_COLUMN = 4;
public static final int ACTION_COLUMN = 5;
public static final int PROPERTIES_COLUMN = 6;
public static final int ASSOCIATION_COLUMN = 7;
public static final int IMG_ID_COLUMN = 8;
// TODO: Create public field for each column in your table.
// SQL Statement to create a new database.
private static final String DATABASE_CREATE = "create table " +
DATABASE_TABLE + " ("
+ KEY_ID + " integer primary key autoincrement, "
+ KEY_ITEM + " TEXT, "
+ KEY_GROUP + " TEXT, "
+ ITEM_CLASSIFICATION + " TEXT, "
+ KEY_USE + " TEXT, "
+ KEY_ACTION + " TEXT, "
+ KEY_PROPERTIES + " TEXT, "
+ KEY_ASSOCIATION + " TEXT, "
+ KEY_IMG_ID + " INTEGER);";
// Variable to hold the database instance
private SQLiteDatabase db;
// Context of the application using the database.
private final Context context;
// Database open/upgrade helper
private myDbHelper dbHelper;
public MyDBAdapter(Context _context) {
context = _context;
dbHelper = new myDbHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public MyDBAdapter open() throws SQLException {
try {
db = dbHelper.getWritableDatabase();
} catch (SQLiteException e) {
db = dbHelper.getReadableDatabase();
}
return this;
}
public void close() {
db.close();
}
public void insertEntry(Item item) {
// TODO: Create a new ContentValues to represent my row
// and insert it into the database.
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_ITEM, item.get_item_name());
values.put(KEY_GROUP, item.get_group());
values.put(ITEM_CLASSIFICATION, item.get_item_classification());
values.put(KEY_USE, item.get_use());
values.put(KEY_ACTION, item.get_action());
values.put(KEY_PROPERTIES, item.get_properties());
values.put(KEY_ASSOCIATION, item.get_association());
values.put(KEY_IMG_ID, item.get_img_id());
// insert row to table
try{
db.insertOrThrow(DATABASE_TABLE, null, values);
}catch (Exception e){Log.w("insertFail", "insert failed: " + e.toString());}
db.close();
}
I get a syntax error-->sqlite returned: error code = 1, msg = near "group": syntax error
You are forgetting a space after your column names. Change,
private static final String DATABASE_CREATE = "create table " +
DATABASE_TABLE + " (" + KEY_ID +
" integer primary key autoincrement, " +
KEY_ITEM + " text not null, " + KEY_GROUP + "TEXT, " +
ITEM_CLASSIFICATION + "TEXT, " + KEY_USE + "TEXT, " +
KEY_ACTION + "TEXT, " + KEY_PROPERTIES + "TEXT" +
KEY_ASSOCIATION + "TEXT," + KEY_IMG_ID + "INTEGER" + ");";
to
private static final String DATABASE_CREATE = "create table " +
DATABASE_TABLE + " (" + KEY_ID +
" integer primary key autoincrement, " +
KEY_ITEM + " text not null, " + KEY_GROUP + " TEXT, " +
ITEM_CLASSIFICATION + " TEXT, " + KEY_USE + " TEXT, " +
KEY_ACTION + " TEXT, " + KEY_PROPERTIES + " TEXT, " +
KEY_ASSOCIATION + " TEXT," + KEY_IMG_ID + " INTEGER" + ");";
(note the space added before TEXT and INTEGER).
You are creating a string like:
...integer primary key autoincrement, item_name text not null, groupTEXT, classificationTEXT, useTEXT, actionTEXT, propertiesTEXT... (sic).
See the problem?
I was using "group" for on of my column names in my table. Apparently there is an issue with this. I am guessing that "group" is a reserved word for SQLite for android. so if anyone else runs into this issue try changing the column name. Hope this is helpful.
Well i been fighting with this all yesterday and today, i got a simple SQLite insert that keeps returning a -1 as a return value, i read somewhere to change the primary key name to _id but made no change.
so here are the snaps op the code.
My constants for the fields:
//BALLS TABLE
public static final String BALLS_TABLE = "balls";
public static final String BALL_ID = "id";
public static final String BALL_USERID = "userId";
public static final String BALL_MODEL = "model";
public static final String BALL_BRAND = "brand";
public static final String BALL_SERIAL = "serial";
public static final String BALL_NOTES = "notes";
public static final String BALL_IMAGE = "image";
then on my createTables(SQLiteDatabase db) i got
//BALLS TABLE
db.execSQL(
"create table " + BALLS_TABLE +" (" +
BALL_ID + " integer primary key autoincrement not null," +
BALL_USERID + "integer not null," +
BALL_MODEL + " text not null," +
BALL_BRAND + " text not null," +
BALL_SERIAL + " text not null," +
BALL_NOTES + " text not null," +
BALL_IMAGE + " blob" +
");");
the creation of tables is working as i got other tables that are been populated.
and finally the whole ball Helper class
package com.kegel.android.bowlermanager.data;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class BallHelper {
private SQLiteDatabase database;
private ArrayList<Ball> currentBalls;
private Context context;
public BallHelper(Context context,SQLiteDatabase database)
{
this.context = context;
this.database = database;
loadBalls();
}
public ArrayList<Ball> getCurrentBalls() {
return currentBalls;
}
public Boolean BallExists(long id)
{
for (Ball ball : currentBalls)
{
if (ball.getId() == id)
return true;
}
return false;
}
public Boolean BallExists(Ball u)
{
for (Ball ball : currentBalls)
{
if (ball.getId() == u.getId())
return true;
}
return false;
}
public void updateBall(Ball b) {
assert(null != b);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] by = null;
if (b.getImage() != null )
{
Bitmap bmp = b.getImage();
bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
by = baos.toByteArray();
}
ContentValues values = new ContentValues();
values.put(SQLiteOpenDataHelper.BALL_USERID, 1);
values.put(SQLiteOpenDataHelper.BALL_MODEL, b.getModel());
values.put(SQLiteOpenDataHelper.BALL_BRAND , b.getBrand());
values.put(SQLiteOpenDataHelper.BALL_SERIAL , b.getSerial());
values.put(SQLiteOpenDataHelper.BALL_NOTES, b.getNotes());
values.put(SQLiteOpenDataHelper.BALL_IMAGE , by);
if (b.isValid())
{
if (b.getId() == 0)
{
b.setId(database.insert(SQLiteOpenDataHelper.BALLS_TABLE, null, values));
}
else
{
long id = b.getId();
String where = String.format("%s = %d", SQLiteOpenDataHelper.BALL_ID, id);
database.update(SQLiteOpenDataHelper.BALLS_TABLE, values, where, null);
}
loadBalls();
}
}
public void deleteBalls(Long id) {
String where = String.format("%s in (%s)", SQLiteOpenDataHelper.BALL_ID, id);
database.delete(SQLiteOpenDataHelper.BALLS_TABLE, where, null);
loadBalls();
}
public void deleteBalls(Ball u) {
String where = String.format("%s in (%s)", SQLiteOpenDataHelper.BALL_ID, u.getId());
database.delete(SQLiteOpenDataHelper.BALLS_TABLE, where, null);
loadBalls();
}
private void loadBalls() {
byte[] img = null;
currentBalls = new ArrayList<Ball>();
//try
//{
Cursor ballsCursor = database.query(SQLiteOpenDataHelper.BALLS_TABLE, new String[] {SQLiteOpenDataHelper.BALL_ID,SQLiteOpenDataHelper.USER_ID, SQLiteOpenDataHelper.BALL_MODEL, SQLiteOpenDataHelper.BALL_BRAND, SQLiteOpenDataHelper.BALL_SERIAL, SQLiteOpenDataHelper.BALL_NOTES, SQLiteOpenDataHelper.BALL_IMAGE}, null, null, null, null, null);
ballsCursor.moveToFirst();
Ball b;
if (! ballsCursor.isAfterLast()) {
do {
long id = ballsCursor.getInt(0);
long bowlerId = ballsCursor.getLong(1);
String model = ballsCursor.getString(2);
String brand = ballsCursor.getString(3);
String serial = ballsCursor.getString(4);
String notes = ballsCursor.getString(5);
img = ballsCursor.getBlob(6);
Bitmap bmp=BitmapFactory.decodeByteArray(img,0,img.length);
b = new Ball(context,bowlerId,model,brand,serial,notes);
b.setId(id);
b.setImage(bmp);
currentBalls.add(b);
} while (ballsCursor.moveToNext());
}
ballsCursor.close();
}
}
A second pair of eyes here will come handy! so if anyone can spot anything here, or let me know if I'm missing something i will really appreciate it. I already checked the values on b ( is even passing my internal validation ) but and insertion like this will fail:
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.fake_pofile);
Ball ball = new Ball(this,1, "Test", "Test", "", "");
ball.setImage(bm);
mHelper.updateBall(ball);
Well... as i didn't, nobody else noted on the code for the table creation, between the field BALL_USERID i wasn't leaving a space so it was a whole word, funny thing that db.exec is supposed to throw exceptions but in this case didn't and accepted a strange name as a field with no type and created the table with no field "userId" but "useridinteger" with no type ( is there a default type if you don't set one?? )
Sometimes are just those litte things that can make you go nuts.
I know this is an old example, but for anyone looking for an Objective C sample, this is good. However, be sure to put the sqlite3_reset(statement) lines BEFORE the return statements. Otherwise, the code only works on the first save or find.