I'm getting the error: "Column count doesn't match value count at row 1", yet I have counted and I have the right number of columns and I feel that the error is with the setBoolean() method. I have 8 columns and you will see that I'm passing 7 arguments in my method as one of the columns is an AUTO_INCREMENTE. My coding works perfectly fine if I don't use the setBoolean method replacing it for a setString, setInt or whatever else, but not when I do it with setBoolean().
Here is my code, which I hope makes my problem clearer:
I have an automatic code in my Java that creates the Database & its respective table/s if it doesn't exist:
DB.createDB("userSecInfo");
DB.createTable("accountInfo", "userSecInfo", "("+
"Username VARCHAR(40) NOT NULL, "+
"Pass VARCHAR(40) NOT NULL, "+
"chkPwChange BOOLEAN NOT NULL DEFAULT FALSE, "+
"chkPwCntChange BOOLEAN NOT NULL DEFAULT FALSE, "+
"chkPwNoExpires BOOLEAN NOT NULL DEFAULT FALSE, "+
"chkPwExpires BOOLEAN NOT NULL DEFAULT FALSE, "+
"expirydays INT, "+
"UserID INT NOT NULL AUTO_INCREMENT, "+
"PRIMARY KEY (UserID))");
I have tried defining all the boolean variables for MySQL in different ways such as BOOL, also as BOOLEAN (as it's above) and as TINYINT & TINYINT(1); but the variable definition does not seem to be the problem.
Then the programme, once it has created the Database and the tables, it proceeds to extract the information that the user has inputted and inserts it into the Database:
DB.insertUserSecAccountInfo("userSecInfo", "accountInfo", tFUsername.getText(),
String.copyValueOf(pFPassword.getPassword()), chckbxUserMustChange.isSelected(),
chckbxUserCannotChange.isSelected(), chckbxPasswordNeverExpires.isSelected(),
chckbxPasswordExpiresAnd.isSelected(), Integer.parseInt(tFdays.getText()));
The insertUserSecAccountInfo method as below:
public void insertUserSecAccountInfo(String db_name,String table_name, String Username, String Pass,
boolean chkPwChange, boolean chkPwCntChange, boolean chkPwNoExpires,boolean chkPwExpires,
int expirydays) throws Exception {
try {
openConnection("whatever","password",db_name);
String Query ="INSERT into "+ table_name +" values(?,?,?,?,?,?,?)";
ps = Conexion.prepareStatement(Query);
ps.setString(1, Username);
ps.setString(2, Pass);
ps.setBoolean(3, chkPwChange);
ps.setBoolean(4, chkPwCntChange);
ps.setBoolean(5, chkPwNoExpires);
ps.setBoolean(6, chkPwExpires);
ps.setInt(7, expirydays);
ps.executeUpdate();
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Error saving data"));
ex.printStackTrace();
} finally {
closeConnection();
}
}
When I run it, it shows me the error: "Column count doesn't match value count at row 1". But then I run basically the same line directly in MySQL as below, and it inserts it perfectly fine:
insert into accountInfo(Username,Pass,chkPwChange,chkPwCntChange,chkPwNoExpires,chkPwExpires,expirydays) values ('Hola','No',true,true,true,true,56);
So it makes me feel it's a problem with the setBoolean() method, which might not be mapping or passing correctly the boolean variables from Java to MySQL; has anyone had any similar issue? I would very much appreciate any guidance with this.
Thank you in advance.
Because you did not name every column explicitly, the implicit default of all columns applies. The fact that one of them has a default value is irrelevant (and autocounting is no more and no less than the script of: "Make a sequence, now set the default value for this column to NEXTVAL(nameOfGeneratedSequence)).
This has nothing whatsoever to do with setBoolean.
As some of the commenters have said, you need to always explicitly name the columns you're setting, so: `INSERT INTO " + tableName + " (Username, Pass, etc) VALUES (?,?,... etc)".
SECURITY NOTE: Storing passwords in plain text in a database does not fit with minimal security best practices. If deployed like this and it ever leaks out, you will likely receive a hefty fine or worse (In europe via the GDPR; other jurisdictions often have similar legislation), not to mention a heck of a lot of deserved media fallout. Do not do it this way. – use bcrypt and store the hash instead.
Related
I'm calling a java function using a url from my front end to insert data to the data base
This is my url:
http://localhost:49779/BackEnd/mobile/rideshare/addride/1590105&toyota&4&Himalaya&10&good&12-04-2017
This is the Java method:
#Path("addride/{student_id}&{vehicle}&{seats}&{destination}&{price}&{description}&{datetime}")
#GET
public void addRide(#PathParam ("student_id") int S_id, #PathParam ("vehicle") String vehicle, #PathParam("seats") int seats,
#PathParam("destination") String destination, #PathParam("price") int price, #PathParam("description") String description,#PathParam("datetime") String datetime) throws ClassNotFoundException,SQLException{
Connection myCon = null;
Class.forName("oracle.jdbc.OracleDriver");
myCon=DriverManager.getConnection("jdbc:derby://localhost:1527/ride_share","yadhu","yadhu");
Statement st=myCon.createStatement();
st.executeUpdate("INSERT INTO RIDES (STUDENT_ID,VEHICLE,SEATS,DESTINATION,PRICE,DESCRIPTION,DATETIME) VALUES "
+ "("+S_id+",'"+vehicle+"',"+seats+",'"+destination+"',"+price+",'"+description+"','"+datetime+"')");
}
The table RIDES has a column RIDES_ID, which is made with auto increment property.
This is how I created the table:
CREATE TABLE RIDES (RIDE_ID INTEGER GENERATED ALWAYS AS IDENTITY (start with 1000), STUDENT_ID INTEGER, VEHICLE VARCHAR(200), SEATS INTEGER, DESTINATION VARCHAR(200), PRICE INTEGER, DESCRIPTION VARCHAR(200), DATETIME VARCHAR(50));
The insertion works when I do it implicitly, but when I call the method using the url it's showing the error. I couldn't find the mistake please help me.
The error means that the number of columns you are trying to add does not match the number of declared columns.
IE. insert into table (col1, col2) values (val1, val2, val3).
This could be due to a code error when reading the parameters from the URL.
This can also be due if one of the values your are passing contains a coma "," .
first level of debug:
Do SYSTEM.OUT.PRINTLN to the statement before executing it and check its outcome in the console to spot possible errors.
Also, please do use PreparedStatement instead of Statement since this will prevent your code from having SQL Injections and avoid many errors.
My goal is to generate random number and insert into database. I do not want any duplication. I have done my research, one of is to check at database first, and then insert.
//GENEREATE RANDOM NUMBER
long number = (long) Math.floor(Math.random() * 900000L) + 900000L;
//CHECK IF NUMBER IS ALREADY EXIST IN DATABASE
String searchQuery = "select appleId from food where appleId='" + number + "'";
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(searchQuery);
boolean appleIdExists = rs.next();
//IT IS UNIQUE
if (!appleIdExists) {
try {
//INSERT STATEMENT
.......
} catch (SQLException e) {
e.printStackTrace();
}
}
//IT IS NOT UNIQUE..
else
{
.....
}
}catch (Exception ex) {
System.out
.println("Log In failed: An Exception has occurred! "
+ ex);
}
So my problem is if it NOT unique, I need to generate another number and check again? And check again and again until it is unique? Will the result be many if-else statement?
I am not sure if use if-else statement is the efficient way. Or there is another way?
Any suggestion?
Help will be appreciate! :)
Why not use an auto incrementing identity column in the database, essentially making the database create a unique id for you? Every modern DBMS supports this capability.
For MySQL:
CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
)
For PostgreSQL:
CREATE TABLE animals
(
id serial primary key,
name VARCHAR(40) not null
);
All databases have this capability, and when you use JDBC to insert a row, you get back the key of the inserted row in the response. A simplified example:
String query = "INSERT INTO animals (name) VALUES ('zebra')";
Integer insertedId = stmt.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
If all you want to do is generate random numbers and insert into database, then you can use Fisher Yates shuffle algorithm
Check this question for details: Unique (non-repeating) random numbers in O(1)?
You can hold the random numbers (generated/existing) to a collection/or cache or queue. don't need to check every time in DB.
Try to do the operations in batch. either first generate all the unique random numbers and the persist based on your requirement.
Define an Unique ID on the column - don't need to do a select and insert, just do a INSERT in case of failure repeat the same process.
You can use recursion as we don't know the failure's count.
theexamtime.com
I've had a look around on the web but can't seem to find a definite answer to my question.
Basically, I have a database and table that are successfully working. Now I want to read each line from my table one by one and store the result into a array and I am trying to use a for loop to be more professional rather then using repetition.
I have this code
for (int i=1; i<=8; i++)
{
String query = "Select * FROM Table1 WHERE ID = i";
Rs = St.executeQuery(query);
COL1Title[i] = Rs.getString("CO1Name");
COL2Age[i] = Rs.getString("CO2Rating");
}
The for loop is in a try catch statement and it's complaining with the error "Unknown column 'i' in 'where clause'"
Im guessing there's a certain way for how variable i is to be inserted in the the query.
I should point out ID is a column that has the auto increment feature added on and is primary key if that helps
Could anyone help me out here?
First, we can simplify the task be executing a single query. Note the addition of the range limit and the ORDER BY - without an ORDER BY the results have an unspecified order!
PreparedStatement stmt = "Select ID, CO1Name, CO2Rating"
+ " FROM Table1"
+ " WHERE ID >= ? AND ID <= ?"
+ " ORDER BY ID";
And bind in placeholders (unless there is good reason otherwise, always use placeholders when injecting data into a query). The values could have been hard-coded above in this case, just as they are hard-coded in the for-loop, but the binding is shown here for future reference:
stmt.setInt(1, 1);
stmt.setInt(2, 8);
Then execute the query:
ResultSet rs = stmt.executeQuery();
And iterate the results. Note that rs.next() must be invoke once before any column is read (the cursor starts before any records) and, in this case, it makes it easy to handle a bunch of results.
while (rs.next()) {
int id = rs.getInt("ID");
String title = rs.getString("CO1Name");
String name = rs.getString("CO2Rating");
// do stuff with this record
}
Note that even though the ORDER BY guarantees that the results are iterated in order of ID, assuming a database cardinality rule ensures each result has a unique ID, there may be 0 to 8 records returned - that is, non-existent records may need to be detected/handled separately.
Also (but not shown), make sure to cleanup (close) the ResultSet when done: use a try/finally or try-with-resources construct.
You need to pass i in string as integer, Replace line by:
String query = String.format("Select * FROM Table1 WHERE ID = %d",i);
This is a strange problem, and I hope it has a simple solution. I have a database with encrypted values. I have created a cursor that will go through each of the entries in a table, decrypt the value from the column I need, and add the value to a variable, "total". I want the sum of all of the values in the column. Here is the code:
while (c.moveToNext())
{
strTotal = c.getString(c.getColumnIndexOrThrow(KEY_TOTAL));
strTotal = sc.decrypt(strTotal);
total = Float.valueOf(strTotal) + total;
}
Now, here's the strange part. Let's suppose I have two values in the database: 2 + 4. After each is decrypted, it will correctly add them: 6. Now, if the values are equal: 2 + 2, for instance, the method returns "2" instead of "4". This happens even if it is off by a decimal (2 + 2.01 = 4.01, but 2 + 2 still outputs 2 for example).
Is there something I am missing here? Thanks!
EDIT:
I've changed the code around just to see if the decryption was the problem and it is still giving me the same result:
float total = 0;
String strTotal = "10";
while (c.moveToNext())
{
try {
//strTotal = sc.decrypt(c.getString(c.getColumnIndex(KEY_TOTAL)));
total = Float.valueOf(strTotal) + total;
} catch (Exception e) {
Log.e(TAG, "exception", e);
}
}
This code is returning "10", even though there are 3 entries in the database! It looks like if two rows in the database have the same value in the KEY_TOTAL field, it is returning less results. Here is the query:
Cursor c = mDb.query(true, DATABASE_TABLE, new String[] {KEY_TOTAL}, KEY_TYPE + "=" + t, null, null, null, null, null);
If I pull the db and open it with a sqlite browser, and SELECT all of the rows, I am getting 3 still, however.
I just checked the SQLite documentation for Android (I'm not an Android developer) and I think I found your problem. The first argument to the query method is whether to select distinct rows. Since you're passing TRUE and you're only selecting one column, duplicates will be removed from the result, which is not what you want.
Changing your call to query to the following should fix your issue.
Cursor c = mDb.query(false, DATABASE_TABLE, new String[] {KEY_TOTAL},
KEY_TYPE + "=" + t, null, null, null, null, null);
Have you checked for thrown exceptions? Especially NumberFormatException? I'm guessing there is some other logic problem that is causing the loop to exit prematurely.
I`m building a decision support system in java. Below is a part of code, that scans the search word that is typed in by user, then compares it with database searchlog.searchcolumn values and if the word is not there creates a new entry. BUT in the if statement i want it to check for the entry, and if it IS already in searchlog.searchcolumn column, then I want it NOT to create a new duplicate entry, but to add +1 value to searchlog.counter column for the specific word.
for example if search word is "UMBRELLA" and there is already one entry for umbrella in database, i want it to add +1 to counter column in UMBRELLA row.
the purpose of this, is to store all searchwords and keep a track of the most popular ones.
Thank you for your time
String CheckSearch = "SELECTsearchcolumn FROMsearchlog";
String InsertColumn = "INSERT INTO `mydb`.`searchlog` (`searchcolumn`) VALUES ('"+ InputScanner + "');
//
if (InputScanner.equals(CheckSearch))
System.out.println("value ealready exist, counter well be updated");
else
stmt.executeUpdate(InsertColumn);
EDIT
Thank you for advice of using PreparedStatement, but this is my first more or less serious challenge and for this time, let`s just ignore vulnerability of my code. Thanks
What database are you using? If you are using MySQL, then you should look into INSERT ... ON DUPLICATE KEY UPDATE statement. (Other SQL databases have MERGE, which I'm less familiar with.) Here is the MySQL Documentation.
You will need make your searchcolumn a UNIQUE or PRIMARY column, then something along the lines of: INSERT INTO searchlog (searchcolumn, count) VALUES ("my search query", 0) ON DUPLICATE KEY UPDATE count = count + 1; will accomplish what you want.
your query should be :
String InsertColumn = "INSERT INTO `mydb`.`searchlog` (`searchcolumn`) VALUES ('"+ InputScanner + "'");
Values clause should also be wrapped around brackets.
and always use equals() to check if two strings are meaningfully equal. In case of objects == checks if two reference variables refer to the same object.
if (InputScanner == CheckSearch) {
should be:
if (InputScanner.equals(CheckSearch)) {
Then, your if statement would return true if InputScanner is same as checkSearch.
ADVICE:
I strongly recommend you to use PreparedStatement rather than simple Statement to prevent SQL Injection.
PreparedStatement st = conn.preparedStatement(InsertColumn);
st.setString(1, val1);
1) Values also need to be in braces
Example:
VALUES ('"+ InputScanner + "');
2) Assuming InputScanner and CheckSearch are Strings/comparable objects, you need to do .equals() instead of ==
Example:
if (InputScanner.equals(CheckSearch)) {
Note: Your SQL statement is prone to SQL Injection attack. Better to use PreparedStatement.
There is an MySQL statement for your task:
Requierement: searchcolumn is a unique key.
String sql = "INSERT INTO mydb.searchlog(searchcolumn, counter) VALUES(?, 1) "
+ " ON DUPLICATE KEY UPDATE counter = counter + 1";
PreparedStatement stmt = connection.createPreparedStatement(sql);
stmt.setParameter(1, checkSearch.toUpperCase());
int updateCount = stmt.executeUpdate();
I do not know whether updateCount distinghuishes whether an INSERT or UPDATE happened though. You could use getGeneratedKeys for that purpose, if there is a unmentioned AUTOINCR primary key.