在學(xué)習(xí)JDBC-語句一章的同時(shí),我們學(xué)習(xí)了如何在JDBC中使用存儲(chǔ)過程。本章與該部分相似,但是它將為您提供有關(guān)JDBC SQL轉(zhuǎn)義語法的更多信息。
就像 Connection 對象創(chuàng)建 Statement 和 PreparedStatement 對象一樣,它也創(chuàng)建 CallableStatement 對象,該對象將用于執(zhí)行對數(shù)據(jù)庫存儲(chǔ)過程的調(diào)用。
假設(shè)您需要執(zhí)行以下Oracle存儲(chǔ)過程-
CREATE OR REPLACE PROCEDURE getEmpName (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS BEGIN SELECT first INTO EMP_FIRST FROM Employees WHERE ID = EMP_ID; END;
NOTE: 上面的存儲(chǔ)過程已經(jīng)為Oracle編寫,但是我們正在使用MySQL數(shù)據(jù)庫,因此,讓我們?yōu)镸ySQL編寫相同的存儲(chǔ)過程,如下所示,以便在EMP數(shù)據(jù)庫中創(chuàng)建它-
DELIMITER $$ DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$ CREATE PROCEDURE `EMP`.`getEmpName` (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255)) BEGIN SELECT first INTO EMP_FIRST FROM Employees WHERE ID = EMP_ID; END $$ DELIMITER ;
存在三種類型的參數(shù):IN,OUT和INOUT。PreparedStatement對象僅使用IN參數(shù)。CallableStatement對象可以使用所有這三個(gè)對象。
這是每個(gè)的定義-
范圍 | 描述 |
---|---|
IN | 創(chuàng)建SQL語句時(shí)其值未知的參數(shù)。使用setXXX()方法將值綁定到IN參數(shù)。 |
OUT | 其值由返回的SQL語句提供的參數(shù)。使用getXXX()方法從OUT參數(shù)中檢索值。 |
INOUT | 同時(shí)提供輸入和輸出值的參數(shù)??梢允褂?setXXX ()方法綁定變量,并使用 getXXX ()方法檢索值。 |
以下代碼片段顯示了如何基于前面的存儲(chǔ)過程使用該方法實(shí)例化對象-Connection.prepareCall()CallableStatement
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt =conn.prepareCall(SQL); . . . } catch (SQLException e) { . . . } finally { . . . }
字符串變量SQL代表帶有參數(shù)占位符的存儲(chǔ)過程。
使用CallableStatement對象與使用PreparedStatement對象非常相似。您必須在執(zhí)行該語句之前將值綁定到所有參數(shù),否則您將收到一個(gè)SQLException。
如果有 IN 參數(shù),只需遵循應(yīng)用于 PreparedStatement 對象的相同規(guī)則和技術(shù); 使用與綁定的 Java 數(shù)據(jù)類型對應(yīng)的 setXXX ()方法。
當(dāng)使用 OUT 和 INOUT 參數(shù)時(shí),必須使用附加的 CallableStatement 方法 registerOutParameter ()。registerOutParameter ()方法將 JDBC 數(shù)據(jù)類型綁定到預(yù)期存儲(chǔ)過程返回的數(shù)據(jù)類型。
調(diào)用存儲(chǔ)過程后,可以使用適當(dāng)?shù)膅etXXX()方法從OUT參數(shù)中檢索值。此方法將檢索到的SQL類型的值轉(zhuǎn)換為Java數(shù)據(jù)類型。
就像關(guān)閉其他Statement對象一樣,出于同樣的原因,您也應(yīng)該關(guān)閉CallableStatement對象。
簡單的調(diào)用close()方法就可以了。如果先關(guān)閉Connection對象,它也會(huì)關(guān)閉CallableStatement對象。但是,您應(yīng)該始終顯式關(guān)閉CallableStatement對象,以確保正確清理。
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt =conn.prepareCall(SQL); . . . } catch (SQLException e) { . . . } finally { cstmt.close(); }
研究我們在可調(diào)用示例代碼中研究了更多的細(xì)節(jié)。
Escape 語法使您能夠靈活地使用標(biāo)準(zhǔn) JDBC 方法和屬性所不能使用的數(shù)據(jù)庫特定特性。
通用的SQL轉(zhuǎn)義語法格式如下-
{keyword 'parameters'}
以下是以下轉(zhuǎn)義序列,在執(zhí)行JDBC編程時(shí)您會(huì)發(fā)現(xiàn)它們非常有用-
它們可以幫助標(biāo)識日期、時(shí)間和時(shí)間戳的文本。如您所知,沒有兩個(gè) dbms 以相同的方式表示時(shí)間和日期。這種轉(zhuǎn)義語法告訴驅(qū)動(dòng)程序以目標(biāo)數(shù)據(jù)庫的格式呈現(xiàn)日期或時(shí)間。例如:
{d 'yyyy-mm-dd'}
其中yyyy =年,mm =月;dd =日。使用此語法{d'2009-09-03'}是2009年3月9日。
這是一個(gè)簡單的示例,顯示如何在表中插入日期-
//創(chuàng)建一個(gè)Statement對象 stmt = conn.createStatement(); //Insert data ==> ID, First Name, Last Name, DOB String sql="INSERT INTO STUDENTS VALUES" + "(100,'Zara','Ali', {d '2001-12-16'})"; stmt.executeUpdate(sql);
同樣,您可以使用以下兩種語法之一,t或者ts:
{t 'hh:mm:ss'}
其中hh =小時(shí);mm=分鐘; ss =秒。使用此語法{t '13:30:29'}是1:30:29 PM。
{ts 'yyyy-mm-dd hh:mm:ss'}
這是上面兩種語法的組合語法,其中'd'和't'代表時(shí)間戳。
此關(guān)鍵字標(biāo)識 LIKE 子句中使用的轉(zhuǎn)義字符。使用 SQL 通配符% 時(shí)非常有用,該通配符匹配零個(gè)或多個(gè)字符。例如:
String sql = "SELECT symbol FROM MathSymbols WHERE symbol LIKE '\%' {escape '\'}"; stmt.execute(sql);
如果將反斜杠字符(\)用作轉(zhuǎn)義字符,則還必須在Java String字面量中使用兩個(gè)反斜杠字符,因?yàn)榉葱备芤彩荍ava轉(zhuǎn)義字符。
此關(guān)鍵字表示DBMS中使用的標(biāo)量函數(shù)。例如,您可以使用SQL函數(shù)length來獲取字符串的長度-
{fn length('Hello World')}
這將返回11,即字符串“ Hello World”的長度。
此關(guān)鍵字用于調(diào)用存儲(chǔ)過程。例如,對于需要IN參數(shù)的存儲(chǔ)過程,請使用以下語法-
{call my_procedure(?)};
對于需要IN參數(shù)并返回OUT參數(shù)的存儲(chǔ)過程,請使用以下語法-
{? = call my_procedure(?)};
此關(guān)鍵字用于表示外部聯(lián)接。語法如下-
{oj outer-join}
其中,外部聯(lián)接=表{LEFT | RIGHT | FULL} OUTERJOIN {table | 搜索條件。例如-
String sql = "SELECT Employees FROM {oj ThisTable RIGHT OUTER JOIN ThatTable on id = '100'}"; stmt.execute(sql);