SQLJ is a working title for efforts to combine Java and SQL. It was a common effort started around 1997 by engineers from IBM, Oracle, Compaq, Informix, Sybase, Cloudscape and Sun Microsystems.
It consists of the three parts: 0, 1 and 2. Part 0 describes the embedding of SQL statements into Java programs. SQLJ part 0 is the basis for part 10 of the SQL:1999 standard, aka SQL Object Language Bindings (SQL/OLB).[1] SQLJ parts 1 and 2 describes the converse possibility to use Java classes (routines and types) from SQL statements. Parts 1 and 2 are the basis for part 13 of the SQL standard, SQL Routines and Types Using the Java Programming Language (SQL/JRT).
"SQLJ" is commonly used to refer to just SQLJ part 0, usually when it is contrasted with other means of embedding SQL in Java, like JDBC.
Part 0 was updated for JDBC 2.0 compatibility and ratified by ISO in 2000. The last two parts were combined when submitted to ISO. Part 2 was substantially rewritten for the ISO submission because the ANSI version was not formal enough for a specification, being closer to the style of a user manual. The combined version was ratified in 2002.[1]
The SQLJ part 0 specification largely originated from Oracle, who also provided the first reference implementation.[1]
In the following SQLJ is a synonym for SQLJ part 0.
Whereas JDBC provides an API, SQLJ consists of a language extension. Thus programs containing SQLJ must be run through a preprocessor (the SQLJ translator) before they can be compiled.
Some advantages of SQLJ over JDBC include:
The following examples compare SQLJ syntax with JDBC usage.
| JDBC | SQLJ |
|---|---|
PreparedStatement stmt = conn.prepareStatement( "SELECT LASTNAME" + " , FIRSTNME" + " , SALARY" + " FROM DSN8710.EMP" + " WHERE SALARY BETWEEN ? AND ?"); stmt.setBigDecimal(1, min); stmt.setBigDecimal(2, max); ResultSet rs = stmt.executeQuery(); while (rs.next()) { lastname = rs.getString(1); firstname = rs.getString(2); salary = rs.getBigDecimal(3); // Print row... } rs.close(); stmt.close(); |
#sql private static iterator EmployeeIterator(String, String, BigDecimal); ... EmployeeIterator iter; #sql [ctx] iter = { SELECT LASTNAME , FIRSTNME , SALARY FROM DSN8710.EMP WHERE SALARY BETWEEN :min AND :max }; do { #sql { FETCH :iter INTO :lastname, :firstname, :salary }; // Print row... } while (!iter.endFetch()); iter.close(); |
| JDBC | SQLJ |
|---|---|
PreparedStatement stmt = conn.prepareStatement( "SELECT MAX(SALARY), AVG(SALARY)" + " FROM DSN8710.EMP"); rs = stmt.executeQuery(); if (!rs.next()) { // Error—no rows found } maxSalary = rs.getBigDecimal(1); avgSalary = rs.getBigDecimal(2); if (rs.next()) { // Error—more than one row found } rs.close(); stmt.close(); |
#sql [ctx] { SELECT MAX(SALARY), AVG(SALARY) INTO :maxSalary, :avgSalary FROM DSN8710.EMP }; |
| JDBC | SQLJ |
|---|---|
stmt = conn.prepareStatement( "INSERT INTO DSN8710.EMP " + "(EMPNO, FIRSTNME, MIDINIT, LASTNAME, HIREDATE, SALARY) " + "VALUES (?, ?, ?, ?, CURRENT DATE, ?)"); stmt.setString(1, empno); stmt.setString(2, firstname); stmt.setString(3, midinit); stmt.setString(4, lastname); stmt.setBigDecimal(5, salary); stmt.executeUpdate(); stmt.close(); |
#sql [ctx] { INSERT INTO DSN8710.EMP (EMPNO, FIRSTNME, MIDINIT, LASTNAME, HIREDATE, SALARY) VALUES (:empno, :firstname, :midinit, :lastname, CURRENT DATE, :salary) }; |