This question already has an answer here:
android.database.sqlite.SQLiteException: no such column or name
(1 answer)
Closed yesterday.
CODE:
//creating an sqlite query and setting column names
along with data types.
String query = "CREATE TABLE tableMon (notes TEXT)";
//calling a exec sql method to execute sql query
db.execSQL(query);
//after adding....passing content values to the table
String insert = "INSERT INTO tableMon (notes) VALUES (
" + values + " )";
db.execSQL(insert);
ERROR:
tableMon has no column named notes in "INSERT INTO tableMon (notes) VALUES ( notes=hello )"
I have tried adding and removing spaces near the column name and adding variables instead direct use of table name and column name.
Though! didn't get any expected result.
Your issue is that the value being inserted is non-numeric and thus must be enclosed in single quotes. So:-
String insert = "INSERT INTO tableMon (notes) VALUES ('" + values + "' )";
However, the above code is susceptible to SQL Injection So it would be better to use:-
String insert = "INSERT INTO tableMon (notes) VALUES (?)";
db.execSQL(insert,new String[]{values};
In this case the value will be suitable enclosed when it is bound by SQLite binding.
However, another approach is to use the SQLiteDatabse insert method. This has the advantages that
it builds the underlying SQL, and
binds values,
and returns the rowid of the inserted row or -1 if the row could not be inserted.
In your case you could use:-
ContentValues cv = new ContentValues();
cv.put("notes",values);
long result = db.insert("tableMon",null,cv);
Here is a working demo:-
public class MainActivity extends AppCompatActivity {
SQLiteDatabase db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = SQLiteDatabase.openOrCreateDatabase(this.getDatabasePath("example.db").getPath(),null);
db.execSQL("CREATE TABLE IF NOT EXISTS tableMon (notes TEXT)");
String values = "notes=hello";
db.execSQL("INSERT INTO tableMon (notes) VALUES('" + values + "')");
db.execSQL("INSERT INTO tableMon (notes) VALUES(?)",new String[]{values});
ContentValues cv = new ContentValues();
cv.put("notes",values);
db.insert("tableMon",null,cv);
}
}
Note the use of CREATE TABLE IF NOT EXISTS, which will circumvent the error if the table already exists.
The result, via Android Studio's App Inspection ,when installed and run (first time, subsequent runs would add another set of 3 rows):-
i.e. 3 rows have been inserted using each of the fixes.
Related
I have this method to create SQLite database, now am wondering code command that will create a table in the database called Medical_Information with column id as AUTOINCREMENT, INT,and then Time of data type DateTime,Dosage_description(VARCHAR255).
//Method to create database in slite
public void createDatabase(){
SQLiteDatabase myDB = this.openOrCreateDatabase("Dosage", MODE_PRIVATE, null);
}
//Method to create table
Syntax for creating table is:
CREATE TABLE tableName (columnName1 valueType1, columnName2 valuType2...);
Below syntax will create table like as you wanted.
private static final String CREATE_TABLE = "CREATE TABLE Medical_Information (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"Time DATETIME, " +
"Dosage_description VARCHAR(255))";
You can also use SQLiteStudio for creating database and tables and you can use that database or you can create database and tables and you can copy syntax for creating table from SQLiteStudio.
EDIT:
Can you post for inserting sample data into table?
Either you can use SQL syntax or insert() method.
Syntax for inserting data into table:
INSERT INTO tableName (column1, column2....) VALUES (value1, value2,...);
Using ContentValues with insert() method:
ContentValues values = new ContentValues();
values.put(columnName, value);
db.insert(tableName, columnHack, values);
Inserting data with SQL syntax:
String sql = "INSERT INTO Medical_Information (Time, Dosage_description) VALUES (datetime(), 'test')";
db.execSQL(sql);
db.close();
Note: datetime() is a time function of SQL so you can't use it with ContentValues (but you can use Java's time methods). Inserting data with insert() method:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ContentValues values = new ContentValues();
values.put("Time", sdf.format(new Date()));
values.put("Dosage_description", "test");
db.insert("Medical_Information", null, values);
db.close();
String sql2="if not exists(select * FROM stock where productCode=?)\n" +
"Begin\n" +
"insert into stock "
+ "(productName,quantity,currentQuantity,price,companyName,categoryName,productCode) "
+ "values(?,?,?,?,?,?,?)\n" +
"End";
PreparedStatement pst2 = con.prepareStatement(sql2);
pst2.setString(1,productCodeTextField.getText());
pst2.setString(2,productNameTextField.getText());
pst2.setString(3,quantityTextField.getText());
pst2.setString(4,quantityTextField.getText());
pst2.setString(5,priceTextField.getText());
pst2.setString(6, (String) companyNameJComboBox.getSelectedItem());
pst2.setString(7, (String) categoryNameJComboBox.getSelectedItem());
pst2.setString(8,productCodeTextField.getText());
int x=pst2.executeUpdate();
if(x!=0){
productCodeTextField.setText("");
productNameTextField.setText("");
quantityTextField.setText("");
priceTextField.setText("");
JOptionPane.showMessageDialog(null,"Product entered");
}else{
JOptionPane.showMessageDialog(null,"Product already exists");
}
I am successfully able to check for for already existing products before insertion but i am not able to populate the correct message on the basis of the query executed. The executeUpdate is always returning some value even when the insertion is not being done. How to fix this.
There is an easier solution that may work for you:
Throw away the first query that checks whether the entry already exists
Rewrite sql2 as follows:
INSERT INTO stock
(productCode, productName, quantity, price, companyName, categoryName)
VALUES (?,?,?,?,?,?)
WHERE NOT EXISTS
(SELECT * FROM stock WHERE productCode = ?)
Add: pst.setString(7, productCodeTextField.getText());
executeUpdate() returns an int indicating the number of rows affected by the query. Use this variable to determine if a row was added. If the variable != 0 display success message.
INSERT INTO stock
(productCode, productName, quantity, price, companyName, categoryName)
select ?,?,?,?,?,?
WHERE NOT EXISTS
(SELECT * FROM stock WHERE productCode = ?)
This is how it works for SQL Server. 3 and 4 points same as Coop answered
I wanna create a table in java for oracle while getting the name of table from user or like a program variable as:
String query= CREATE TABLE ? (ID NUMBER , NAME VARCHAR2(20));
PreparedStatement preStatement = connection.prepareStatement(query );
preStatement.setString(1,tableNAME);
BUT i've got INVALID TABLE NAME error;
How can I reach to this purpose(creating a table by a dynamic name)?
so much thanks!
You can always concatenate the tablename into the string (after checking for possibility of SQL injection).
String query= "CREATE TABLE " + tablename + " (ID NUMBER , NAME VARCHAR2(20))";
In prepared Statement it first compile the query and then bind the value. Hence you cant set tablename to query via prepared statement.
Normal appending the table name to query causes Sql injection.
Best way is to whitelist the tablename and check for the tablename in it. and use it.
else
try the below method it will avoid sql injection.
String tableName = urtablename;
String query= String.format("CREATE TABLE \"%s\" (ID NUMBER , NAME VARCHAR2(20))", tableName.replace("\"", "\"\""));
I have to do remove the row (containing the userId) in the table "USERS". This is my query:
#SqlUpdate("delete from USERS where userId = :userId ")
void removeUser(#Bind("userId") String userId);
But first I want to remove that user from the table "USERS_DATA" (that is a daughter of USERS) which also contain the "userId". How can I do? I've tried this:
#SqlUpdate("delete from USERS_DATA where userId = :userId " +
" and delete from USERS where userId = :userId")
void removeUser(#Bind("userId") String userId);
but console tell me: java.sql.SQLSyntaxErrorException: ORA-00936: missing expression
Unlike some other RDBMS, Oracle does not allow you to pass two statements in the same SQL command (this helps to prevent SQL injection).
You can try using wrapping both queries in an anonymous PL/SLQ block:
BEGIN
delete from USERS_DATA where userId = :userId;
delete from USERS where userId = :userId;
END;
/
This will allow you to execute both DML statements together as they are part of the singular containing PL/SQL block.
Unfortunately, I am not familiar with that annotation syntax in Java so I cannot help you convert it to Java but I would guess at:
#SqlUpdate("BEGIN " +
"delete from USERS_DATA where userId = :userId; " +
"delete from USERS where userId = :userId; " +
"END;")
void removeUser(#Bind("userId") String userId);
Alternatively, you can create a procedure in Oracle:
CREATE OR REPLACE PROCEDURE delete_user(
in_userID USERS_DATA.USERID%TYPE
)
AS
BEGIN
DELETE FROM USERS_DATA WHERE userId = in_userId;
DELETE FROM USERS WHERE userId = in_userId;
END;
/
And you can then just call this procedure.
So I'm trying to fetch data from one of my database tables, could you please check this out for me and see if you can spot the error?
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH, null,
SQLiteDatabase.OPEN_READONLY);
Cursor cursor = db.query(TABLE_CLASSES, new String[] { TABLE_C_DAY,
TABLE_C_NAME, TABLE_C_DAY, TABLE_C_LOCATION, TABLE_C_TIMEHR,
TABLE_C_TIMEMIN, TABLE_C_DURATION, TABLE_C_ONETIMEEVENT,
TABLE_C_CTYPE, TABLE_C_OCCURINGWEEK}, TABLE_C_DAY + "=?",
new String[] { String.valueOf(day) }, null, null, null, null);
Okay so DB_PATH is definitely correct. I tried to close the db connection and it works fine so db works fine and exists.
All of the table column names are correct as these were used in onCreate to create the db and that worked fine. I also tried using
db.rawQuery("SELECT * FROM " + TABLE_CLASSES + " WHERE day = ?", new String[] { String.valueOf(day) });
So when I make the query the app stops and I get a Source code not found message in Eclipse. LogCat says that table 'classes' doesn't exist.
I tried the creation code manually and it worked. Here is the code from onCreate(SQLiteDatabase db);
String CREATE_DB_WITH_INIT_VALUES =
"CREATE TABLE %1$s (%4$s TEXT);" +
"INSERT INTO %1$s VALUES('Lecture');" +
"INSERT INTO %1$s VALUES('Lab');" +
"INSERT INTO %1$s VALUES('Tutorial');" +
"INSERT INTO %1$s VALUES('Meeting');" +
"INSERT INTO %1$s VALUES('Examples Class');" +
"CREATE TABLE %2$s (%5$s smallint, %6$s varchar(40), %7$s varchar(10), %8$s smallint, %9$s smallint, %10$s smallint, %11$s boolean, %12$s smallint, %13$s smallint);" +
"INSERT INTO %2$s VALUES(1,'COMP12112 Computation',1.1,9,0,60,'False','Lecture',3);" +
"INSERT INTO %2$s VALUES(1,'COMP16212 Java OOP 2',1.1,11,0,45,'False','Lecture',3);" +
"INSERT INTO %2$s VALUES(1,'COMP18111 Distributed Systems','Unix',13,15,60,'False','Lab',3);" +
"INSERT INTO %2$s VALUES(2,'Tutorial','LF13',15,0,60,'False','Tutorial',3);" +
"INSERT INTO %2$s VALUES(2,'COMP14111 AI','LF31',10,30,60,'False','Lab',3);" +
"CREATE TABLE %3$s (%14$s smallint, %15$s smallint, %16$s TEXT, %17$s date);";
CREATE_DB_WITH_INIT_VALUES = String.format(CREATE_DB_WITH_INIT_VALUES, TABLE_CLASS_TYPES,
TABLE_CLASSES, TABLE_DEADLINES, TABLE_CT_TYPE,
TABLE_C_DAY, TABLE_C_NAME, TABLE_C_LOCATION, TABLE_C_TIMEHR, TABLE_C_TIMEMIN, TABLE_C_DURATION,
TABLE_C_ONETIMEEVENT, TABLE_C_CTYPE, TABLE_C_OCCURINGWEEK,
TABLE_D_TIMEHR, TABLE_D_TIMEMIN, TABLE_D_DTEXT, TABLE_D_DDATE
);
db.execSQL(CREATE_DB_WITH_INIT_VALUES);
This code doesn't crash and all seems fine but then during the query the table can't be found.
Any idea what is wrong?
What you've done is a valid list of SQL statements. The real problem here is that the method execSQL() only allows you the execution of a single sql statement (See documentation here).
If you want to execute multiple statements automatically, I'd write a method that first splits those statements (by the ending semicolon of each one) and then execute each one in a loop, checking for errors in every iteration so that when some sql statement fails, you can throw a SQLException indicating the sql statement that failed. Something like this:
public static void execSQLScript(SQLiteDatabase db, String script) throws SQLException {
String[] statements = script.split(";");
db.beginTransaction();
for(String statement : statements) {
try {
db.execSQL(statement); // Seems like this method already throws a decent exception
}
catch(SQLException e) {
db.endTransaction(); // Rolling back the changes done
throw e;
}
}
db.setTransactionSuccessful(); // Not rolling but commiting changes, since everything went fine.
db.endTransaction();
}
I'm not a SQL expert but I think your trying to do a little too much when creating the tables. I would suggest creating the table and adding any initial data in 2 different steps.
I don't have any initial data in my database but this is what I'm using to create the table:
createTable = "CREATE TABLE " + TABLE_NAME + "(" + COLUMN_ID + " INTEGER PRIMARY KEY," +
COLUMN_ONE + " TEXT," + COLUMN_TWO + " INTEGER," + COLUMN_THREE + " TEXT," +
COLUMN_FOUR + " TEXT," + COLUMN_FIVE + " TEXT)";
db.execSQL(createTable);
Now in your case after creating the table you can then insert the initial data you want. After
db.execSQL(createTable);
use a ContentValues to add the data you need to the database.
contentValues = new ContentValues();
contentValues.putXXX();
// keep adding data
// the insert method will add the data for you.
SQLiteDatabase.insert(TABLE_NAME, null, contentValues);