How can we rename column name in ORMLite?
I am trying to write that query SELECT id as _id from some_table
Android Cursor Adapter requires us to have column named _id and ORMLite requires us to have column named id.
I am trying to write that query and return Cursor from this query.
Dao<NewsArticle, Long> newsArticleDao =
((SomeApp)mContext.getApplicationContext()).getDAOConnection().getDAO(
NewsArticle.class);
QueryBuilder<NewsArticle, Long> query = newsArticleDao.queryBuilder().selectRaw(
"`id` as `_id`");
PreparedQuery<NewsArticle> preparedQuery = query.prepare();
CloseableIterator<NewsArticle> iterator = newsArticleDao.iterator(preparedQuery);
AndroidDatabaseResults results =
(AndroidDatabaseResults)iterator.getRawResults();
cursor = results.getRawCursor();
That's what I have so far but I am getting this error when I pass query to iterator.
java.sql.SQLException: Could not compile this SELECT_RAW statement since the caller is expecting a SELECT statement. Check your QueryBuilder methods.
I guess I have to answer my question.
I still couldn't figure out how to rename column but I found the solution to problem.
Android Custom Adapter requires column named_id that's true but ORMLite doesn't require the column name to be id, I was wrong about that. It wants you to mark a column as id.
In my model, I marked my id and now it works like a charm.
#DatabaseField(id = true)
private long _id;
How can we rename column name in ORMLite?
Not sure I understand what you mean by rename. I don't think you mean schema change here. Are you talking about how to assign the name of the field in the database? You can do:
#DatabaseField(id = true, columnName = "_id")
private long id;
ORMLite requires us to have column named id.
Uh, no. ORMLite shouldn't care what the name of your column is. Maybe you are talking about Android?
I am trying to write that query and return Cursor from this query.
Is this is a different question?
java.sql.SQLException: Could not compile this SELECT_RAW statement since the caller is expecting a SELECT statement. Check your QueryBuilder methods.
You are getting this because you are calling:
newsArticleDao.queryBuilder().selectRaw(...);
And then calling:
query.prepare();
To quote from the javadocs of selectRaw(...)
... This will turn the query into something only suitable for the Dao.queryRaw(String, String...) type of statement.
I think you want to assign the name of your column using columnName. Have you looked at the javadocs for #DatabaseField? Or maybe look up "column name" in the online manual?
Related
Question: Is it possible to use a variable as your table name without having to use string constructors to do so?
Info:
I'm working on a project right now that catalogs data from a star simulation of mine. To do so I'm loading all the data into a sqlite database. It's working pretty well, but I've decided to add a lot more flexibility, efficiency, and usability to my db. I plan on later adding planetoids to the simulation, and wanted to have a table for each star. This way I wouldn't have to query a table of 20m some planetoids for the 1-4k in each solar system.
I've been told using string constructors is bad because it leaves me vulnerable to a SQL injection attack. While that isn't a big deal here as I'm the only person with access to these dbs, I would like to follow best practices. And also this way if I do a project with a similar situation where it is open to the public, I know what to do.
Currently I'm doing this:
cursor.execute("CREATE TABLE StarFrame"+self.name+" (etc etc)")
This works, but I would like to do something more like:
cursor.execute("CREATE TABLE StarFrame(?) (etc etc)",self.name)
though I understand that this would probably be impossible. though I would settle for something like
cursor.execute("CREATE TABLE (?) (etc etc)",self.name)
If this is not at all possible, I'll accept that answer, but if anyone knows a way to do this, do tell. :)
I'm coding in python.
Unfortunately, tables can't be the target of parameter substitution (I didn't find any definitive source, but I have seen it on a few web forums).
If you are worried about injection (you probably should be), you can write a function that cleans the string before passing it. Since you are looking for just a table name, you should be safe just accepting alphanumerics, stripping out all punctuation, such as )(][;, and whitespace. Basically, just keep A-Z a-z 0-9.
def scrub(table_name):
return ''.join( chr for chr in table_name if chr.isalnum() )
scrub('); drop tables --') # returns 'droptables'
For people searching for a way to make the table as a variable, I got this from another reply to same question here:
It said the following and it works. It's all quoted from mhawke:
You can't use parameter substitution for the table name. You need to add the table name to the query string yourself. Something like this:
query = 'SELECT * FROM {}'.format(table)
c.execute(query)
One thing to be mindful of is the source of the value for the table name. If that comes from an untrusted source, e.g. a user, then you need to validate the table name to avoid potential SQL injection attacks. One way might be to construct a parameterised query that looks up the table name from the DB catalogue:
import sqlite3
def exists_table(db, name):
query = "SELECT 1 FROM sqlite_master WHERE type='table' and name = ?"
return db.execute(query, (name,)).fetchone() is not None
I wouldn't separate the data into more than one table. If you create an index on the star column, you won't have any problem efficiently accessing the data.
Try with string formatting:
sql_cmd = '''CREATE TABLE {}(id, column1, column2, column2)'''.format(
'table_name')
db.execute(sql_cmd)
Replace 'table_name' with your desire.
To avoid hard-coding table names, I've used:
table = "sometable"
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS {} (
importantdate DATE,
somename VARCHAR,
)'''.format(table))
c.execute('''INSERT INTO {} VALUES (?, ?)'''.format(table),
(datetime.strftime(datetime.today(), "%Y-%m-%d"),
myname))
As has been said in the other answers, "tables can't be the target of parameter substitution" but if you find yourself in a bind where you have no option, here is a method of testing if the table name supplied is valid.
Note: I have made the table name a real pig in an attempt to cover all of the bases.
import sys
import sqlite3
def delim(s):
delims="\"'`"
use_delim = []
for d in delims:
if d not in s:
use_delim.append(d)
return use_delim
db_name = "some.db"
db = sqlite3.connect(db_name)
mycursor = db.cursor()
table = 'so""m ][ `etable'
delimiters = delim(table)
if len(delimiters) < 1:
print "The name of the database will not allow this!"
sys.exit()
use_delimiter = delimiters[0]
print "Using delimiter ", use_delimiter
mycursor.execute('SELECT name FROM sqlite_master where (name = ?)', [table])
row = mycursor.fetchall()
valid_table = False
if row:
print (table,"table name verified")
valid_table = True
else:
print (table,"Table name not in database", db_name)
if valid_table:
try:
mycursor.execute('insert into ' +use_delimiter+ table +use_delimiter+ ' (my_data,my_column_name) values (?,?) ',(1,"Name"));
db.commit()
except Exception as e:
print "Error:", str(e)
try:
mycursor.execute('UPDATE ' +use_delimiter+ table +use_delimiter+ ' set my_column_name = ? where my_data = ?', ["ReNamed",1])
db.commit()
except Exception as e:
print "Error:", str(e)
db.close()
you can use something like this
conn = sqlite3.connect()
createTable = '''CREATE TABLE %s (# );''' %dateNow)
conn.execute(createTable)
basically, if we want to separate the data into several tables according to the date right now, for example, you want to monitor a system based on the date.
createTable = '''CREATE TABLE %s (# );''' %dateNow) means that you create a table with variable dateNow which according to your coding language, you can define dateNow as a variable to retrieve the current date from your coding language.
You can save your query in a .sql or txt file and use the open().replace() method to use variables in any part of your query. Long time reader but first time poster so I apologize if anything is off here.
```SQL in yoursql.sql```
Sel *
From yourdbschema.tablenm
```SQL to run```
tablenm = 'yourtablename'
cur = connect.cursor()
query = cur.execute(open(file = yoursql.sql).read().replace('tablenm',tablenm))
You can pass a string as the SQL command:
import sqlite3
conn = sqlite3.connect('db.db')
c = conn.cursor()
tablename, field_data = 'some_table','some_data'
query = 'SELECT * FROM '+tablename+' WHERE column1=\"'+field_data+"\""
c.execute(query)
I have a column in my SQLite table named 'img_name'. An example of data in that column: '/storage/extSdCard/img1.jpg /storage/extSdCard/img2.jpg /storage/extSdCard/pic3.jpg'. Lets say I wanted to delete an image. I would delete the corresponding word(path). Only problem is, I do not know how to delete a specific word(path) from that column.
Any help will be appreciated.
The way to "delete a specific word" is to update the existing value.
So you will need an UPDATE statement which selects the appropriate rows, and changes the value of the column. The new value will have to be "computed" from the old value, as you would do in a programming language, using string functions.
UPDATE column1
SET column1 = trim(replace(column1||' ','/storage/extSdCard/img2.jpg ',''))
WHERE column2 = 'example'
Note that this is an example only. The correct string manipulation required may be different. Your question does not specify your exact requirements.
Please consult the SQLite documentation and internet articles for details of string functions in SQLite.
Note that this would not be necessary if you didn't store more than one value in a column in each row.
You should get id of your string that you need to remove, and then pass it in to this:
public void deleteById(int id)
{
SQLiteDatabase db=getWritableDatabase();
String[] position =new String[]{id+""};
db.delete("img_name", "id=?", position );
}
Note: "id=?". Replace "id" in this statement by your id column
I just want to insert values into a table if the value provided does not exists in that table, I mean I have provided a column as UNIQUE, so sqlite3 UNIQUE constraint will be broken when that value is tried to input twice, i want an sqlite3 insert statement which helps to do this my code is. I read that INSERT IGNORE is used for this purpose. Can somebody provide me with syntax to do this correctly?
My code is given below.
String insertQuery1 = "INSERT INTO Bookdetails bookpath,lastchapter VALUES(?,?)";
db.execSQL(Query1, new String[] { filepath, none });
What is the correct syntax for this query? filepath and none are string which have values assigned
Also this table Bookdetails has a primarykey field 'id' which is auto increment? will it create any problems when data is inserted like this way?
String insertQuery1 = "INSERT INTO Bookdetails (bookpath,lastchapter) VALUES(?,?)";
db.execSQL(Query1, new String[] { filepath, none });
Change
INSERT INTO Bookdetails bookpath,lastchapter VALUES(?,?)
to
INSERT OR IGNORE INTO Bookdetails (bookpath,lastchapter) VALUES(?,?)
The OR IGNORE causes that when a constraint such as UNIQUE is violated, the insert doesn't take place and there won't be an error.
The column names to insert to need to be in () parens.
Additionally, you're passing some other query to execSQL() than the insertQuery1 here.
Also this table Bookdetails has a primarykey field 'id' which is auto increment? will it create any problems when data is inserted like this way?
No, since no insertion takes place.
If you had INSERT OR REPLACE instead of the ignore, it would translate to a DELETE followed by INSERT, generating a new row id in case the id was not specified in the insert itself.
The query is wrong:
INSERT INTO Bookdetails bookpath,lastchapter VALUES(?,?)
It should be:
INSERT INTO Bookdetails (bookpath, lastchapter) VALUES (?, ?)
Mind the parentheses surrounding the fields list!
I have a case that I would like to insert record in SQLite with database.insert(table, null, values).
TABLE t2 (_id, field1, field2)
..
val.setVal1(null);
val.setVal2(val2);
..
if(val.getVal1==null){
values.put(field1, _id);
}else{
values.put(field1, var.val1);
}
values.put(field2, var.val2);
database.insert("t2", null, values);
Is possible to do sth like this "values.put(field1, _id);"?
_id is generated at database.insert().
Note: I am looking for solution for one insert call. Insert and update row with (field1=_id) is easy.
i think i see now. you're asking if you can enter a value into a specific SQLite row _id field if it's available in your val object. Else, you want the database to automatically create a unique id for that column while inserting, like normally done. Is this correct?
To that end, i would seriously reconsider this purpose. You should never be specifying values for the _id column because it needs to be unique or else you'll get exceptions thrown. Moreover, it's only purpose is to be a unique identifier for the system, so you personally knowing this value should be of no use to you.
If you still need this functionality, i'd suggest making another field in your table (much like the _id column but not it), which you can fill with randomly generated numbers or val.getVal1 values.
Is the field "_id" necessary in Android SQLite?
_id is useful when you are using the enhanced Adapters which make use of a Cursor (e.g. ResourceCursorAdapter). It's used by these adapters to provide an ID which can be used to refer to the specific row in the table which relates the the item in whatever the adapter is being used for (e.g. a row in a ListView).
It's not necessary if you're not going to be using classes which need an _id column in a cursor, and you can also use "as _id" to make another column appear as though it's called _id in your cursor.
Why not make use of _ROWID_?
SQLite provides this anyway for every row, so you can just alias it to _id in your select statement.
Technically no the field _id is not required, however if you are making use of the CursorAdapter class (which you probably are, especially if you are working with the Notepad example) then yes
"The Cursor must include a column named "_id" or this class will not
work"
as explained in the documentation here. Unfortunately the code examples do not make this very clear.
It's quite convenient in many cases to have an id field. I prefer mine to be auto-incrementing (as shown below). I'm always finding new uses for the id field :)
When it comes time to attach the data to an adapter, I like to use a table name alias to query the id field as _id. Example: SELECT id _id, msg from message order by id. That way the adapter sees a field called _id and everybody's happy.
Here's a sample of how I define my tables:
CREATE TABLE message (_id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, tripID TEXT, msg TEXT);
From the official docs...
The Cursor must include a column named "_id" or this class will not work. Additionally, using MergeCursor with this class will not work if the merged Cursors have overlapping values in their "_id" columns.
And the Cursor is:
This interface provides random read-write access to the result set returned by a database query.
In other words, you need _id for Android SQLite ( which usually uses Cursor )
If you define your _id column as an autoincrementing integer it is actually an alias for the ROWID column that SQLite provides by default (https://www.sqlite.org/lang_createtable.html#rowid).
Your create statement needs take the form...
CREATE TABLE t(_id INTEGER PRIMARY KEY ASC, y, z);
To prove this works...
UPDATE t SET _id=22 WHERE _id=11;
then
SELECT ROWID, _id FROM t;
and you'll find both _id and ROWID have the same value.
Note, that if you use DESC in the CREATE a new column is created and ROWID is not aliased.
Surely not.
Its a convenience field that some widgets like ListView uses to populate data. See this good article:
http://www.casarini.org/blog/2009/android-contentprovider-on-sqlite-tables-without-the-_id-column/
Of course if you are creating your own UI widget and your own adapter, you don't have to name your primary key as "_id". It can be any name you want. But you would be responsible for managing your collections of UI widgets and binding them to the right row in your database. "_id" is only useful for ListView as Brad has pointed out.
The _id field is indeed necessary in sqlite, it will help you to select a particular data from sqlite.
SELECT name from table_name where _id = ?
And if your are creating a recyclerview/ listview and you want a detailed activity for that list item you indeed need an id for this to fetch data of that item.
if you are creating a class for constants there is a BaseColumn interface in android,
which provide _ID field to that constant class.
//from android documentation..
public static class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "entry";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
}