使用 SQL 陳述式參數可以讓您建立可重複使用的 SQL 陳述式。當您使用陳述式參數時,陳述式之中的值可以變更 (例如正在加入
INSERT
陳述式中的值),但基本的陳述式文字維持不變。所以,使用參數可提供效能上的優勢,同時也更容易撰寫應用程式的程式碼。
瞭解陳述式參數
應用程式經常會在應用程式中多次使用單一 SQL 陳述式,不過會稍做變化。例如,以存貨追蹤應用程式為例,使用者可以將新的存貨項目加入資料庫。將存貨項目加入資料庫的應用程式程式碼會執行 SQL
INSERT
陳述式,此陳述式會實際將資料加入至資料庫。但是,每次執行陳述式,陳述式就會有些微的改變。明確地說,也就是,插入資料表中的實際值會不同,因為這些值屬於正在加入的存貨項目。
當您具有會在陳述式中以不同的值多次使用之 SQL 陳述式時,最佳的做法就是使用包含參數的 SQL 陳述式,而不要在 SQL 文字中使用常值。參數是陳述式文字中的預留位置,會在每次執行陳述式時以實際的值取代。若要在 SQL 陳述式中使用參數,請依一般做法建立
SQLStatement
實體。對於實際指定給
text
屬性的 SQL 陳述式,請使用參數預留位置,而不要使用常值。然後,請設定 SQLStatement 實體之
parameters
屬性中元素的值,以定義每個參數的值。
parameters
屬性是關聯陣列,因此請使用下列語法來設定特定的值:
statement.parameters[parameter_identifier] = value;
如果您使用命名的參數,則
parameter_identifier
會是字串;如果您使用未命名的參數,就會是整數索引。
使用命名的參數
參數可以是命名的參數。命名的參數具有特定的名稱,可供資料庫用來比對參數值及其陳述式文字中的預留位置。參數名稱會包含「:」或「@」字元,後面加上名稱,如下列範例所示:
:itemName
@firstName
下面列出的程式碼會示範命名的參數用法:
var sql:String =
"INSERT INTO inventoryItems (name, productCode)" +
"VALUES (:name, :productCode)";
var addItemStmt:SQLStatement = new SQLStatement();
addItemStmt.sqlConnection = conn;
addItemStmt.text = sql;
// set parameter values
addItemStmt.parameters[":name"] = "Item name";
addItemStmt.parameters[":productCode"] = "12345";
addItemStmt.execute();
使用未命名的參數
除了使用命名的參數之外,您也可以使用未命名的參數。若要使用未命名的參數,請在 SQL 陳述式中使用「?」字元表示參數。每個參數都會根據陳述中參數的順序指定數字索引,第一個參數從索引 0 開始。下列範例會示範在上一個範例中使用未命名參數的版本:
var sql:String =
"INSERT INTO inventoryItems (name, productCode)" +
"VALUES (?, ?)";
var addItemStmt:SQLStatement = new SQLStatement();
addItemStmt.sqlConnection = conn;
addItemStmt.text = sql;
// set parameter values
addItemStmt.parameters[0] = "Item name";
addItemStmt.parameters[1] = "12345";
addItemStmt.execute();
使用參數的優點
在 SQL 陳述式中使用參數有多項優點:
-
效能更佳
-
使用參數的 SQLStatement 實體執行起來會比在每次執行時以動態方式建立 SQL 文字的實體更有效率。效能改進的最大原因在於,陳述式只會準備一次,之後就能使用不同的參數值執行多次,而不必重新編譯 SQL 陳述式。
-
明確的資料輸入
-
使用參數後,便可以將建構 SQL 陳述式時未知的值取代為所輸入資料。使用參數是唯一可確保傳入資料庫之值使用儲存類別的方式。如果不使用參數,執行階段會嘗試將所有的值根據關聯欄的類型相似性,從文字形式轉換成儲存類別。
如需儲存類別和欄相似性的詳細資訊,請參閱
資料類型支援
。
-
更高的安全性
-
使用參數可協助避免稱為 SQL 插入式攻擊的惡意技巧。在 SQL 插入式攻擊中,使用者會在使用者可存取的位置 (例如,資料輸入欄位) 輸入 SQL 程式碼。如果應用程式程式碼是直接將使用者輸入連接至 SQL 文字中以建構 SQL 陳述式,則使用者所輸入的 SQL 程式碼會針對資料庫來執行。以下列出的程式碼會示範將使用者輸入連接至 SQL 文字中的範例,
請勿使用此技巧
:
// assume the variables "username" and "password"
// contain user-entered data
var sql:String =
"SELECT userId " +
"FROM users " +
"WHERE username = '" + username + "' " +
" AND password = '" + password + "'";
var statement:SQLStatement = new SQLStatement();
statement.text = sql;
使用陳述式參數來取代將使用者輸入值連接至陳述式的文字,可以防止 SQL 插入式攻擊。由於參數值會視為明確的替代值,而不是陳述式文字常值的一部分,因此不會發生 SQL 插入。以下為上述程式碼範例的建議替代方式:
// assume the variables "username" and "password"
// contain user-entered data
var sql:String =
"SELECT userId " +
"FROM users " +
"WHERE username = :username " +
" AND password = :password";
var statement:SQLStatement = new SQLStatement();
statement.text = sql;
// set parameter values
statement.parameters[":username"] = username;
statement.parameters[":password"] = password;
|
|
|