How to Insert a value where not exist in SQLite Android - java

I want to insert values into my table only when values don't exist in the table.
String CREATETABLE = "CREATE TABLE contacts ( " +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT, "+
"phone TEXT )";
Here is my code to create the table, I used UNIQUE(phone), and it doesn't work.
And to add a new contact I am using this code:
ContentValues values = new ContentValues();
values.put("name", contact.getName()); // get title
values.put("phone", contact.getNumero()); // get author
// 3. insert
db.insert("contacts", // table
null, //nullColumnHack
values);

I don't think there is a way of doing that without retrieving the row first. You query the database looking for that particular contact (which you have to specify at least one column to be unique, or any combination of columns to be primary key) otherwise how would you handle two person with the same name?.
So you query and search for the desired person, if you find it, check if the column is null and a) insert if it is, b) ignore if it isn't. If the query doesn't find any person, you cant just insert.
About the unique constraint, its like this:
String CREATETABLE = "CREATE TABLE contacts ( " +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT, " +
"phone TEXT UNIQUE)";

In your sample you are using SQLiteDatabase.insert(), try to use SQLiteDatabase.insertWithOnConflict() with one of values CONFLICT_IGNORE, CONFLICT_REPLACE or others.
Also have a look about implementing database as ContentProvider which is much harder to understand but really good to know.

Related

I'm trying to create a customize id or unique id like SID0000001, but there's an error: '(' , ')', <column constraint> or comma expected, got'+'

So this is were the error occur on CON_SID + "AS 'SID' + RIGHT('000000' + CAST(ID AS VARCHAR(6)),6)PERSISTED);";
#Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + TBL_Name +
" ("+ CON_ID + "INT IDENTITY(1,1) NOT NULL PRIMARY KEY AUTOINCREMENT, "+
CON_Name + " TEXT, " +
CON_Address + " TEXT, " +
CON_BDay + " TEXT, " +
CON_Gender + " TEXT, " +
CON_Course + " TEXT, " +
CON_SID + "AS 'SID' + RIGHT('000000' + CAST(ID AS VARCHAR(6)),6)PERSISTED);";
db.execSQL(query);
}
You cannot use MYSQL's dialect of SQL. However, you could mimic the result by utilising a TRIGGER (not that you need to - explained below) for example :-
First create the table (names based upon your question) e.g. :-
CREATE TABLE IF NOT EXISTS example (
id INTEGER PRIMARY KEY,
name TEXT,
address TEXT,
bday TEXT,
gender TEXT,
course TEXT,
sid TEXT UNIQUE
);
note AUTOINCREMENT dropped, see link
Then add the TRIGGER using :-
CREATE TRIGGER IF NOT EXISTS example_after_insert AFTER INSERT ON example
BEGIN
UPDATE example SET sid = 'SID'||substr('000000',1,6-length(id))||id WHERE id = new.id;
END
;
The SID would then be generated whenever a row is inserted. For example :-
/* INSERT rows where id column is generated by SQLite */
INSERT INTO example (name,address,bday,gender,course) VALUES
('name1','addr1','bday1','female','course1'),
('name2','addr2','bday2','male','course2'),
('name3','addr3','bday3','female','course3')
;
/* INSERT rows with specific ID's to test values */
INSERT INTO example (id,name,address,bday,gender,course) VALUES
(15,'name1','addr1','bday1','female','course1'),
(135,'name2','addr2','bday2','male','course2'),
(1234,'name3','addr3','bday3','female','course3'),
(98765,'name3','addr3','bday3','female','course3'),
(999999,'name3','addr3','bday3','female','course3'),
(9999999,'name3','addr3','bday3','female','course3') /* overflow */
;
Using SELECT * FROM example; then shows :-
Not that you need to
You could achieve the same result without the trigger by simply generating the column when needed.
This approach would afford the following benefits
reduce the storage space required
reduce the processing required when inserting a row
no extra column
no trigger and update
no additional index conflict checking
conform better with normalisation (not duplicating data)
For example to get the same result without accessing the sid column (i.e. showing that it's not needed) you could use (the generated column has been named schoolID ):-
SELECT
id,
name,
address,
bday,
gender,
course,
'SID'||substr('000000',1,6-length(id))||id AS schoolID
FROM example;
The result :-

Prepared Statement Primary Key store seed 1 and increment

Okay, so I just started JDBC with derby client and I'm kind of new with it.
I set column ID as primary key with int as it's data type. However, I'm not sure if I should include myStatement.setString(1, ?); because I thought it should Auto Increment but it looks like it's not doing it.
Here's my Grab file details:
create table "ADMIN1".STUDENTPERSONALDETAILS
(
ID INTEGER not null primary key,
STUDENTID VARCHAR(10) not null,
LASTNAME VARCHAR(50) not null,
FIRSTNAME VARCHAR(50) not null,
MIDDLENAME VARCHAR(50) not null,
PLACEOFBIRTH VARCHAR(200) not null,
DOB VARCHAR(50) not null,
GENDER VARCHAR(4) not null,
CIVILSTATUS VARCHAR(7) not null,
RELIGION VARCHAR(15) not null,
NATIONALITY VARCHAR(20) not null
)
How can I correct my PreparedStatement or My Table in such a way that adding of value for column ID will be automatic so that I can start setString(2, studentID) and avoid getting error about the number of columns not matching with what was supplied?
Here's my code:
addButton.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
try {
String myDbUrl = "jdbc:derby://localhost:1527/Enrollment"; //stores url to string
String userName = "admin1";
String Password = "admin1";
Connection myDBConnection = DriverManager.getConnection(myDbUrl, userName, Password);
String myQuery = "INSERT INTO STUDENTPERSONALDETAILS"
+ "(STUDENTID,LASTNAME,FIRSTNAME,MIDDLENAME,PLACEOFBIRTH,DOB,GENDER,CIVILSTATUS,RELIGION,NATIONALITY) "
+ "VALUES(?,?,?,?,?,?,?,?,?,?) ";
String adminissionNo ;
String studentID = tfStudentId.getText().toString();
String lastName = tfLastName.getText().toString();
String firstName = tfFirstName.getText().toString();
String middleName = tfMiddleName.getText().toString();
String placeOfBirth = tfPob.getText().toString();
String dateOfBirth = listDOB.getSelectedItem().toString();
String gender = listGender.getSelectedItem().toString();
String civilStatus = listCivilStatus.getSelectedItem().toString();
String religion = listReligion.getSelectedItem().toString();
String nationality = listNationality.getSelectedItem().toString();
PreparedStatement myStatement = myDBConnection.prepareStatement(myQuery);
myStatement.setString(2, lastName);
myStatement.setString(3, firstName);
myStatement.setString(4, middleName);
myStatement.setString(5, placeOfBirth);
myStatement.setString(6, dateOfBirth);
myStatement.setString(7, gender);
myStatement.setString(8, civilStatus);
myStatement.setString(9, religion);
myStatement.setString(10, nationality);
boolean insertResult = myStatement.execute();
if(insertResult == true)
JOptionPane.showMessageDialog(null, "Successfully Added Information");
else
JOptionPane.showMessageDialog(null, "Encountered an error while inserting data");
}
catch(SQLException ex) {
JOptionPane.showMessageDialog(null, ex.toString());
}
}
});
Is it necessary to include myStatement.setString(1, integervaluehere) for Primary Keys? Isn't it supposed to autoincrement?
I'd appreciate any explanation because I just started learning the basics of PreparedStatements recently.
I tried counting the columns and tried 10 and 11 lines of myStatement.setString(), but still can't get it to insert data because of mismatch.
Thanks in advance.
You need to mention 'auto increment' explicitly.
Or you can write your own java code to track the Id for each table and whenever you ask the method to give the ID it will return lastID + 1.
But, I think now you can go with auto_increment option.
If you want it to autoincrement you need to say so in the column definition, and you haven't.
I don't know what 'default 1' in your title is supposed to mean, as you haven't mentioned it in your question, but you can't have a default value and autoincrement. It doesn't make sense.
I don't know what 'store seed 1' means either, in your edit.
When you have a column with a default value you want to rely on, or autoincrement, you don't mention it at all in the INSERT statement, so there is no positional argument to set.
First, set the primary identifier column to autoincrement. Since your query already excludes the primary key, you then only have to change the PreparedStatement indexes to match the number of parameters in your query starting from one.
Since you have 10 columns in addition to the primary ID column, your PreparedStatement might look something like the following:
PreparedStatement myStatement = myDBConnection.prepareStatement(myQuery);
myStatement.setString(1, studentId);
myStatement.setString(2, lastName);
myStatement.setString(3, firstName);
myStatement.setString(4, middleName);
myStatement.setString(5, placeOfBirth);
myStatement.setString(6, dateOfBirth);
myStatement.setString(7, gender);
myStatement.setString(8, civilStatus);
myStatement.setString(9, religion);
myStatement.setString(10, nationality);
Note that you do not need to have the instruction, myStatement.setInt(1, primaryId);, once you have changed the primary key in your table to auto-increment. However, if you elect to keep the primary key as non-autoincrementing, then you must explicitly specify the primary key value and provide a parameter in your query to insert that data.
If you're using MySQL Workbench, which if you're not, I highly recommend because it just works. You have to choose Auto-Increment as a characteristic of that column. If you want your column to auto increment, when creating columns in your database, check the option Auto-Increment, sometimes written as AI.

Insert into table with autoincrement primary key

I'm creating a table as follows:
#Override
public void onCreate(SQLiteDatabase db) {
String sql =
"CREATE TABLE IF NOT EXISTS users (" +
"_id INTEGER PRIMARY KEY, " +
"name TEXT NOT NULL, " +
"password TEXT NOT NULL);";
db.execSQL(sql);
sql = "INSERT INTO users VALUES ('testuser', 'textpassword')";
db.execSQL(sql);
}
But when I try to insert a user, I'm getting the following exception:
android.database.sqlite.SQLiteException: table users has 3 columns but 2 values were supplied (code 1): , while compiling: INSERT INTO users VALUES ('testuser', 'textpassword')
As _id is the primarykey, why is it expecting it? I also tried AUTOINCREMENT but it doesn't work.
Try this
#Override
public void onCreate(SQLiteDatabase db) {
String sql =
"CREATE TABLE IF NOT EXISTS users (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
"name TEXT NOT NULL, " +
"password TEXT NOT NULL);";
db.execSQL(sql);
sql = "INSERT INTO users(name, password) VALUES ('testuser', 'textpassword')";
db.execSQL(sql);
}
AUTOINCREMENT NOT NULL is missing in your insert query which will increase the value of _id field automatically.
You should specify the values you're inserting:
sql = "INSERT INTO users(name, password) VALUES ('testuser', 'textpassword')";
There's no need to specify AUTOINCREMENT: On an INSERT, if the ROWID or INTEGER PRIMARY KEY column is not explicitly given a value, then it will be filled automatically with an unused integer, usually one more than the largest ROWID currently in use. This is true regardless of whether or not the AUTOINCREMENT keyword is used.

Letting Android choose the next SQLITE _ID

Somewhere in my code I do this:
contentValues = new ContentValues();
// contentValues.put("_ID",BaseColumns._ID); // Not Working can someone explain what this is and how it's used BaseColumns._ID ?
contentValues.put("_ID", null); // Not working, Everywhere they say to pass in a null value and Android will do it's magic ...
contentValues.put("_ID", "1") // This works but has to be changed manually every time
contentValues.put("login", username.getText().toString());
contentValues.put("password", pwd.getText().toString());
contentValues.put("type", type);
This is my small schema:
public static final String CREATE_DATABASE = "CREATE TABLE "+
TABLE +"(_ID INTEGER PRIMARY KEY AUTOINCREMENT, login VARCHAR(50) NOT NULL, password VARCHAR(50) NOT NULL, type CHAR(1) NOT NULL)";
Some people say not to put AUTOINCREMENT, but in some other websites you can see it in the code. I'm not sure what to do anymore.
How do I get Android to choose the next increment value ?
Using autoincrement will auto assign an ID to any new row inserted into the database
You do not need to call contentValues.put("_ID", null); or even access the column in any way when you insert something into the database, it is done automatically

Reset the row number count in an android DataBase

I need to reset the row number count to 1.
How can I do that?
An example for an update query in my code:
public boolean update (long rowId, String title, String body, String reminderDateTime, String loca, String type, String settime, String lat, String llong) {
ContentValues args = new ContentValues();
args.put(KEY_TITLE, title);
args.put(KEY_BODY, body);
args.put(KEY_DATE_TIME, reminderDateTime);
args.put(KEY_LOCATION, loca);
args.put(KEY_TYPE, type);
args.put(KEY_SETTIME, settime);
args.put(KEY_LAT, lat);
args.put(KEY_LONG, llong);
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
I tried to do that but the eclipse showing me an error:"sqlite_sequence cannot be resolved to a variable"
public void resetAutoNumbering ()
{
mDb.update(sqlite_sequence, args, KEY_ROWID + "=" + rowId, null);
}
What can I do and how?
Found this as answer for a similar question SQLite Reset Primary Key Field:
delete from your_table;
delete from sqlite_sequence where name='your_table';
SQLite Autoincrement
SQLite keeps track of the largest ROWID that a table has ever held using the special SQLITE_SEQUENCE table. The SQLITE_SEQUENCE table is created and initialized automatically whenever a normal table that contains an AUTOINCREMENT column is created. The content of the SQLITE_SEQUENCE table can be modified using ordinary UPDATE, INSERT, and DELETE statements. But making modifications to this table will likely perturb the AUTOINCREMENT key generation algorithm. Make sure you know what you are doing before you undertake such changes.
-axel
You use sqlite_sequence in your procedure but before this you used DATABASE_TABLE instead of sqlite_sequence. Change your sqlite_sequence to DATABASE_TABLE.

Categories