How to auto Increment a primarykey in JDBC sql - sql

can you please guys help me, i'm having trouble on making my primary key into auto-increment, My table name is books and the column that i want to be auto-increment is serial_no which is a primary key.
public class donate extends javax.swing.JFrame {
Connection con;
Statement stmt;
ResultSet rs;
PreparedStatement pst;
DefaultTableModel loginModel = new DefaultTableModel();
int curRow = 0;
/**
* Creates new form donate
*/
public donate() {
initComponents();
DoConnect();
showAll();
}
void showAll(){
try{
rs = stmt.executeQuery("SELECT * FROM books");
while(rs.next())
{
String book = rs.getString("book_title");
String categorie = rs.getString("category");
String status = rs.getString("book_status");
String donators = rs.getString("donator");
int serial_nos = rs.getInt("serial_no");
loginModel.addRow(new Object[]{book, categorie, status, donators, serial_nos});
}
}catch(SQLException err){
System.out.println(err);
}
}
void DoConnect( ) {
try{
//CONNECT TO THE DATABASE
String host = "jdbc:derby://localhost:1527/Dafuq7";
String uName ="Dafuq7";
String uPass ="Dafuq7";
con = DriverManager.getConnection(host, uName, uPass);
//EXECUTE SOME SQL AND LOAD THE RECORDS INTO THE RESULTSET
stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String sql = "SELECT * FROM books";
rs = stmt.executeQuery(sql);
}
catch(SQLException err){
JOptionPane.showMessageDialog(donate.this, err.getMessage());
}
}
and here is for may button, which when i input all the data will be submitted to my table books
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String bookttl = bookt.getText();
String yourn = yn.getText();
String categ = cat.getSelectedItem().toString();
String bstat = bs.getSelectedItem().toString();
try {
rs.moveToInsertRow();
rs.updateString( "book_title", bookttl );
rs.updateString( "category", yourn );
rs.updateString( "book_status", categ );
rs.updateString( "donator", bstat );
loginModel.addRow(new Object[]{bookttl, yourn, categ, bstat});
rs.insertRow( );
stmt.close();
rs.close();
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sql = "SELECT * FROM books";
rs = stmt.executeQuery(sql);
}
catch (SQLException err) {
System.out.println(err.getMessage() );
}// TODO add your handling code here:
}
BTW i found another way around by doing this, grabbing my table and reconstructing it and put this code in the create table script
SERIAL_NO INTEGER default AUTOINCREMENT: start 1 increment 1 not null primary key

Simply define your serial_no column as int primary key generated always as identity and then Derby will automatically assign the numbers for you. Here is some example code:
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(
"jdbc:derby:C:/__tmp/derbytest;create=true")) {
String sql;
sql = "DROP TABLE books";
try (Statement s = conn.createStatement()) {
s.executeUpdate(sql);
} catch (Exception e) {
// assume table did not previously exist
}
sql = "CREATE TABLE books (" +
"serial_no int primary key " +
"generated always as identity, " +
"title varchar(100))";
try (Statement s = conn.createStatement()) {
s.executeUpdate(sql);
}
sql = "INSERT INTO books (title) VALUES (?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "The Book of Foo");
ps.executeUpdate();
ps.setString(1, "The Book of Bar");
ps.executeUpdate();
ps.setString(1, "The Book of Baz");
ps.executeUpdate();
}
sql = "SELECT * FROM books";
try (Statement s = conn.createStatement()) {
try (ResultSet rs = s.executeQuery(sql)) {
while (rs.next()) {
System.out.println(String.format(
"%d: %s",
rs.getInt("serial_no"),
rs.getString("title")));
}
}
}
} catch (SQLException se) {
se.printStackTrace(System.out);
System.exit(0);
}
}
which produces
1: The Book of Foo
2: The Book of Bar
3: The Book of Baz

Related

Creating Trigger to auto-increment id by sequence in JDBC

I am writing methods through JDBC to create a table and a sequence to recall in a Trigger, I want to set up an id column which auto-increments before every insert on the table. I succeeded in building both the createTable method and the createSequence method in the DAO, but when I run the method to create the Trigger I got the java.sql.SQLException: Missing IN or OUT parameter at index:: 1
public void createTrigger() {
PreparedStatement ps;
StringBuilder queryTrigger = new StringBuilder();
queryTrigger.append("CREATE OR REPLACE TRIGGER ");
queryTrigger.append(Tables.getInstance().getName() + "_INSERTED\n");
queryTrigger.append("BEFORE INSERT ON " + Tabelle.getInstance().getName());
queryTrigger.append("\nFOR EACH ROW\n");
queryTrigger.append("BEGIN\n");
queryTrigger.append("SELECT " + Tables.getInstance().getName() + "SEQ.NEXTVAL\n");
queryTrigger.append("INTO :new.id\n");
queryTrigger.append("FROM dual;\n ");
queryTrigger.append("END;\n");
queryTrigger.append("/\n");
queryTrigger.append("ALTER TRIGGER " +Tabelle.getInstance().getName() + "_INSERTED ENABLE\n");
queryTrigger.append("/\n");
String stringQueryTrigger = queryTrigger.toString();
Connection conn = JDBCUtility.openConnection();
try {
ps = (PreparedStatement) conn.prepareStatement(stringQueryTrigger);
ps.executeUpdate();
ps.close();
} catch(SQLException e) {
e.printStackTrace();
}
JDBCUtility.closeConnection(conn);}
Here instead the creation of the table does actually work even if I don't
write the classic lines with parametrized "?" for the preparedStatement.setString(index, String)
public void createTable(Columns c) {
PreparedStatement ps;
StringBuilder query = new StringBuilder();
query.append("CREATE TABLE " + Tabelle.getInstance().getName() + "(");
query.append(Columns.getInstance().getColumnName() + " ");
query.append(Columns.getInstance().getDataType());
if(Columns.getInstance().isNullOrNot() == true) {
query.append(" NOT NULL");
}
else {
query.append("");
}
if(Columns.getInstance().isPrimaryKeyOrNot() == true) {
query.append(" PRIMARY KEY)");
}
else {
query.append(")");
}
String queryToString = query.toString();
Connection conn = JDBCUtility.openConnection();
try {
ps = (PreparedStatement) conn.prepareStatement(queryToString);
ps.executeUpdate();
ps.close();
} catch(SQLException e) {
e.printStackTrace();
}
JDBCUtility.closeConnection(conn);
}
//EDIT
turns out that is enough to substitute the PreparedStatement with a simple Statement, to get rid of the indexes mechanism and get the DB to accept the query
I would suggest creating an auto-increment sequnce in oracle that can be used for all ids and just add the string id.NextVal to the string query
What I mean is:
Rem in oracle create sequence
CREATE SEQUENCE ID
START BY 1
INCREMENT 1
// in java to execute query
String query = "INSERT INTO TABLE VALUES(ID.NEXTVAL);" ;
//rest of code

SQL query into JTable

I've found one totally working query, which gets columns and their data from Oracle DB and puts the output in console printout.
I've spent 3 hours trying to display this data in Swing JTable.
When I am trying to bind data with JTable:
jTable1.setModel(new javax.swing.table.DefaultTableModel(
data, header
));
it keeps telling me that constructor is invalid. That's true, because I need arrays [] and [][] to make that. Any ideas how this can be implemented?
Here is the original query:
package com.javacoderanch.example.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class MetadataColumnExample {
private static final String DRIVER = "oracle.jdbc.OracleDriver";
private static final String URL = "jdbc:oracle:thin:#//XXX";
private static final String USERNAME = "XXX";
private static final String PASSWORD = "XXX";
public static void main(String[] args) throws Exception {
Connection connection = null;
try {
//
// As the usual ritual, load the driver class and get connection
// from database.
//
Class.forName(DRIVER);
connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
//
// In the statement below we'll select all records from users table
// and then try to find all the columns it has.
//
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select *\n"
+ "from booking\n"
+ "where TRACKING_NUMBER = 1000001741");
//
// The ResultSetMetaData is where all metadata related information
// for a result set is stored.
//
ResultSetMetaData metadata = resultSet.getMetaData();
int columnCount = metadata.getColumnCount();
//
// To get the column names we do a loop for a number of column count
// returned above. And please remember a JDBC operation is 1-indexed
// so every index begin from 1 not 0 as in array.
//
ArrayList<String> columns = new ArrayList<String>();
for (int i = 1; i < columnCount; i++) {
String columnName = metadata.getColumnName(i);
columns.add(columnName);
}
//
// Later we use the collected column names to get the value of the
// column it self.
//
while (resultSet.next()) {
for (String columnName : columns) {
String value = resultSet.getString(columnName);
System.out.println(columnName + " = " + value);
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
connection.close();
}
}
}
Ok I found a bit better way adding SQL query to JTable without even using the ArrayList. Maybe will be helpful for someone, completely working:
import java.awt.*;
import javax.swing.*;
import java.sql.*;
import java.awt.image.BufferedImage;
public class report extends JFrame {
PreparedStatement ps;
Connection con;
ResultSet rs;
Statement st;
JLabel l1;
String bn;
int bid;
Date d1, d2;
int rows = 0;
Object data1[][];
JScrollPane scroller;
JTable table;
public report() {
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
setSize(600, 600);
setLocation(50, 50);
setLayout(new BorderLayout());
setTitle("Library Report");
try {
Class.forName("oracle.jdbc.OracleDriver");
con = DriverManager.getConnection("jdbc:oracle:thin:#XXXXX", "XXXXX", "XXXXX");
} catch (Exception e) {
}
try {
/*
* JDBC 2.0 provides a way to retrieve a rowcount from a ResultSet without having to scan through all the rows
* So we add TYPE_SCROLL_INSENSITIVE & CONCUR_READ_ONLY
*/
st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); //Creating Statement Object
} catch (SQLException sqlex) {
System.out.println("!!!###");
}
try {
rs = st.executeQuery("select TRACKING_NUMBER, INCO_TERM_CODE, MODE_OF_TRANSPORT\n"
+ "from salog.booking\n"
+ "where rownum < 5");
// Counting rows
rs.last();
int rows = rs.getRow();
rs.beforeFirst();
System.out.println("cc " + rows);
ResultSetMetaData metaData = rs.getMetaData();
int colummm = metaData.getColumnCount();
System.out.println("colms =" + colummm);
Object[] Colheads = {"BookId", "BookName", "rtyry"};
if (Colheads.length != colummm) {
// System.out.println("EPT!!");
JOptionPane.showMessageDialog(rootPane, "Incorrect Column Headers quantity listed in array! The program will now exit.", "System Error", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
data1 = new Object[rows][Colheads.length];
for (int i1 = 0; i1 < rows; i1++) {
rs.next();
for (int j1 = 0; j1 < Colheads.length; j1++) {
data1[i1][j1] = rs.getString(j1 + 1);
}
}
JTable table = new JTable(data1, Colheads);
JScrollPane jsp = new JScrollPane(table);
getContentPane().add(jsp);
} catch (Exception e) {
}
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
JFrame frm = new report();
frm.setSize(600, 600);
frm.setLocation(50, 50);
BufferedImage image = null;
frm.setIconImage(image);
frm.setVisible(true);
frm.show();
}
}

using clearParameter() even thought PreparedStatement is being closed

private PreparedStatement InsertPS = null;
public boolean InsertInDB(String username, String password, double balance, String secret) {
boolean ans = false;
try {
InsertPS = con.prepareStatement("Insert into BankDB values(?,?,?,?)");
String data[] = AMC.SendtoDB(password, secret);
InsertPS.setString(1, data[0]);
InsertPS.setString(2, username);
InsertPS.setString(3, data[1]);
InsertPS.setDouble(4, balance);
int rows = InsertPS.executeUpdate();
if (rows != 0) {
ans = true;
}
InsertPS.clearParameters();
} catch (SQLException sqlInite) {
System.out.println("SQL Error in InsertInDB method: " + sqlInite);
} finally {
try {
InsertPS.close();
} catch (SQLException sqle) {
System.out.println("SQL Exception in InsertInDB method finally clause : " + sqle);
}
}
return ans;
}
Above is the InsertInDB() method given,
It has a InsertPS PreparedStatement Object.
Here is it necessary to use clearParameters() method even though i am closing the InsertPS object at the end of the method.
(I have provided a separate method to close the connection object)
also another question: Is it a good idea to create PreparedStatement Object's outside any method within a class,initializing using Constructor and Say for example Once all Object's (each in different method) are used, close all PreparedStatement Objects using a separate method.
public class JavatoDB {
Driver DM = null;
Connection con = null;
PreparedStatement InsertPS = null;
PreparedStatement BalancePS = null;
PreparedStatement DeletePS = null;
PreparedStatement UpdatePS = null;
PreparedStatement SearchDB = null;
ResultSet RS = null;
ResultSetMetaData RSMD = null;
AdminControl AMC = null;
public JavatoDB() {
AMC = new AdminControl();
try {
DM = new com.mysql.jdbc.Driver();
con = DriverManager.getConnection("jdbc:mysql://localhost/javadb", "java", "javaaccess");
InsertPS = con.prepareStatement("Insert into BankDB values(?,?,?,?)");
BalancePS = con.prepareStatement("Select BALANCE from BankDB where ACCNAME=? AND ACCPIN = ?");
DeletePS = con.prepareStatement("Delete from BankDB where ACCNAME = ? AND ACCPIN = ? ");
UpdatePS = con.prepareStatement("Update BankDB set BALANCE = (BALANCE + ?) where ACCNAME = ? AND ACCPIN = ?");
SearchDB = con.prepareStatement("Select ID AND ACCPIN from BankDB where ACCNAME = ? ");
} catch (SQLException JavatoDBContrsuctor) {
System.out.println("SQL Error in JavatoDBConstructor: " + JavatoDBContrsuctor);
}
}
public boolean InsertInDB(String username, String password, double balance, String secret) {
boolean ans = false;
try {
String data[] = AMC.SendtoDB(password, secret);
InsertPS.setString(1, data[0]);
InsertPS.setString(2, username);
InsertPS.setString(3, data[1]);
InsertPS.setDouble(4, balance);
int rows = InsertPS.executeUpdate();
if (rows != 0) {
ans = true;
}
InsertPS.clearParameters();
} catch (SQLException sqlInite) {
System.out.println("SQL Error in InsertInDB method: " + sqlInite);
}
return ans;
}
Suggestion's or Criticism on other aspects of code are also welcome.
For the first question, when you call:
con.prepareStatement()
a new preparedStatement is created, then parameters dont survive, i mean you dont need to clear then.
About the second question, in your implementation i cant see where you close your preparedStatement, and if you only add close, next time method will fail. Then, it is usual to create the preparedStatement and close it in the same method.

MS Access [Microsoft][ODBC Driver Manager] Invalid cursor state

I had the error in this code snippet:
private String[][] connectToDB(String query) throws ClassNotFoundException{
String[][] results = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String db = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=E:/EACA_AgroVentures1.accdb";
conn = DriverManager.getConnection(db);
stmt = conn.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsm = rs.getMetaData();
rs.beforeFirst();
int columns = rsm.getColumnCount();
int rows = getRowCount(rs);
//int rows = rs.getFetchSize();
int rowCount = 0;
results = new String[rows][columns];
//System.out.println(rows+" "+columns);
while((rs!=null) && (rs.next())){
for(int i = 1; i < columns; i++){
results[rowCount][i-1] = rs.getString(i); // --> ERROR SHOWS HERE
//System.out.println(rowCount+","+i+" = "+rs.getString(i));
}
rowCount++;
}
rs.getStatement().close();
conn.close();
} catch (SQLException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
return results;
}
My query consists of the following:
private void loadMR(){
try {
String query = "SELECT dealerCode, SUM(kg) AS totalKG, SUM(price) AS totalPrice, returnDate, BID FROM meatReturns GROUP BY BID, dealerCode, returnDate;";
Object[][] result = connectToDB(query);
// some more code below..
I tried using the first code with some other query given in another method:
private void loadDealers(){
try {
String query = "SELECT * FROM Dealers";
Object[][] result = connectToDBWithRows(
query);
// some more code..
and it runs perfectly well. What is going on here? How can i fix this problem?
UPDATE: the only difference of connectToDBWithRows and connectToDB is the while loop that manages the resultSet
// Snippet from connectToDBWithRows()
while((rs!=null) && (rs.next())){
for(int i = 0; i < columns; i++){
if (i == 0){
// Do nothing
}else{
results[rowCount][i] = rs.getString(i);
//System.out.println(rowCount+","+i+" = "+rs.getString(i));
}
}
rowCount++;
}
and this is my getRowCount() method
private int getRowCount(ResultSet resultSet){
int size = 0;
try {
resultSet.last();
size = resultSet.getRow();
resultSet.beforeFirst();
}
catch(Exception ex) {
return 0;
}
return size;
}
I've noticed that sometimes, Access needs you to specify the table name when referring to columns in sql statements. Try the following:
private void loadMR(){
try {
String query = "SELECT meatReturns.dealerCode, SUM(meatReturns.kg) AS totalKG, SUM(meatReturns.price) AS totalPrice, meatReturns.returnDate, meatReturns.BID FROM meatReturns GROUP BY meatReturns.BID, meatReturns.dealerCode, meatReturns.returnDate";
Object[][] result = connectToDBWithRows(query);

JDBC if a string exist in a database

I am trying to find where a specific string exist in a database (all tables). I have the following code:
DatabaseMetaData md = con.getMetaData();
ResultSet rs = md.getTables(null, null, "%", null);
while (rs.next()) {
stm = con.createStatement();
String sql;
sql = "SELECT * FROM "+rs.getString(3)+"WHERE F01 = '0000000000998'";
rs2 = stm.executeQuery(sql);
while(rs2.next()){
System.out.println(rs.getString(3));
}
}
The problem is in some of the tables F01 doesn't exist, so it throws an exception. Is there any way that even without specifying the column I can search through the whole table?
which database you are using.
Look over this discussion post. you may get good ideas about how to make sure column exists before you call your check
http://www.coderanch.com/t/299298/JDBC/databases/Oracle-describe-table-jdbc
For oracle
you can check these queries
select COLUMN_NAME, DATA_LENGTH, DATA_TYPE from user_tab_columns where Lower(table_name) = 'product'
select table_name, COLUMN_NAME, DATA_LENGTH, DATA_TYPE from user_tab_columns where upper(column_name) = 'PRODUCTID'
therefore your call should be something like this
select table_name from user_tab_columns where upper(column_name) = 'F01'
and then
SELECT * FROM "+rs.getString(1)+"WHERE F01 = '0000000000998'
as you see I am using LOWER and UPPER, you need to make sure you include them, reason as you can understand even though SQL is not case sensitive in its statements, but the value for which conditional check is happening is case sensitive.
The following Java code loops through each VARCHAR/NVARCHAR column in each table and performs a SELECT TOP 1 on that column to see if it gets a hit:
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JDBCQuery {
public static void main(String args[]) {
String textToSearchFor = "Gord"; // test data
System.out.println(String.format("The value '%s' was found in the following locations:", textToSearchFor));
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String connectionString =
"jdbc:odbc:Driver={SQL Server};" +
"Server=.\\SQLEXPRESS;" +
"Trusted_Connection=yes;" +
"Database=myDb";
conn = DriverManager.getConnection(connectionString);
DatabaseMetaData md = conn.getMetaData();
ResultSet mdrs = md.getTables(null, null, "%", new String[] { "TABLE" });
List<String> tableList = new ArrayList<String>();
while (mdrs.next()) {
tableList.add(String.format("[%s].[%s].[%s]", mdrs.getString(1), mdrs.getString(2), mdrs.getString(3)));
// i.e., [catalogName].[schemaName].[tableName]
}
mdrs.close();
for (String tableName : tableList) {
Statement stmt = conn.createStatement();
stmt.execute("SELECT * FROM " + tableName + " WHERE 0=1");
ResultSet rs0 = stmt.getResultSet();
ResultSetMetaData rsmd = rs0.getMetaData();
List<String> columnList = new ArrayList<String>();
for (int colIndex = 1; colIndex <= rsmd.getColumnCount(); colIndex++) {
switch (rsmd.getColumnType(colIndex)) {
case java.sql.Types.VARCHAR:
case java.sql.Types.NVARCHAR:
columnList.add("[" + rsmd.getColumnName(colIndex) + "]");
break;
}
}
rs0.close();
stmt.close();
for (String columnName : columnList) {
String psSql = String.format("SELECT TOP 1 * FROM %s WHERE %s = ?", tableName, columnName);
ps = conn.prepareStatement(psSql);
ps.setString(1, textToSearchFor);
ResultSet rs1 = ps.executeQuery();
if (rs1.next()) {
System.out.println(String.format("column %s in %s", columnName, tableName));
}
rs1.close();
ps.close();
}
}
} catch( Exception e ) {
e.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch( Exception e ) {
e.printStackTrace();
}
}
}
}
The results look like this;
The value 'Gord' was found in the following locations:
column [textCol] in [myDb].[dbo].[linkedTable]
column [FirstName] in [myDb].[dbo].[myContacts]