Copy values from one table to another with 'where' condition - java

I want to copy values from songDetails table to playlistDetails table.
here is my code :
public void transferData(String name) {
SQLiteDatabase db = this.getWritableDatabase();
String selectQuery = "INSERT INTO "+ TABLE_CURRENTLIST + " SELECT * FROM " + TABLE_DATA + " WHERE " + KEY_ALBUMNAME+ " = " + name + "";
db.execSQL(selectQuery);
}
While executing this code, it throws this exception
01-31 01:29:49.426: E/AndroidRuntime(3102): android.database.sqlite.SQLiteException: no such column: unknown (code 1): , while compiling: INSERT INTO PlayListDetails SELECT * FROM songDetails WHERE albumName = unknown
the value of 'name' variable is correct. And i want to copy only the rows which have the albumName as unknown.
I'm struggled with this. Please help me.

You are missing single quotes around query param value (unknown).
Your query should be
String selectQuery = "INSERT INTO "+ TABLE_CURRENTLIST + " SELECT * FROM " + TABLE_DATA + " WHERE " + KEY_ALBUMNAME+ " = '" + name + "'";
My suggestion would be to use PreparedStatement style parameters.

Related

How can I use this query with the query method (SQLiteDatabase.query)?

The task I've been given is to write a query to return the number of orphaned rows. I have achieved this but another task is to then not use the rawQuery method to achieve the same result using the query method.
The issue is that I get java.lang.IllegalStateException: Invalid tables
The tables, there are 3 are
the parent table which has an _id column and a name column
the child table which has an _id column, a name column and a childtoparentlink column that is an integer that links to the parent table.
the friend table which has an _id column, a name column and a friendtochildlink column.
The SQL to create and to put rows into the tables, including some orphans is like
CREATE TABLE parent(_id INTEGER PRIMARY KEY,parentname TEXT);
CREATE TABLE child(_id INTEGER PRIMARY KEY,childname TEXT, childtoparentlink INTEGER);
CREATE TABLE friend(_id INTEGER PRIMARY KEY,friendname TEXT, friendtochildlink INTEGER);
INSERT INTO parent VALUES(null,'Parent A');
INSERT INTO parent VALUES(null,'Parent B');
INSERT INTO child VALUES(null,'Child A',1);
INSERT INTO child VALUES(null,'Child B',2);
INSERT INTO child VALUES(null,'Child X',10); -- orphan
INSERT INTO friend VALUES(null,'Friend A',1);
INSERT INTO friend VALUES(null,'Friend B',2);
INSERT INTO friend VALUES(null,'Friend X',100); -- orphan
The query that works and gives the right values when using rawQuery is
SELECT
(
SELECT count() FROM child
LEFT JOIN parent ON child.childtoparentlink = parent._id
WHERE parent.parentname IS NULL
) AS child_mismatches,
(
SELECT count() FROM friend
LEFT JOIN child ON friend.friendtochildlink = child._id
WHERE child.childname IS NULL
) AS friend_mismatches
I get two columns each with a value of 1 (as wanted).
My actual code is :-
public ArrayList<String> checkLinkIntegrity() {
ArrayList<String> return_value = new ArrayList<>();
String suffix = "_mismatches";
String child_result_cl = TB_CHILD + suffix;
String sq_child_mismatches = "(SELECT count() FROM " +
TB_CHILD +
" LEFT JOIN " + TB_PARENT +
" ON " + TB_CHILD + "." + CL_CHILDTOPARENTLINK + " = " +
TB_PARENT + "." + CL_PARENTID +
" WHERE " + TB_PARENT + "." + CL_PARENTNAME + " IS NULL)" +
" AS " + child_result_cl;
String friend_result_cl = TB_FRIEND + suffix;
String sq_friend_mismatches = "(SELECT count() FROM " +
TB_FRIEND +
" LEFT JOIN " + TB_CHILD +
" ON " + TB_FRIEND + "." + CL_FRIENDTOCHILDLINK + " = " +
TB_CHILD + "." + CL_CHILD_ID +
" WHERE " + TB_CHILD + "." + CL_CHILDNAME + " IS NULL)" +
" AS " + friend_result_cl;
String full_query = "SELECT " + sq_child_mismatches + "," + sq_friend_mismatches;
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr;
Log.d("RAWQUERYSQL",full_query);
csr = db.rawQuery(full_query,null);
return_value.addAll(dumpCursorToStringArrayList(csr,"RAWQUERY"));
// Fails invalid table
csr = db.query(null,new String[]{sq_child_mismatches,sq_friend_mismatches},null,null,null,null,null);
return_value.addAll(dumpCursorToStringArrayList(csr,"SECONDTRY"));
csr.close();
return return_value;
}
and the dumpCursortoStringArrayList method is :-
private ArrayList<String> dumpCursorToStringArrayList(Cursor csr, String tablename) {
ArrayList<String> rv = new ArrayList<>();
int original_position = csr.getPosition();
csr.moveToPosition(-1);
rv.add("Table: " + tablename);
while (csr.moveToNext()) {
rv.add("\tRow # " + String.valueOf(csr.getPosition() + 1));
for (String column: csr.getColumnNames()) {
rv.add("\t\tColumn: " + column + "\tvalue is: \t" + csr.getString(csr.getColumnIndex(column)));
}
}
csr.moveToPosition(original_position);
return rv;
}
I get the same error if I try "" instead of null e.g.
If I use only the rawQuery I get
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS: Table: RAWQUERY
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS: Row # 1
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS: Column: child_mismatches value is: 1
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS: Column: friend_mismatches value is: 1
This is from using
ArrayList<String> results = DBOpenHelper.checkLinkIntegrity();
for (String s : results) {
Log.i("RESULTS",s);
}
How can I run the query with the query method instead of the rawQuery method, to get the better marks?
Your issue is that the query method expects a table as it then generates SQL as per
SELECT your_columns FROM the_table;
As there is no table it issues the Invalid Table exception.
You have to provide something that will satisfy the FROM clause, it cannot be nothing.
You can get around this in a few ways, which I guess is what the homework is trying to get you to ascertain/explore.
Fix 1
You could supply one of the tables that exist e.g. use
csr = db.query(null,new String[]{sq_child_mismatches,sq_friend_mismatches},null,null,null,null,null,"1");
Note the 8th parameter, this LIMITs the number of rows generated to one as there would be a row generated for each row in the fake table.
Fix 2
or as FROM can be a subquery (see diagram) you could use a subquery e.g. one that you have
So you could use :-
csr = db.query(
sq_child_mismatches, //<<<<<<<<<< the fake subquery
new String[]{
sq_child_mismatches,
sq_friend_mismatches
},
null ,null,null,null,null
);
In this case, as the fake subquery returns a single row/result, there is no need for the LIMIT clause.

sqlite fetching data using foreign key: Cannot bind argument at index 1 because the index is out of range. The statement has 0 parameters

I am trying to fetch a record from the sqlite database in Android, and having trouble. It often throws java.lang.IllegalArgumentException and gives me the same message.
mListSongs = mSongDao.getSelectedSongs(artist_id);
public List<Song> getSelectedSongs(Long artistId) {
List<Song> listSongs = new ArrayList<Song>();
String selectQuery = "SELECT " + DBHelper.SONG_PATH + " FROM " + DBHelper.TABLE_SONG + " s, "
+ DBHelper.TABLE_ARTIST + " a WHERE s."
+ DBHelper.SONG_ID + " = a.'" + DBHelper.ARTIST_ID + "'";
String[] selectionArgs = new String[]{String.valueOf(artistId)};
Cursor cursor;
cursor = mDatabase.rawQuery(selectQuery, selectionArgs);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Song song = cursorToSelectSong(cursor);
listSongs.add(song);
cursor.moveToNext();
}
cursor.close();
return listSongs;
}
private Song cursorToSelectSong(Cursor cursor) {Song song = new Song(); song.setmSong_path(cursor.getString(3)); return song;}
The issue is that you are supplying an argument, as per String[] selectionArgs = new String[]{String.valueOf(artistId)}; and then cursor = mDatabase.rawQuery(selectQuery, selectionArgs); but that the statement (the SELECT statement) has no place-holder (an ?) within it.
So you have 1 argument but the statement has 0 parameters to substitute the argument for.
Changing :-
String selectQuery = "SELECT " + DBHelper.SONG_PATH + " FROM " + DBHelper.TABLE_SONG + " s, "
+ DBHelper.TABLE_ARTIST + " a WHERE s."
+ DBHelper.SONG_ID + " = a.'" + DBHelper.ARTIST_ID + "'";
to :-
String selectQuery = "SELECT " + DBHelper.SONG_PATH + " FROM " + DBHelper.TABLE_SONG + " s, "
+ DBHelper.TABLE_ARTIST + " a WHERE s."
+ DBHelper.SONG_ID + "=?";
Introduces the parameter and it, the ?, will be substituted for the artist_id passed to the method.
Alternately using :-
String selectQuery = "SELECT " + DBHelper.SONG_PATH + " FROM " + DBHelper.TABLE_SONG + " s, "
+ DBHelper.TABLE_ARTIST + " a WHERE s."
+ DBHelper.SONG_ID + " =" + String.valueOf(artist_id);
along with :-
cursor = mDatabase.rawQuery(selectQuery, null);
would also work BUT is open to SQL injection (but not really as it's a long that has been passed, which cannot be a String that could contain dangerous SQL).
i.e. no arguments are passed into rawQuery and therefore there is no expectation that the statement should contain a parameter place-holder (?).
However, there is no need to JOIN the ARTIST table as the SONG table has the ARTIST_ID column.
You'd only need the JOIN if you wanted other details about the ARTIST e.g. artist name (which you probably already know as you've ascertained the ARTIST_ID when invoking the method).
As such the simplified :-
String selectQuery = "SELECT " + DBHelper.SONG_PATH + " FROM " + DBHelper.TABLE_SONG + " WHERE " + DBHelper.SONG_ID + "=?";
would suffice.
Regarding Cursor issues I'd suggest trying :-
cursor = mDatabase.rawQuery(selectQuery, selectionArgs);
DatabaseUtils.dumpCursor(cursor); //<<<<<<<<<< will output the contents of the cursor to the log
while(cursor.moveToNext()) {
String songpath = cursor.getString(cursor.getColumnIndex(DBHelper.SONG_PATH));
Log.d("EXTRACTEDPATH", "Extracted PATH " + songpath); //<<<<<<<<<< output extracted path to the log
Song newsong = new Song();
newsong.setmSong_path(songpath);
listSongs.add(newsong);
}
cursor.close();
return listSongs;
}
Dumps the Cursor immediately after it is retrieved
Uses simpler loop
Uses column name to derive the column offset
outputs the data from the column (if it shows path in log, but you still get empty path in list then it's either setmSong_path that is wrong or how you are getting data from the List.)
I think you want to fetch a list of songs by an artist, providing the artistId.
I believe that in in each row of the songs table DBHelper.TABLE_SONG there is a column for the id of the artist. If there isn't it should be.
Change your sql statement to this:
String selectQuery = "SELECT " + DBHelper.SONG_PATH + " FROM " + DBHelper.TABLE_SONG + " WHERE " + DBHelper.ARTIST_ID + " = ?";
As I said there must be a column DBHelper.ARTIST_ID or similar to identify the artist of each song.
The ? is the 1 parameter and its value will be artistId.

Android - SQLiteException: near "=": syntax error (code 1)

I am trying to log id from users table and jobname from jobs table using user id
String select = "SELECT jobname FROM " + TABLE_JOBS+ "where userid =" +myid;
"SELECT jobname FROM " + TABLE_JOBS+ "where userid =" +myid;
You need whitespace between identifiers such as your table name and keywords such as where:
"SELECT jobname FROM " + TABLE_JOBS+ " where userid =" +myid;
You're missing a whitespace before the where clause, so it gets appended directly to the table name, and you effectively don't have a where clause:
String select = "SELECT jobname FROM " + TABLE_JOBS+ " where userid =" +myid;
// whitespace was missing here -----------------------^

Condition on resultset of a select that return null or not null values-Java

For an application,I am checking if a table is filled so that I can retrieve that from it; otherwise I will retrive from another table. For that, I use a select and checks if it has null values by wasnull(). If it does, I execute a query; otherwise, I execute a differet query. The problem that I have is when it is null, it does not execute the query but returns null values !
Can you please show me what I am doing wrong or a better solution ?
Here is my code:
String reqEx = "SELECT PYE_DATEDEBUT,PYE_DATEFIN FROM PGEXCEPTPRESENCE WHERE PYE_SALARIE='"+chaine+"' ";
ResultSet rs = stmt.executeQuery(reqEx);
if (rs.wasNull()) {
req = " select jour.PJO_HORDEBPLAGE1,jour.PJO_HORFINPLAGE1,jour.PJO_HORDEBPLAGE2,jour.PJO_HORFINPLAGE2"
+ " from profilpressalarie propressal join profilpresence propres on propressal.ppz_profilpres = propres.ppq_profilpres "
+ "join modelecycle modcyc on propres.PPQ_CYCLEAFFECT = modcyc.PMO_MODELECYCLE join JOURNEETYPE jour " +
" on modcyc.PMO_JOURNEETYPE= jour.PJO_JOURNEETYPE where modcyc.PMO_ORDREJOUR='"+orderJ+"' " +
" and propressal.PPZ_salarie= '"+chaine+"'";
}
else{
while(rs.next()){
req = " select jour.PJO_HORDEBPLAGE1,jour.PJO_HORFINPLAGE1,jour.PJO_HORDEBPLAGE2,jour.PJO_HORFINPLAGE2"
+ " from PGEXCEPTPRESENCE exc join profilpresence propres on exc.PYE_CYCLEAFFECT = propres.ppq_profilpres join modelecycle modcyc " +
"on propres.PPQ_CYCLEAFFECT = modcyc.PMO_MODELECYCLE join JOURNEETYPE jour " +
"on modcyc.PMO_JOURNEETYPE= jour.PJO_JOURNEETYPE where modcyc.PMO_ORDREJOUR='"+orderJ+"' " +
"and exc.PYE_SALARIE= '"+chaine+"' ";
}}
rs.wasNull() is meant to be used for verifying the last read column is NULL or not. If your table's first column is a primitive data type like int it will not return NULL. So in this case you need to verify if the query returns any row or not. For this please use the following if condition:
if (!rs.next()) {
req = " select jour.PJO_HORDEBPLAGE1,jour.PJO_HORFINPLAGE1,jour.PJO_HORDEBPLAGE2,jour.PJO_HORFINPLAGE2"
+ " from profilpressalarie propressal join profilpresence propres on propressal.ppz_profilpres = propres.ppq_profilpres "
+ "join modelecycle modcyc on propres.PPQ_CYCLEAFFECT = modcyc.PMO_MODELECYCLE join JOURNEETYPE jour " +
" on modcyc.PMO_JOURNEETYPE= jour.PJO_JOURNEETYPE where modcyc.PMO_ORDREJOUR='"+orderJ+"' " +
" and propressal.PPZ_salarie= '"+chaine+"'";
}

Updating SQL Table with Java

I am developing an application that can update my database... However, I can't get my Java method working correctly. It gives me the following error: Must declare the scalar variable "#P0WHERE". Any suggestions?
The method I am using:
public void updateTable() throws SQLException
{
Scanner input = new Scanner(System.in);
System.out.println("Update the following:\n" + this);
this.getReservationInfo(input);
DataConnection connection = new DataConnection();
String query = "UPDATE " + TableName;
query += "Set Name = ?";
query += "WHERE Person_ID = " + id;
connection.updateData(query, person_name);
connection.closeConnection();
}
Add spaces before 'SET' and 'WHERE', otherwise it will not work.
String query = "UPDATE " + TableName;
query += " SET Name = ?";
query += " , Age = ?";
query += " , Col1 = ?"; //And other cols
query += " WHERE Person_ID = " + id;
EDIT: Changed query to update multiple columns.
I think so. You seem to be missing spaces. After the TableName and after the ?.
String query = "UPDATE " + TableName;
query += " Set Name = ?"; // tableSet not good, and
// ?WHERE is not valid add spaces.
query += " WHERE Person_ID = " + id;

Categories