在討論JDBC Statement教學文章時,我們已經學習了如何在JDBC中使用儲存過程。 本教學文章與該部分類似,但它將講解演示有關JDBC SQL跳脫語法的其他資訊。
就像Connection
物件建立Statement
和PreparedStatement
物件一樣,它可使用同樣的方式建立CallableStatement
物件,該物件將用於執行對資料庫儲存過程的呼叫。
假設需要執行以下Oracle儲存過程 -
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;
注意:上面的儲存過程是為Oracle編寫的,但是如果使用MySQL資料庫,參考以下程式碼為MySQL編寫相同的儲存過程,如下在
EMP
資料庫中建立它 -
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 ;
存在三種型別的引數:IN
,OUT
和INOUT
。 PreparedStatement
物件只使用IN
引數。 CallableStatement
物件可以使用上面三種型別引數。
以下是上面三種型別引數的定義 -
引數 | 描述 |
---|---|
IN | 建立SQL語句時其引數值是未知的。 使用setXXX() 方法將值系結到IN 引數。 |
OUT | 由SQL語句返回的引數值。可以使用getXXX() 方法從OUT引數中檢索值。 |
INOUT | 提供輸入和輸出值的引數。使用setXXX() 方法系結變數並使用getXXX() 方法檢索值。 |
以下程式碼片段顯示了如何使用Connection.prepareCall()
方法根據上述儲存過程來範例化一個CallableStatement
物件 -
CallableStatement cstmt = null;
try {
String str = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
String變數str
表示儲存過程,帶有引數預留位置。
使用CallableStatement
物件與使用PreparedStatement
物件很像。 在執行語句之前,必須將值系結到所有引數,否則將收到一個SQLException
異常。
如果有IN
引數,只需遵循適用於PreparedStatement
物件的相同規則和技術; 使用與系結的Java資料型別相對應的setXXX()
方法。
使用OUT
和INOUT
引數時,必須使用一個額外的CallableStatement
物件方法registerOutParameter()
。 registerOutParameter()
方法將JDBC資料型別系結到儲存過程預期返回的資料型別。
當呼叫儲存過程後,可以使用適當的getXXX()
方法從OUT
引數中檢索該值。 此方法將檢索到的SQL型別的值轉換為Java資料型別。
就像關閉其他Statement物件一樣,由於同樣的原因(節省資源),還應該關閉CallableStatement
物件。
簡單的呼叫close()
方法將執行關閉工作。 如果先關閉Connection
物件,它也會關閉CallableStatement
物件。 但是,應該始終顯式關閉CallableStatement
物件,以確保正確的順序清理。
CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
cstmt.close();
}
有關更多的細節,建議學習研究「Callable範例程式碼」
通過使用標準JDBC方法和屬性,跳脫語法使您能夠靈活地使用不可用的資料庫特定功能。
一般SQL跳脫語法格式如下 -
{keyword 'parameters'}
以下是以下跳脫序列,在執行JDBC程式設計時非常有用 -
d, t, ts關鍵字
它們用於幫助確定日期,時間和時間戳文字。沒有哪兩個DBMS表示時間和日期的方式相同。 該跳脫語法告訴驅動程式以目標資料庫的格式呈現日期或時間。 例如 -
{d 'yyyy-mm-dd'}
yyyy
=年份,mm
=月份; dd
=日期。 使用這種語法{d'2019-09-03'}
表示的是2019年3月9日。
這是一個簡單的範例,顯示如何將日期插入表中 -
//Create a Statement object
stmt = conn.createStatement();
//Insert data ==> ID, First Name, Last Name, DOB
String sql="INSERT INTO STUDENTS VALUES" +
"(100,'Kobe','Bryant', {d '2002-12-16'})";
stmt.executeUpdate(sql);
同樣,還可以使用以下兩種語法:t
或ts
-
{t 'hh:mm:ss'}
這裡,hh
=小時,mm
=分鐘, ss
=秒。 使用這種語法{t '13:30:29'}
是1:30:29 PM
。
{ts 'yyyy-mm-dd hh:mm:ss'}
這裡「d
」和「t
」是上述兩種語法的組合語法來表示時間戳。
escape關鍵字
escape
關鍵字標識LIKE
子句中使用跳脫字元。 使用SQL萬用字元%
(與0
個或多個字元匹配)時很有用。 例如 -
String sql = "SELECT symbol FROM MathSymbols
WHERE symbol LIKE '\%' {escape '\'}";
stmt.execute(sql);
如果使用反斜槓字元(\
)作為跳脫字元,則還必須在Java字串文字中使用兩個反斜槓字元,因為反斜槓也是Java跳脫字元。
fn 關鍵字
這個關鍵字表示DBMS中使用的標量函式。 例如,可以使用SQL函式長度來獲取字串的長度 -
{fn length('Hello World')}
上面語句返回結果值為:11
,也就是字串’Hello World
‘的長度。
call 關鍵字
此關鍵字用於呼叫儲存過程。 例如,對於需要IN
引數的儲存過程,請使用以下語法 -
{call my_procedure(?)};
對於需要IN
引數並返回OUT
引數的儲存過程,請使用以下語法 -
{? = call my_procedure(?)};
oj關鍵字
此關鍵字用於表示外部連線。 語法如下 -
{oj outer-join}
這裡,outer-join = table {LEFT|RIGHT|FULL} OUTERJOIN {table | outer-join} 搜尋條件。 例如 -
String sql = "SELECT Employees
FROM {oj ThisTable RIGHT
OUTER JOIN ThatTable on id = '100'}";
stmt.execute(sql);