I'm creating a program to put on my resume seeing as I am a college student with no work experience yet. For this particular part of the program I want to allow the user to search the sqlite database for an employee by either id number, first name or last name. It is working properly, however, it will only show the employee with the name that is spelled exactly and caps sensitive. I want it so that the user can type in a single letter or more and it will show everything in the database that contains that letter or couple letters and so on.
This is what I have:
try {
String field = (String)fieldCombo.getSelectedItem();//gets jcombobox selection
//jcombobox fields are slightly different than the column names in sql table so i did this
if(field.equals("First Name")) {
newField = "firstName";
}
else if(field.equals("Last Name")) {
newField = "lastName";
}
else if(field.equals("ID Num")) {
newField = "idNum";
}
String sql = "select idNum as 'ID Number', firstName as 'First Name', lastName as 'Last Name' from tableEMPLOYEE where " + newField + " = ?";
pst = connect.prepareStatement(sql);
pst.setString(1, searchField.getText());
rs = pst.executeQuery();
empTable.setModel(DbUtils.resultSetToTableModel(rs));
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
as Tim mentioned in comment section. SQL LIKE is what you might need.
But it will not be fast if the database is big and the user types fast, it wont feel responsive enough.
For making a query in SQLITE case insensitive you can use:
SELECT * FROM ... WHERE name = 'enterName' COLLATE NOCASE
Related
I am building a simple program for a library database system in Java where patrons can borrow and return books. The database has 4 tables: Book, Author, Patrons, and AuthorIds. I'm using the SQL statement below to retrieve 1 row of data that includes everything plus a column that counts how many books the patron has already borrowed. The problem is that the program never goes into the while(res.next()) loop and I think it's because the result set is empty. The test print doesn't get printed and membID doesn't get changed to the MemberID of the patron.
But when I try that same SQL statement on db browser on the same database it returns 1 row as expected with the BooksBorrowed column. All of my other ResultSet while loops have worked and returned rows with other SQL statements, it's just this one that doesn't and I don't know why.
public void borrowBooks(String fName, String lName, Scanner input) throws SQLException {
//first find out how many books the user has already borrowed
int booksBorrowed = 0;
int membID = 1; //this will be used for later
sql = "select *, Count(MemberID) AS BooksBorrowed\r\n" +
"FROM Book\r\n" +
" JOIN AuthorIds USING (BookID)\r\n" +
" JOIN Author USING (AuthorID)\r\n" +
" JOIN Patron USING (MemberID)\r\n" +
"WHERE PatronFirstName LIKE ? AND PatronLastName LIKE ?\r\n" +
"GROUP BY MemberID\r\n" +
"ORDER BY BookID ASC";
PreparedStatement stmt = connection.prepareStatement( sql );
stmt.setString(1, fName);
stmt.setString(2, lName);
ResultSet res = stmt.executeQuery();
while(res.next()) {
booksBorrowed = res.getInt("BooksBorrowed");
System.out.println(res.getInt("MemberID"));
System.out.println("Test");
membID = res.getInt("MemberID");
}
if(booksBorrowed >= 2) {
System.out.println("You have already borrowed the maximum amount of 2 books. Return books to borrow more");
}
I figured it out and it was that I should have gotten the memberID in a separate query because I was trying to change it to the corresponding patron in the same query as I was trying to get the number of books borrowed. The problem was that if the patron didn't have any books borrowed, then the result set would be empty and the memberID wouldn't change from what it was temporarily initialized as. This memberID was later inserted into the table for when a book was borrowed so it would be the temporary stand in each time and not the actual memberID of the patron, so the patron would have no books under their name as borrowed.
So I have a database that is made like this
{MATERIAL NAME;QUANTITY}
I also have a JTable in Java that uploads the info from the database (SQLite). As I edit a cell in the table, it automatically updates the database in this way:
//table listener
public void tableChanged(TableModelEvent e) {
//gets row and column if the table is edited
int row = e.getFirstRow();
int column = e.getColumn();
//change in sqlite
if (column == 1) {
int value = Integer.parseInt(table.getModel().getValueAt(row, column).toString());
String materialId = table.getModel().getValueAt(row, column-1).toString();
try (Connection c = DriverManager.getConnection("jdbc:sqlite:database.db"); Statement statement = c.createStatement()) {
String sql = "UPDATE MATERIALS set QUANTITY = " + value + " where MATERIAL='" + materialId +"';";
statement.executeUpdate(sql);
statement.close();
c.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
else if (column == 0) {
int value = Integer.parseInt(table.getModel().getValueAt(row, column+1).toString());
String materialId = table.getModel().getValueAt(row, column).toString();
try (Connection c = DriverManager.getConnection("jdbc:sqlite:database.db"); Statement statement = c.createStatement()) {
String sql = "UPDATE MATERIALS set MATERIAL = " + materialId + " where MATERIAL='" + materialId +"';";
statement.executeUpdate(sql);
statement.close();
c.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
It's okay when the quantity is updated. However, once the material name is updated, I don't know how I am supposed to update it in the database.
String sql = "UPDATE MATERIALS set MATERIAL = " + materialId + " where MATERIAL='" + materialId +"';";
Maybe there is a way to save a previous value of that value? I can not use the quantity of materials as they might be repeated.
I would like to avoid adding IDs to the objects if possible.
This statement:
String sql = "UPDATE MATERIALS set MATERIAL = " + materialId + " where MATERIAL='" + materialId +"';"
Has two (three) problems.
The 'old' value and the 'new' value are the same. You have a logical problem.
WHERE part is concatenated like for string type, but SET part is not
concatenation is evil. The Correct way to do this is
String sql = "UPDATE MATERIALS set MATERIAL = ? where MATERIAL= ?";
PreparedStatement prepstmt = conn.prepareStatement(sql);
prepstmt .setString(1, newMatewrial);
prepstmt .setString(2, oldMaterial);
prepstmt .executeUpdate();
Logical problem must be resolved in your conception.
It Seems the main problem is in basically not using the ID . Every row in relational database should have stable primary key (ID like You say). Name isn't primary key, because can be changed.
WHERE part should use ID and not name.
EDIT: in my opinion good JTable model is one way to solve your problem.
Maybe automagic default table model is too poor. Class implementing Row should have one more column (ID) which can(or not) be invisible.
My English isn't too fluent, cannot teach relational database and Swing in SO post.
The second, small snippet of code doesn't show your application conception.
Read in google about custom JTable model.
Very basic example:
http://www.java2s.com/Code/Java/Swing-JFC/TablewithacustomTableModel.htm
Okay so it seems that I found the solution to the problem
JTable: Detect cell data change
However, this requires implementing another class into the project and using it. The answer for the SQL statement still stays the same.
please i am trying to check if an entry exists in an sqlite database column.
and i am using java. here is what my code looks like
String name =JTextField.getText();
String sql0 = "select * from Objects where Description like " + name;
pStmt = conn.prepareStatement(sql0);
rs = pStmt.executeQuery();
if (rs.next()) {//if there is such entry...
System.out.println("there is an entry");
} else {//no such entry add the asset normally...
System.out.println("there is no such entry");
}
the code is just a test code for testing my sqlite query...
name is the the entry to search for in the Description Column. whenever i run this i get an error saying no such column as the value i have stored as name. please i really need help on this thanks.
I am not really familiar with sql in java but propably you need to use quotes to escape the string
Change
String sql0 = "select * from Objects where Description like " + name;
To
String sql0 = "select * from Objects where Description like '" + name + "'";
Another way is to use prepared staments
I m writing a small utility that captures and logs SQL statements, but will have to remove sensitive data from the Query text and replace with with some dummy text (i.e:XXXXX).
What is a good way to parse the SQL query in java and replace parameters value?
for example:
replace
SELECT NAME, ADDRESS, .... FROM USER WHERE SSN IN ('11111111111111', '22222222222222');
with
SELECT NAME, ADDRESS, .... FROM USER WHERE SSN IN (?, ?);
Using JSQLParser (V0.8.9) this is a solution for your problem:
String sql ="SELECT NAME, ADDRESS, COL1 FROM USER WHERE SSN IN ('11111111111111', '22222222222222');";
Select select = (Select) CCJSqlParserUtil.parse(sql);
//Start of value modification
StringBuilder buffer = new StringBuilder();
ExpressionDeParser expressionDeParser = new ExpressionDeParser() {
#Override
public void visit(StringValue stringValue) {
this.getBuffer().append("XXXX");
}
};
SelectDeParser deparser = new SelectDeParser(expressionDeParser,buffer );
expressionDeParser.setSelectVisitor(deparser);
expressionDeParser.setBuffer(buffer);
select.getSelectBody().accept(deparser);
//End of value modification
System.out.println(buffer.toString());
//Result is: SELECT NAME, ADDRESS, COL1 FROM USER WHERE SSN IN (XXXX, XXXX)
This replaces all found String values within your SQL. To replace other types of data e.g. Long values, override the corresponding visit method in ExpressionDeParser.
Don't use regexp in this case. It turns out quickly to be hard maintainable.
The correct answer depends on how much you want to replace. Something like:
[0-9]{3}-?[0-9]{2}-?[0-9]{4}
will replace social security numbers pretty well. I always take regex code to
regexpal.com
to tweak it and work out bugs.
If you need to replace tons of sensitive information though, and if there are a lot of cases, definitely start looking into using a parser to parse the SQL query string. (such as jsqlparser, as Anirudh recommended.)
String sqlDebit = select * from table where and billing_cycle_start_date between :startDate and :endDate
java:
sqlDebit= sqlDebit.replaceAll(":startDate ", ""+startDate).replaceAll(":endDate", ""+endDate);
With prepare statement you can replace "?" in your query string with your value. Use number to specify which "?" you are referring too. They go by order from right to left.
For example: "SELECT LastName, FirstName FROM Person.Contact WHERE LastName = ? and FirstName = ?"
pstmt.setString(1, "LastNameValue");
pstmt.setString(2, "FirstNameValue");
see full example below:
public static void executeStatement(Connection con) {
try(PreparedStatement pstmt = con.prepareStatement("SELECT LastName, FirstName FROM Person.Contact WHERE LastName = ?");) {
pstmt.setString(1, "Smith");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("LastName") + ", " + rs.getString("FirstName"));
}
}
// Handle any errors that may have occurred.
catch (SQLException e) {
e.printStackTrace();
}
}
I am trying to develop a program where you want to add a new book ( title, author, date,...)
but i do not want to add the author multiple times..
i want the program to check if the author already exists in the table, if not it will add him... here is my code :
public void insert_bk(String m, String a, String b, String c, String d, String e) {
String sql="Select * from author where Full_Name='"+b+"'";
System.out.println(sql);
try {
opencn();
Statement st=cn.createStatement();
ResultSet rs=st.executeQuery(sql);
while (rs.next()) {
String id=rs.getString("Author_ID");
System.out.println(id);
st.executeUpdate("INSERT into book (`Book_ID`,`Title`,`Author_ID`,`Date_of_release`,`Theme`,`Edition`)"+ "VALUES ('" + m+ "','" + a+ "','" + id+ "', '" + d+ "', '" + e+ "', '" + c+ "')");
}
}
catch(SQLException exp) {
System.out.println(exp.getMessage());
}
}
In this code it just checks if the Author exists and adds the book... how can i make the condition that if the author does not exist it will add him along with the book?
Any ideas?
Thank you in advance :)
Instead of using a while-loop you should put rs.next() into an if-statement. If the call returns false no author is present and it has to be inserted.
you can do this stored procedure
declare #i int
Select #i=count(*) from author where Full_Name=#FullName
IF(#i < 1)
BEGIN
// INSERT
END
This might help
String query = "Select * from author where Full_Name='"+b+"'";
SqlCommand cmd = new SqlCommand(query, con);
SqlDataReader rdr;
con.Open();
cmd.ExecuteNonQuery();
rdr = cmd.ExecuteReader();
if (rdr.Read()) { // if you have an author
//do your updation code here
}
else {
//if rdr.Read() gives 0 which will be the case when our
//author wont exist past the code for adding an author here
}
You can make a conditional insert by adding the keyword IGNORE into the statement. Depending on which SQL database you are using the answer is slightly different. I'll demonstrate here the two ways for MySQL and sqlite, but of course there are more.
For MySQL
INSERT IGNORE INTO authors VALUES(?,?...,?)
For SQLite
INSERT OR IGNORE INTO authors VALUES(?,?,...,?);