I'm trying to do some Sqlite querying but I don't know if I'm doing it correctly because this feels really unsave to do. So my question is how do I fix this. I'm new to the whole Xamarin and Sqlite usage.
I'm only making a Android project so it is not a cross platform application. I also cant seem to figure out where to get Mono.Data.Sqlite if I even need it. Everything is welcome.
static public List<Users> SelectUser(string name)
{
try
{
var dbConn = new SQLiteConnection(DatabasePath);
{
return dbConn.Query<Users>("SELECT name, email FROM TblUsers where name = " + name+ ";");
}
}
catch (SQLiteException ex)
{
return null;
}
}
You should use Prepared Statements.
There is an official java documentation about Prepared Statements from Oracle here.
You can also search it on google. There are a lot of guides on how to use prepared statements.
Related
Im making a login and register system and if need to check if the user already exits so I wrote this function in my database handler to check it.
public boolean checkIfUserExits(String username){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME + " WHERE username=" + "\"" + username + "\"";
Cursor cursor = db.rawQuery(query, null);
if(cursor.getCount() <= 0){
cursor.close();
return false;
}
cursor.close();
return true;
}
But the problem if that i always getting a true.
Thanks for help.
Well, it does exist:
From the other function you posted (it can be accessed in the revision history, so double check before posting stuff, as it will stay around even if you edit it away).
user = new User(username, password, email);
dbHandler.createUser(user);
if(dbHandler.checkIfUserExits(username) == true){
You can just remove the == true, that's redundant. Anyway, you create the user, then you check whether it exists. Of course it does, you just created it.
The easy but wrong fix would be to check first, then create the user. Unfortunately, if for some reason two programs do this at the same time, it is very possible they both see the user doesn't exist, and both proceed.
What you probably want to do here would be to try creating the user no matter what, then check whether it worked or not. I dont't know this environment, but for sure you should be able to detect integrity constraint violations.
It's posible that your cursor is null and can't count members... My app uses a similar method but it's more complet and can control errors more good.
Why I pass the complet query? It's simple it's a general method, for a general class. With this you can use this method for all calls and don't need to create a new methods for differents calls... If you need this one for one query, then includes inside how your question.
You can see the code below:
public boolean exists_the_ColumnParameter(String query){
//Declaration of variables
Cursor a3 = null;
try{
a3 = database.rawQuery(query,null);
a3.moveToFirst();
if(a3.getString(0).equals("")){
a3.close();
return false;
}
else{
a3.close();
return true;
}
}
catch (CursorIndexOutOfBoundsException ex){
return false;
} catch (Exception ex){
Log.e("-- BDD.exists_the_ColumnParameter --","Exception",ex);
return false;
}
}
Tell me if I helped you and good programming!
so I'm learning microsoft azure, and I'm trying to understand the reading from columns, now I'm able to do that with a new column I've made, but I'm trying to obtain all values from my text column, based on the whichever one is deleted looking at the _deleted column (Automatically made by azure).
Currently I am doing it as follows:
mClient.getTable(Item.class).where().field("_deleted").eq(false)
.execute(new TableQueryCallback<Item>() {
public void onCompleted(List<Item> result,
int count,
Exception exception,
ServiceFilterResponse response) {
if (exception == null) {
for (Item item : result) {
Log.i("ITEM", "Read object with ID " + item.Text);
}
}
}
});
If I use other field and eq values I can confirm it works. But I can't seem to get this to work with the _deleted column and was hoping if anyone had some insights?
Thanks
Apologies guys, turns out I did a super noob mistake, the column "_deleted" is actually "__deleted" I couldn't see those two underscores there since the text was quite small. Hits palm into face
I'm looking at the tutorial for Spatialite-Android, and I'm noticing the following code samples:
String query = "SELECT AsText(Transform(MakePoint(" + TEST_LON + ", " + TEST_LAT + ", 4326), 32632));";
sb.append("Execute query: ").append(query).append("\n");
try {
Stmt stmt = db.prepare(query);
if (stmt.step()) {
String pointStr = stmt.column_string(0);
sb.append("\t").append(TEST_LON + "/" + TEST_LAT + "/EPSG:4326").append(" = ")//
.append(pointStr + "/EPSG:32632").append("...\n");
}
stmt.close();
} catch (Exception e) {
e.printStackTrace();
sb.append(ERROR).append(e.getLocalizedMessage()).append("\n");
}
In particular, I noticed that poor practice is done of simply stringing together a SQL query, instead of a more proper method, such as is used by the Android SQLite library. Is there a way that I can make Spatialite use true prepared statements?
Just to be clear, I'm looking for something like this, using the standard SQLite database in Android:
String query="SELECT * FROM table WHERE _id=?";
Cursor data=db.rawQuery(query,new String[]{id});
There are a few tricks. They all use the exec() call, which has 3 arguments for this version. The statement from the source code is:
public void exec(String sql, jsqlite.Callback cb, String args[])
A jsqlite.Callback is an interface, of which there can be several. But the best way seems to be using a db.get_table(query,args) function. %q is the effective replacement for ? in the Android SQLite representation. Here's the transformation of the given code:
String query = "SELECT AsText(Transform(MakePoint(%q, %q, 4326), 32632));";
TableResult result=db.get_table(query,new String[]{""+TEST_LONG,""+TEST_LAT});
From there, you just have to get the results from TableResult. There isn't a method call to get the results from here, you actually have to grab the publicly declared variable and manually parse through it. Here's an example of how that can be done.
TableResult result=db.get_table(query,new String[]{""+lng,""+lat});
Vector<String[]> rows=result.rows;
for (String[] row:rows)
{
for (String val:row)
{
Log.v(TAG,val);
}
}
If you aren't doing a select, try something like this:
TableResult result=new TableResult();
db.exec("ATTACH DATABASE %q AS newDb",result,new String[]{path});
I assume the same pattern will work for INSERTS and the like
can anyone explain why my inserts are taking so long in Ormlite? Doing 1,700 inserts in one sqlite transaction on the desktop takes less than a second. However, when using Ormlite for Android, it's taking about 70 seconds, and I can see each insert in the debugging messages.
When I try and wrap the inserts into one transaction it goes at exactly the same speed. I understand that there is overhead both for Android and for Ormlite, however, I wouldn't expect it to be that great. My code is below:
this.db = new DatabaseHelper(getApplicationContext());
dao = db.getAddressDao();
final BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.poi)));
try {
dao.callBatchTasks(new Callable<Void>() {
public Void call() throws Exception {
String line;
while ((line = reader.readLine()) != null) {
String[] columns = line.split(",");
Address address = new Address();
// setup Address
dao.create(address);
}
return null;
}
});
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
I've had the same problem, and found a reasonable workaround. This took insert time from 2 seconds to 150ms:
final OrmLiteSqliteOpenHelper myDbHelper = ...;
final SQLiteDatabase db = myDbHelper.getWritableDatabase();
db.beginTransaction();
try{
// do ormlite stuff as usual, no callBatchTasks() needed
db.setTransactionSuccessful();
}
finally {
db.endTransaction();
}
Update:
Just tested this on Xperia M2 Aqua (Android4.4/ARM) and callBatchTasks() is actually faster. 90ms vs 120ms. So I think more details are in order.
We have 3 tables/classes/DAOs: Parent, ChildWrapper, Child.
Relations: Parent to ChildWrapper - 1 to n, ChildWrapper to Child - n to 1.
Code goes like this:
void saveData(xml){
for (parents in xml){
parentDao.createOrUpdate(parent);
for (children in parentXml){
childDao.createOrUpdate(child);
childWrapperDao.createOrUpdate(generateWrapper(parent, child));
}
}
}
I've got original speed up on a specific Android4.2/MIPS set-top-box (STB).
callBatchTasks was the first option because that's what we use througout all the code and it works well.
parentDao.callBatchTasks(
// ...
saveData();
// ...
);
But inserts were slow, so we've tried to nest callBatchTasks for every used DAO, set autocommit off, startThreadConnection and probably something else - don't remember at the moment. To no avail.
From my own experience and other similar posts it seems the problem occurs when several tables/DAOs are involved and it has something to do with implemetation specifics of Android (or SQLite) for concrete devices.
Unfortunately, this may be "expected". I get similar performance when I do that number of inserts under my emulator as well. The batch-tasks and turning off auto-commit don't seem to help.
If you are looking to load a large amount of data into a database, you might consider replaying a database dump instead. See here:
Android OrmLite pre-populate database
My guess would be that you are slowing somewhat because you are doing two IO tasks at one time (at least in the code shown above). You are reading from a file and writing to a database (which is a file). Also, from what I understand transactions should be a reasonable size. 1600 seems like a very high number. I would start with 100 but play around with the size.
So essentially I suggest you "chunk" your reads and inserts.
Read 100 lines to a temp Array, then insert that 100. Then read the next 100, then insert, etc.
I am working on a fuel use application which will run on Android 1.6 onwards. The bundled SQLite on v1.6 doesn't do foreign keys, so I've had to handle it manually. So far, I have done this using an Android transaction:
public static long addFuelUp(String registrationNumber, String date)
{
SQLiteDatabase db = uKMpgData.getReadableDatabase();
long result = -1;
ContentValues values = new ContentValues();
Cursor vehicleCursor = VehicleDataProvider.getVehicle(registrationNumber);
if(vehicleCursor.moveToNext())
{
Cursor fuelUpsCursor = getFuelUps(registrationNumber, date);
if(!fuelUpsCursor.moveToNext())
{
db.beginTransaction();
try
{
values.put(REGISTRATION_NO_COLUMN, registrationNumber.replace(" ", ""));
values.put(DATE_TIME_COLUMN, date);
result = db.insertOrThrow(FUEL_USE_TABLE_NAME, null, values);
db.setTransactionSuccessful();
}
catch(SQLException e)
{
Log.d("addFuelUp", e.getMessage());
}
finally
{
db.endTransaction();
vehicleCursor.close();
fuelUpsCursor.close();
}
}
}
return result;
}
I.e. fuel data cannot be entered unless there is a matching vehicle registration number in the database.
My question is, is there a better way to do this? I'm not a database expert, but I know you can set up triggers to enforce rules - are triggers more suited to handle constraints?
Cheers,
Barry
Triggers would be a good solution to this problem.
In fact there is an automated way to generate triggers for simulating foreign keys. SQLite for PC provides a utility called "genfkey" which can examine an existing database which uses foreign keys and outputs the corresponding triggers.