In the SQLite chapter of "Hello, Android", an interface Constants is created to hold some constant strings: the table name and field names.
Why? How is it more useful to use TITLE than "title" directly? Is there something else I'm missing?
And by the way: how should it be organized if I need two tables? Should I make FirstTableConstants and SecondTableConstants interfaces?
If you're going to use a string more than once, its best to create a constant for it.
It prevents creation of the string more than once.
Object allocation isn't free so you will see some performance gain.
Consider the case where you create the string in a loop.
for(int i=0;i<n;++i){
System.out.println("title");
}
vs using a constant:
for(int i=0;i<n;++i){
System.out.println(TITLE);
}
If it took 1ms to allocate the string "title", your run time for the first loop code is N X 1ms.
Also building SQL statements with constants will be quicker than repeatedly creating new strings for the statement keywords for types (text, integer,) modifiers (unique, not null), etc.
String TABLE_SCHEMA = "(" +
ID + " integer primary key autoincrement, " +
COL_FOO1 + " text, " +
COL_FOO2 + " text, " +
COL_FOO3 + " text, " + ...
If you make " text, " a constant you aren't creating that string over and over again, so your TABLE_SCHEMA string is created quicker.
String TABLE_SCHEMA = "(" +
ID + " integer primary key autoincrement, " +
COL_FOO1 + TYPE_TEXT +
COL_FOO2 + TYPE_TEXT +
COL_FOO3 + TYPE_TEXT + ...
If you're using a class, you should probably have them as public static final String TITLE = "Some Title" field. It's better to use it this way so that you won't make an error while typing it into a command. You'll only have to type the variable name.
Related
I'm trying to add numeric values to parameterized AnalyticsQuery but keep getting errors when the query runs. The java creating the query looks like this:
private ParameterizedAnalyticsQuery aggregateQuery(String userId, Long from, Long to) {
return AnalyticsQuery.parameterized(
"select d.field1,"
+ " d.field2"
+ " from data d"
+ " where d.userId = $userId"
+ " and d.timestamp between $from and $to",
JsonObject.create()
.put("userId", userId)
.put("from", from)
.put("to", to)
);
}
When the query is run the following error is returned:
<< Encountered \"from\" at column 213. ","code":24000}]
If I change the query to the following then it works and returns rows:
return AnalyticsQuery.parameterized(
"select d.field1,"
+ " d.field2"
+ " from data d"
+ " where d.userId = $userId"
+ " and d.timestamp between " + from
+ " and " + to,
JsonObject.create()
.put("userId", userId)
);
Why is there a problem when the parameters are not Strings? Is there a way to use parameterized queries with numeric values?
FROM and TO are reserved keywords in N1QL for Analytics and therefore must be put in backquotes when used as parameter names:
... and d.timestamp between $`from` and $`to`
For a list of all reserved keywords please see:
https://docs.couchbase.com/server/current/analytics/appendix_1_keywords.html
I'm trying to update data in rows in my DB, but i catch error that there's no such column (no such column 'Moscow' or another)
This is DBHelper code:
public static final String tableName = "currentWeather";
public static final String KEY_ID = "_id";
public static final String cityName = "city";
public static final String cityTemp = "temperature";
And creating DB:
sqLiteDatabase.execSQL("create table " + tableName + "(" + KEY_ID + "
integer primary key autoincrement,"
+ cityName + " text," + cityTemp + " text, " + " UNIQUE(" + cityName +
"))");
and error shows when i try to execSQl in response:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " +
DBHelper.cityTemp + "=" +
response.body().getForecastMain().getTemp() + "
WHERE "
+ DBHelper.cityName + "=" + cityName);
I expect to update temperature data in rows by cityName
cityName and response.body().getForecastMain().getTemp() are strings and they should be passed surrounded with single quotes to the sql statement:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " + DBHelper.cityTemp + "='" + response.body().getForecastMain().getTemp() + "'" +
"WHERE " + DBHelper.cityName + " = '" + cityName + "'"
);
But the recommended and safe way of doing the update is with the use of ContentValues and ? as placeholders for the parameters:
ContentValues cv = new ContentValues();
cv.put(DBHelper.cityTemp, String.valueOf(response.body().getForecastMain().getTemp()));
int rows = sqLiteDatabase.update(
DBHelper.tableName,
cv,
DBHelper.cityName + " = ?",
new String[] {cityName}
);
You can examine the value of the integer variable rows.
If it is 1 this means that 1 row was updated (because cityName is unique) so the update was successful.
I think you have changed column name or add new one (city). So you can fix it by two ways
By uninstall the application from phone
Add column name in upgrade method.
Example:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// If you need to add a column
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER DEFAULT 0");
}
}
The thing is you need to wrap the values after the = sign in single quotations in the UPDATE statement. As for digits they work in both cases.
For example here is the correct syntax
UPDATE currentWeather
SET temperature = 45
WHERE
city = 'Moscow'
But in your code I'm assuming cityName has the value Moscow without the single quotation marks so the converted SQL code will be like this
UPDATE currentWeather
SET temperature = 45
WHERE
city = Moscow
Now the sql interpreter will think Moscow is some database object or column or something and not a literal value. So you need to surround your values in single quotation marks.
Also consider What the data type of response.body().getForecastMain().getTemp() is.
If it's int you have to parse it or something, as the data type of the related column is Text.
I'm trying to create a Database using JDBC from Java.
The DB and Table creation goes easily, however now I need to create functions and later a trigger and I keep hitting the wall of exceptions with this function as example:
USE ratercases;
DROP FUNCTION IF EXISTS `IMC`;
DELIMITER $$
CREATE FUNCTION `IMC` (altura INT,peso INT)
RETURNS DOUBLE
BEGIN
DECLARE AltM DOUBLE;
DECLARE AltSqr DOUBLE;
SET AltM=(altura/100);
SET AltSqr=AltM*AltM;
RETURN peso/AltSqr;
END $$
DELIMITER ;
If i run the script above on MySQL Workbench there are no problems; However runnning it from Java gets me SQL Syntax Error Exceptions.
I use the following Java code:
// ps is a SQL Statement; ratercases is the target Database;
ps.execute("USE ratercases;"
+ "DROP FUNCTION IF EXISTS `IMC`;"
+ " DELIMITER $$"
+ " CREATE FUNCTION `IMC` (altura INT,peso INT)"
+ " RETURNS DOUBLE"
+ " BEGIN"
+ " DECLARE AltM DOUBLE;"
+ " DECLARE AltSqr DOUBLE;"
+ " SET AltM=(altura/100);"
+ " SET AltSqr=AltM*AltM;"
+ " RETURN peso/AltSqr;"
+ " END $$"
+ " DELIMITER ;");
//
Java/SQL is apparently having problems with the Delimiter $$ ...
Can anyone enlighten me?
Thanks
An alternative approach would be to connect to the ratercases database directly by specifying it in the connection URL and then execute two separate statements for DROP and CREATE, avoiding the requirement to use DELIMITER at all:
ps.execute("DROP FUNCTION IF EXISTS `IMC`");
ps.execute("CREATE FUNCTION `IMC` (altura INT,peso INT)"
+ " RETURNS DOUBLE"
+ " BEGIN"
+ " DECLARE AltM DOUBLE;"
+ " DECLARE AltSqr DOUBLE;"
+ " SET AltM=(altura/100);"
+ " SET AltSqr=AltM*AltM;"
+ " RETURN peso/AltSqr;");
So the program is the connecting to a .mdb file as our data base. I have written all the other code to the program and know it works fine but I am now having trouble with a complex SQL statement being passed as a parameter to a createQuery(Sring, int) method.
There are two tables
Person, which has Name, Id, City, State
Classes, which has Id, Course, Grade
The intended purpose of this line is to print out "Name and Id" from a table of Persons and also print "Course and Grade" from the Classes table. The query only prints entries with matching Id's(Person.Id = Classes.Id), in a specific Course('CSC 225'), and that have a Grade > 70.
We never were taught the SQL statements in any depth so my basic understanding has concocted the following lines of code.
String s = "SELECT " + personTableTitle + ".Name, " + personTableTitle + ".Id, " +
classesTableTitle + ".Course, " + classesTableTitle + ".Grade FROM " +
personTableTitle + " " + classesTableTitle + " WHERE " +
personTableTitle + ".ID = " + classesTableTitle + ".Id AND " +
"Course = 'CIS 225' AND " + classesTableTitle + ".Grade > 70 AND " +
personTableTitle + ".Id = ? AND " + classesTableTitle + ".Id = ?";
System.out.print(s); // Double check of my SQL Statement before passing
db.createQuery(s, 4);
I have been playing with this SQL statement since Wednesday night and haven't been having much luck.
I only see two problems. Sql needs commas between the table names in the FROM clause, i.e. ...FROM table1, table2 WHERE.... So change your line to
personTableTitle + ", " + classesTableTitle + " WHERE " +
This next one might not be a problem, but it's a good idea to include the table name in front of every field reference.
classesTableTitle + ".Course = 'CIS 225' AND " + classesTableTitle + ".Grade > 70 AND " +
You should definitely try your query directly on the database (console or GUI). Once your query is valid, you'll be able to translate it very quickly back into Java.
Otherwise, it's good practice to add an alias to tables; for example:
select *
from Person P, Classes C
where P.Name = 'joe' and P.id = C.id
You may also need to do an outer join to get your data (look at how to do joins for your database).
Here's what I would suggest for SQL code
String s = "SELECT P.Name, P.Id, ";
s = s + "C.Course, C.Grade ";
s = s + "FROM Person P ";
s = s + "JOIN Classes C ";
s = s + "ON P.ID = C.ID ";
s = s + "WHERE Course = 'CIS 225' AND C.Grade > 70;";
I split up each assignment into its own line.
Solved it everyone, thanks for the help.
I started rewriting it using the suggestions posted and came up with this as the string:
String s = "SELECT Person2.Name, Person2.Id, Classes.Course, Classes.Grade FROM Person2, Classes WHERE Classes.Id = Person2.Id AND Classes.Course = 'CIS 225' AND Classes.Grade >70";
It works so I can make it more presentable now. The reason I am using my variable names from java in the original post was that is what the teacher wanted. She is very stubborn and has taken off points from my material for things as simple as writings += whatever; instead of s = s + whatever;
In eclipse as soon as i type this out:
BaseColumns._ID, + "=?"
I get:
The operator + is undefined for the argument type(s) String
How is that possible, they are both Strings aren't they?
now here is documentation for BaseColumns._ID:
public static final String _ID
the code I am writing is:
public void deteleProfile(Long id) throws SQLException {
SQLiteDatabase db = helper.getWritableDatabase();
Integer i = db.delete(ProlificDatabase.TABLE, BaseColumns._ID, + "=?", new String[] {id.toString()});
Log.d(TAG, i + " records deleted where id is " + id);
You've got a rogue comma:
BaseColumns._ID, + "=?"
should probably be
BaseColumns._ID + "=?
Otherwise it's trying to use + "=?" as a stand-alone argument with the + acting as a unary operator.
Do you mean BaseColumns._ID + "=?" instead of BaseColumns._ID, + "=?"?
The compiler just sees the left hand side of the + operator as being empty.
See this documentation on how to use the db.delete method. Instead of BaseColumns._ID, + "=?" - you should be doing this:
Integer i = db.delete(ProlificDatabase.TABLE, BaseColumns._ID + "=?", new String[] {id.toString()});
Lovely extra , (comma)... love the commas for what they are, meaning a separator between expressions and a pain ... for when you overlook them!