I have 3 classes.
One to setup the DB and tables, works fine. DBHelper.java
private static final String TAG = "DBHelper";
public static final String DB_NAME = "pat_test.db";
public static final String TABLE5 = "sites";
public static final String S_ID = BaseColumns._ID;
public static final String S_CLIENT = "client_of_site";
public static final String S_POSTCODE = "site_postode";
public static final String S_CON_NAME = "contact_name";
public static final String S_CON_NUM = "contact_tel_num";
public static final String S_NAME = "site_name";
public static final String S_LAST_TEST = "last_test_date";
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql5 = String.format("create table %s (%s INT PRIMARY KEY, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s INT, %s TEXT)",TABLE5, S_ID, S_CLIENT, S_NAME, S_POSTCODE, S_CON_NAME,S_CON_NUM,S_LAST_TEST);
Log.d(TAG, "onCreate: " + sql5);
db.execSQL(sql5);
}
The next one has my functions DBControl.java
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.provider.BaseColumns;
public class DBControl {
public static final String TABLE5 = "sites";
public static final String S_ID = BaseColumns._ID;
public static final String S_CLIENT = "client_of_site";
public static final String S_NAME = "site_name";
public static final String S_POSTCODE = "site_postode";
public static final String S_CON_NAME = "contact_name";
public static final String S_CON_NUM = "contact_tel_num";
public static final String S_LAST_TEST = "last_test_date";
private Context context;
private SQLiteDatabase database;
private DBHelper dbhelper;
public DBControl(Context context) {
this.context = context;
}
public DBControl open() throws SQLiteException {
dbhelper = new DBHelper(context);
database = dbhelper.getWritableDatabase();
return this;
}
public void close() {
dbhelper.close();
}
public ContentValues createContentValues3(String CLIENT,
String NAME, String POSTCODE, String CON_NAME,
long CON_NUM) {
ContentValues values = new ContentValues();
values.put(S_CLIENT, CLIENT);
values.put(S_POSTCODE, POSTCODE);
values.put(S_CON_NAME, CON_NAME);
values.put(S_CON_NUM, CON_NUM);
values.put(S_NAME, NAME);
return values;
}
public long addSiteDetails( String CLIENT, String NAME,
String POSTCODE, String CON_NAME, int CON_NUM ) {
ContentValues siteValues = createContentValues3( CLIENT, NAME,
POSTCODE, CON_NAME, CON_NUM );
return database.insert(TABLE5, null, siteValues);
}
public boolean updateSiteDetails(long id, String CLIENT, String NAME,
String POSTCODE, String CON_NAME , int CON_NUM
) {
ContentValues siteUpdateValues = createContentValues3( CLIENT, NAME,
POSTCODE, CON_NAME, CON_NUM);
return database.update(TABLE5, siteUpdateValues, S_ID + "=" + id, null) > 0;
}
}
public long fetchSiteIdByName(String NAME){
Cursor dbCursor;
long id = 0;
try {
dbCursor = database.query(true, TABLE5, new String []{S_ID}, S_NAME + "= " + NAME , null, null, null, null, null);
dbCursor.moveToFirst();
id = dbCursor.getLong(dbCursor.getColumnIndex(S_ID)); }
catch (SQLiteException e) {
id = -1;
}
return id;
}
My third class is used to call and check. But this is where my problem arises or in fetchSiteIdByName in the previous class.
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class activityStartNewTest extends Activity implements OnClickListener {
Button buttonBeginTesting;
private AutoCompleteTextView clientInput; //Refers to input box for client
private AutoCompleteTextView siteInput; //Refers to input box for site
private AutoCompleteTextView postcodeInput; //Refers to input box for postcode
private EditText nameInput; //Refers to input box for contact name
private EditText telInput; //Refers to input box for contact number
// private EditText jobrefInput; //Refers to input box for Job reference number
private DBControl dbControl;
@ Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_new_test);
dbControl = new DBControl(this);
clientInput = (AutoCompleteTextView) findViewById(R.id.autoCompleteClientNameEdit);
siteInput = (AutoCompleteTextView) findViewById(R.id.autoCompleteSiteNameEdit);
postcodeInput = (AutoCompleteTextView) findViewById(R.id.autoCompletePostcodeEdit);
nameInput = (EditText) findViewById(R.id.editTextContactName);
telInput = (EditText) findViewById(R.id.editTextContactNum);
// jobrefInput = (EditText)findViewById(R.id.editTextJobRef);
buttonBeginTesting = (Button) findViewById(R.id.buttonBeginTesting);
buttonBeginTesting.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void onClick(View arg) {
String clientData = clientInput.getText().toString();
String siteData = siteInput.getText().toString();
String postcodeData = postcodeInput.getText().toString();
String nameData = nameInput.getText().toString();
String telData = telInput.getText().toString();
// String jobrefData = jobrefInput.getText().toString();
Toast toastNotice = new Toast(this);
Dialog notice = new Dialog(this); // this needs the textview below for displaying
TextView msgBody = new TextView(this);
msgBody.setTextSize(20);
long tempValue = 0;
switch(arg.getId()){
case R.id.buttonBeginTesting:
try{
int telDataAsNum = Integer.parseInt(telData);
dbControl.open();
if((tempValue = dbControl.fetchSiteIdByName(siteData)) != -1) {
if(dbControl.updateSiteDetails(tempValue, clientData, siteData, postcodeData, nameData, telDataAsNum)){
notice.setTitle("Site Updated!");
msgBody.setText("Site detail have been updated instead");
}
else{
notice.setTitle("Update failed!");
msgBody.setText("Site already Exists, but failed!");
}
}
else{
long siteID = 0;
siteID = dbControl.addSiteDetails( clientData, siteData, postcodeData, nameData, telDataAsNum );
notice.setTitle("Site Added");
msgBody.setText("Site added at row "+ siteID);
}
dbControl.close();
}
catch (SQLiteException e){ // Notifies user if SQL error occurred
e.printStackTrace();
notice.setTitle("Insert failed");
msgBody.setText("SQL Error!");
}
catch (NumberFormatException e){ // Notifies user if NUM format error occurred
e.printStackTrace();
notice.setTitle("Insert failed");
msgBody.setText("Contact number must be a number!");
}
notice.setContentView(msgBody);
notice.show();
}
}
}
Now when I run the application I insert into the DB with new details absolutley fine. Using adb I pull the DB and open in sqlite3. It shows all entries with NULL in the first column and NULL in the last (the last has not been posted yet). I use the same text in the field of the editbox siteData and it just adds a new entry and does not update the previous.
The log cat is showing SQLiteLog (1) no such column: xxx where xxx would have been the entry into the autocompleteTextView.
Why is it looking for a column named to whatever text was input?
Surrounding the NAME in fetchSiteIdByName() with single quotes might help.
dbCursor = database.query(true, TABLE5, new String []{S_ID}, S_NAME + "= '" + NAME + "'" , null, null, null, null, null);
I'm not much sure if it will work on SQLite but I've been through same kind of issues in MySQL and it helps. Moreover, when you fetch non-numeric values in the database you surround them in single quotes.
Hope it helps. :)
It appears I had 3 different issues but using Lokesh's links and post's help me get a fix.
I modified the SQL string in DBelper.java to this
String sql5 = String.format("create table %s (%s INTEGER PRIMARY KEY **AUTOINCREMENT**, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s INT, %s TEXT)",
TABLE5, S_ID, S_CLIENT, S_NAME, S_POSTCODE, S_CON_NAME,
S_CON_NUM, S_LAST_TEST);
And added to the DBControl.java class
**if**(dbCursor.moveToFirst()) id = dbCursor.getLong(dbCursor.getColumnIndex(S_ID));
Dropping the semicolon after the moveToFirst()). Like I said I'm a real noob but believe this to be correct.
Adding the AUTOINCREMENT had 1 dramatic effect when I uninstalled and reinstalled the application (I could have changed the DB version instead, if I wanted too, I know).
When the Tables were rebuilt they did not have the column _id I had seen before. So I think the SQL string was the reason for my failure. I'm sure I heard somewhere it wasn't required for PRIMARY KEY basecolumns._ID but now I know IT IS.
Thanks Lokesh for your pointers. I couldn't have found the issue without some guidance and I really appreciate it.
I tried to add to the up arrow but don't have enough rating yet. Doh.
Hope this helps others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With