A General Purpose SQL Interpreter Program
From Java Example Source Code
Contents |
[edit] Overview - A General Purpose SQL Interpreter Program
This Java example introduces how to operate Database with JDBC in a general purpose.
[edit] Java Source Code
- Package: flanagan.david
- File: ExecuteSQL.java
package flanagan.david; /* * Copyright (c) 2000 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 2nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book (recommended), * visit http://www.davidflanagan.com/javaexamples2. */ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; /** * A general-purpose SQL interpreter program. */ public class ExecuteSQL { public static void main(String[] args) { Connection conn = null; // Our JDBC connection to the database server try { String driver = null, url = null, user = "", password = ""; // Parse all the command-line arguments for (int n = 0; n < args.length; n++) { if (args[n].equals("-d")) driver = args[++n]; else if (args[n].equals("-u")) user = args[++n]; else if (args[n].equals("-p")) password = args[++n]; else if (url == null) url = args[n]; else throw new IllegalArgumentException("Unknown argument."); } // The only required argument is the database URL. if (url == null) throw new IllegalArgumentException("No database specified"); // If the user specified the classname for the DB driver, load // that class dynamically. This gives the driver the opportunity // to register itself with the DriverManager. if (driver != null) Class.forName(driver); // Now open a connection the specified database, using the // user-specified username and password, if any. The driver // manager will try all of the DB drivers it knows about to try to // parse the URL and connect to the DB server. conn = DriverManager.getConnection(url, user, password); // Now create the statement object we'll use to talk to the DB Statement s = conn.createStatement(); // Get a stream to read from the console BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); // Loop forever, reading the user's queries and executing them while (true) { System.out.print("sql> "); // prompt the user System.out.flush(); // make the prompt appear now. String sql = in.readLine(); // get a line of input from user // Quit when the user types "quit". if ((sql == null) || sql.equals("quit")) break; // Ignore blank lines if (sql.length() == 0) continue; // Now, execute the user's line of SQL and display results. try { // We don't know if this is a query or some kind of // update, so we use execute() instead of executeQuery() // or executeUpdate() If the return value is true, it was // a query, else an update. boolean status = s.execute(sql); // Some complex SQL queries can return more than one set // of results, so loop until there are no more results do { if (status) { // it was a query and returns a ResultSet ResultSet rs = s.getResultSet(); // Get results printResultsTable(rs, System.out); // Display them } else { // If the SQL command that was executed was some // kind of update rather than a query, then it // doesn't return a ResultSet. Instead, we just // print the number of rows that were affected. int numUpdates = s.getUpdateCount(); System.out.println("Ok. " + numUpdates + " rows affected."); } // Now go see if there are even more results, and // continue the results display loop if there are. status = s.getMoreResults(); } while (status || s.getUpdateCount() != -1); } // If a SQLException is thrown, display an error message. // Note that SQLExceptions can have a general message and a // DB-specific message returned by getSQLState() catch (SQLException e) { System.err.println("SQLException: " + e.getMessage() + ":" + e.getSQLState()); } // Each time through this loop, check to see if there were any // warnings. Note that there can be a whole chain of warnings. finally { // print out any warnings that occurred SQLWarning w; for (w = conn.getWarnings(); w != null; w = w .getNextWarning()) System.err.println("WARNING: " + w.getMessage() + ":" + w.getSQLState()); } } } // Handle exceptions that occur during argument parsing, database // connection setup, etc. For SQLExceptions, print the details. catch (Exception e) { System.err.println(e); if (e instanceof SQLException) System.err.println("SQL State: " + ((SQLException) e).getSQLState()); System.err.println("Usage: java ExecuteSQL [-d <driver>] " + "[-u <user>] [-p <password>] <database URL>"); } // Be sure to always close the database connection when we exit, // whether we exit because the user types 'quit' or because of an // exception thrown while setting things up. Closing this connection // also implicitly closes any open statements and result sets // associated with it. finally { try { conn.close(); } catch (Exception e) { } } } /** * This method attempts to output the contents of a ResultSet in a textual * table. It relies on the ResultSetMetaData class, but a fair bit of the * code is simple string manipulation. */ static void printResultsTable(ResultSet rs, OutputStream output) throws SQLException { // Set up the output stream PrintWriter out = new PrintWriter(output); // Get some "meta data" (column names, etc.) about the results ResultSetMetaData metadata = rs.getMetaData(); // Variables to hold important data about the table to be displayed int numcols = metadata.getColumnCount(); // how many columns String[] labels = new String[numcols]; // the column labels int[] colwidths = new int[numcols]; // the width of each int[] colpos = new int[numcols]; // start position of each int linewidth; // total width of table // Figure out how wide the columns are, where each one begins, // how wide each row of the table will be, etc. linewidth = 1; // for the initial '|'. for (int i = 0; i < numcols; i++) { // for each column colpos[i] = linewidth; // save its position labels[i] = metadata.getColumnLabel(i + 1); // get its label // Get the column width. If the db doesn't report one, guess // 30 characters. Then check the length of the label, and use // it if it is larger than the column width int size = metadata.getColumnDisplaySize(i + 1); if (size == -1) size = 30; // Some drivers return -1... if (size > 500) size = 30; // Don't allow unreasonable sizes int labelsize = labels[i].length(); if (labelsize > size) size = labelsize; colwidths[i] = size + 1; // save the column the size linewidth += colwidths[i] + 2; // increment total size } // Create a horizontal divider line we use in the table. // Also create a blank line that is the initial value of each // line of the table StringBuffer divider = new StringBuffer(linewidth); StringBuffer blankline = new StringBuffer(linewidth); for (int i = 0; i < linewidth; i++) { divider.insert(i, '-'); blankline.insert(i, " "); } // Put special marks in the divider line at the column positions for (int i = 0; i < numcols; i++) divider.setCharAt(colpos[i] - 1, '+'); divider.setCharAt(linewidth - 1, '+'); // Begin the table output with a divider line out.println(divider); // The next line of the table contains the column labels. // Begin with a blank line, and put the column names and column // divider characters "|" into it. overwrite() is defined below. StringBuffer line = new StringBuffer(blankline.toString()); line.setCharAt(0, '|'); for (int i = 0; i < numcols; i++) { int pos = colpos[i] + 1 + (colwidths[i] - labels[i].length()) / 2; overwrite(line, pos, labels[i]); overwrite(line, colpos[i] + colwidths[i], " |"); } // Then output the line of column labels and another divider out.println(line); out.println(divider); // Now, output the table data. Loop through the ResultSet, using // the next() method to get the rows one at a time. Obtain the // value of each column with getObject(), and output it, much as // we did for the column labels above. while (rs.next()) { line = new StringBuffer(blankline.toString()); line.setCharAt(0, '|'); for (int i = 0; i < numcols; i++) { Object value = rs.getObject(i + 1); if (value != null) overwrite(line, colpos[i] + 1, value.toString().trim()); overwrite(line, colpos[i] + colwidths[i], " |"); } out.println(line); } // Finally, end the table with one last divider line. out.println(divider); out.flush(); } /** This utility method is used when printing the table of results */ static void overwrite(StringBuffer b, int pos, String s) { int slen = s.length(); // string length int blen = b.length(); // buffer length if (pos + slen > blen) slen = blen - pos; // does it fit? for (int i = 0; i < slen; i++) // copy string into buffer b.setCharAt(pos + i, s.charAt(i)); } }
[edit] What Result You Can Get
Run the program without parameters, you will get:
java.lang.IllegalArgumentException: No database specified Usage: java ExecuteSQL [-d <driver>] [-u <user>] [-p <password>] <database URL>
Run the program with the following parameters:
-d com.mysql.jdbc.Driver -u root -p <password here> jdbc:mysql://localhost:3306/exampleshow
and you will get:
sql>
then input sql query scripte:
SELECT * FROM pet
press Enter key, you will get:
sql> select * from pet +-------------+------------------------------------------------------------------------------------------------------+ | id | name | +-------------+------------------------------------------------------------------------------------------------------+ | 1 | Dog | | 2 | Cat | | 3 | Panda | +-------------+------------------------------------------------------------------------------------------------------+ sql>
and you can continue try other sql query statements.
[edit] Required External Library for this Java Example
In order to run this example, you need a table in a Database server, and a JDBC driver, such as MySQL JDBC driver, or Oracle JDBC driver or MSSQL JDBC driver, depends on what your Database server is, and one of the following libraries may be required:
- MySQL JDBC driver. You can download it from MySQL Connector/J — for connecting to MySQL from Java
- Oracle JDBC driver. You can download it from JDBC driver for Oracle.
- MSSQL JDBC driver. There are several vendors provide JDBC driver for MSSQL, you should chose one of them:
- jTDS - SQL Server and Sybase JDBC driver. It is an open source JDBC 3.0 Type 4 driver for Microsoft SQL Server (6.5, 7.0, 2000 and 2005) and Sybase. jTDS is the fastest JDBC driver for MS SQL Server and is a complete implementation of the JDBC spec. You can download it from jTDS - SQL Server and Sybase JDBC driver
- MSSQL JDBC driver from Microsoft.
- JDBC driver for MSSQL 2000. You can download it from SQL Server 2000 Driver for JDBC Service Pack 3
- JDBC driver for MSSQL 2005. You can download it from Microsoft SQL Server 2005 JDBC Driver 1.2
For example, we chose MySQL, and create a table pet in MySQL Database exampleshow.
Here's how to create table pet in Database exampleshow:
- Create a Database in MySQL server, name it exampleshow
- Created a table, name it pet, with the following SQL script:
CREATE TABLE pet ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(100) DEFAULT NULL, PRIMARY KEY (id) );
- Input some demo data into the table pet, you can do it by following SQL script:
INSERT INTO pet VALUES (1,'Dog'); INSERT INTO pet VALUES (2,'Cat'); INSERT INTO pet VALUES (3,'Panda');
[edit] How to Run this Java Example Program
We recommend running this Java example program with Eclipse.
For assistance in working with Eclipse, please see How to Run Java Program with Eclipse.
It's fairly easy.
[edit] Question & Answer
Any question?
Click edit and post your question or answer here.
