fbpx
维基百科

參數化查詢

參數化查詢(parameterized query 或 parameterized statement)是指在設計與資料庫連結並存取資料時,在需要填入數值或資料的地方,使用參數(parameter)來給值,這個方法目前已被視為最有效可預防SQL注入攻击的攻擊手法的防禦方式。

除了安全因素,相比起拼接字符串的SQL语句,参数化的查询往往有性能优势。因为参数化的查询能令不同的数据通过参数到达数据库,从而共用同一条SQL语句。大多数数据库会缓存解释SQL语句产生的字节码而省下重复解析的开销。如果采取拼接字符串的SQL语句,则会由于操作数据是SQL语句的一部分而非参数的一部分,而反复大量解释SQL语句产生不必要的开销。

原理

在使用參數化查詢的情況下,資料庫伺服器不會將參數的內容視為SQL指令的一部份來處理,而是在資料庫完成SQL指令的編譯後,才套用參數執行,因此就算參數中含有具破壞性的指令,也不會被資料庫所執行。

SQL指令撰寫方法

在撰寫SQL指令時,利用參數來代表需要填入的數值,例如:

Microsoft SQL Server

Microsoft SQL Server的參數格式是以"@"字元加上參數名稱而成,SQL Server亦支援匿名參數"?"。

 SELECT * FROM myTable WHERE myID = @myID 
 INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4) 

Microsoft Access

Microsoft Access不支援具名參數,只支援匿名參數"?"。

 UPDATE myTable SET c1 = ?, c2 = ?, c3 = ? WHERE c4 = ? 

MySQL

MySQL的參數格式是以"@"字元加上參數名稱而成。

set @c1 := xxx; set @c2 := xxx;  set @c3 := xxx; set @c4 := xxx; UPDATE myTable SET c1 = @c1, c2 = @c2, c3 = @c3 WHERE c4 = @c4 

PostgreSQL/SQLite

PostgreSQLSQLite的参数格式是以“:”加上参数名而成。当然,也支持类似Access的匿名参数。

 UPDATE "myTable" SET "c1" = :c1, "c2" = :c2, "c3" = :c3 WHERE "c4" = :c4 

用戶端程式撰寫方法

在用戶端程式碼中撰寫使用參數的程式碼,例如:

ADO.NET

ADO.NET用於ASP.NET之內。

SqlCommand sqlcmd = new SqlCommand("INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)", sqlconn); sqlcmd.Parameters.AddWithValue("@c1", 1); // 設定參數@c1的值。 sqlcmd.Parameters.AddWithValue("@c2", 2); // 設定參數@c2的值。 sqlcmd.Parameters.AddWithValue("@c3", 3); // 設定參數@c3的值。 sqlcmd.Parameters.AddWithValue("@c4", 4); // 設定參數@c4的值。 sqlconn.Open(); sqlcmd.ExecuteNonQuery(); sqlconn.Close(); 

PDO

PDO用於PHP之內。在使用PDO驱动时,参数查询的使用方法一般为:

// 实例化数据抽象层对象 $db = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=testdb'); // 对SQL语句执行prepare,得到PDOStatement对象 $stmt = $db->prepare('SELECT * FROM "myTable" WHERE "id" = :id AND "is_valid" = :is_valid'); // 绑定参数 $stmt->bindValue(':id', $id); $stmt->bindValue(':is_valid', true); // 查询 $stmt->execute(); // 获取数据 foreach($stmt as $row) { var_dump($row); } 

对于MySQL的特定驱动,也可以这样使用:

$db = new mysqli("localhost", "user", "pass", "database"); $stmt = $db -> prepare("SELECT priv FROM testUsers WHERE username=? AND password=?"); $stmt -> bind_param("ss", $user, $pass); $stmt -> execute(); 

值得注意的是,以下方式虽然能有效防止SQL注入(归功于mysql_real_escape_string函数的转义),但并不是真正的参数化查询。其本质仍然是拼接字符串的SQL语句。

$query = sprintf("SELECT * FROM Users where UserName='%s' and Password='%s'", mysql_real_escape_string($Username), mysql_real_escape_string($Password)); mysql_query($query); 

ODBC/JDBC

ODBC 使用 C 样式的函数 / 句柄接口,而 JDBC 用於 Java 之內。

//C/C++, Microsoft Windows ODBC TCHAR szStatement[]=TEXT("select * from table where col1=?"); HSTMT hStmt; SQLAllocHandle(SQL_HANDLE_STMT, hDBC, &sRet.hStmt); SQLPrepare(hStmt, szStatement, SQL_NTS); int iValue=5; SQLLEN iLOI; SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, sizeof(iValue), 0, &iValue, sizeof(iValue), &iLOI); SQLExecute(hStmt); 
//JDBC java.sql.PreparedStatement prep = connection.prepareStatement( "SELECT * FROM users WHERE USERNAME = ? AND PASSWORD = ?"); prep.setString(1, username); prep.setString(2, password); prep.executeQuery(); 

Cold Fusion

<cfquery name="Recordset1" datasource="cafetownsend"> SELECT * FROM COMMENTS WHERE COMMENT_ID =<cfqueryparam value="#URL.COMMENT_ID#" cfsqltype="cf_sql_numeric"> </cfquery> 

參數化查詢, parameterized, query, parameterized, statement, 是指在設計與資料庫連結並存取資料時, 在需要填入數值或資料的地方, 使用參數, parameter, 來給值, 這個方法目前已被視為最有效可預防sql注入攻击的攻擊手法的防禦方式, 除了安全因素, 相比起拼接字符串的sql语句, 参数化的查询往往有性能优势, 因为参数化的查询能令不同的数据通过参数到达数据库, 从而共用同一条sql语句, 大多数数据库会缓存解释sql语句产生的字节码而省下重复解析的开销, 如. 參數化查詢 parameterized query 或 parameterized statement 是指在設計與資料庫連結並存取資料時 在需要填入數值或資料的地方 使用參數 parameter 來給值 這個方法目前已被視為最有效可預防SQL注入攻击的攻擊手法的防禦方式 除了安全因素 相比起拼接字符串的SQL语句 参数化的查询往往有性能优势 因为参数化的查询能令不同的数据通过参数到达数据库 从而共用同一条SQL语句 大多数数据库会缓存解释SQL语句产生的字节码而省下重复解析的开销 如果采取拼接字符串的SQL语句 则会由于操作数据是SQL语句的一部分而非参数的一部分 而反复大量解释SQL语句产生不必要的开销 目录 1 原理 2 SQL指令撰寫方法 2 1 Microsoft SQL Server 2 2 Microsoft Access 2 3 MySQL 2 4 PostgreSQL SQLite 3 用戶端程式撰寫方法 3 1 ADO NET 3 2 PDO 3 3 ODBC JDBC 3 4 Cold Fusion原理 编辑在使用參數化查詢的情況下 資料庫伺服器不會將參數的內容視為SQL指令的一部份來處理 而是在資料庫完成SQL指令的編譯後 才套用參數執行 因此就算參數中含有具破壞性的指令 也不會被資料庫所執行 SQL指令撰寫方法 编辑在撰寫SQL指令時 利用參數來代表需要填入的數值 例如 Microsoft SQL Server 编辑 Microsoft SQL Server的參數格式是以 字元加上參數名稱而成 SQL Server亦支援匿名參數 SELECT FROM myTable WHERE myID myID INSERT INTO myTable c1 c2 c3 c4 VALUES c1 c2 c3 c4 Microsoft Access 编辑 Microsoft Access不支援具名參數 只支援匿名參數 UPDATE myTable SET c1 c2 c3 WHERE c4 MySQL 编辑 MySQL的參數格式是以 字元加上參數名稱而成 set c1 xxx set c2 xxx set c3 xxx set c4 xxx UPDATE myTable SET c1 c1 c2 c2 c3 c3 WHERE c4 c4 PostgreSQL SQLite 编辑 PostgreSQL和SQLite的参数格式是以 加上参数名而成 当然 也支持类似Access的匿名参数 UPDATE myTable SET c1 c1 c2 c2 c3 c3 WHERE c4 c4用戶端程式撰寫方法 编辑在用戶端程式碼中撰寫使用參數的程式碼 例如 ADO NET 编辑 ADO NET用於ASP NET之內 SqlCommand sqlcmd new SqlCommand INSERT INTO myTable c1 c2 c3 c4 VALUES c1 c2 c3 c4 sqlconn sqlcmd Parameters AddWithValue c1 1 設定參數 c1的值 sqlcmd Parameters AddWithValue c2 2 設定參數 c2的值 sqlcmd Parameters AddWithValue c3 3 設定參數 c3的值 sqlcmd Parameters AddWithValue c4 4 設定參數 c4的值 sqlconn Open sqlcmd ExecuteNonQuery sqlconn Close PDO 编辑 PDO用於PHP之內 在使用PDO驱动时 参数查询的使用方法一般为 实例化数据抽象层对象 db new PDO pgsql host 127 0 0 1 port 5432 dbname testdb 对SQL语句执行prepare 得到PDOStatement对象 stmt db gt prepare SELECT FROM myTable WHERE id id AND is valid is valid 绑定参数 stmt gt bindValue id id stmt gt bindValue is valid true 查询 stmt gt execute 获取数据 foreach stmt as row var dump row 对于MySQL的特定驱动 也可以这样使用 db new mysqli localhost user pass database stmt db gt prepare SELECT priv FROM testUsers WHERE username AND password stmt gt bind param ss user pass stmt gt execute 值得注意的是 以下方式虽然能有效防止SQL注入 归功于mysql real escape string函数的转义 但并不是真正的参数化查询 其本质仍然是拼接字符串的SQL语句 query sprintf SELECT FROM Users where UserName s and Password s mysql real escape string Username mysql real escape string Password mysql query query ODBC JDBC 编辑 ODBC 使用 C 样式的函数 句柄接口 而 JDBC 用於 Java 之內 C C Microsoft Windows ODBC TCHAR szStatement TEXT select from table where col1 HSTMT hStmt SQLAllocHandle SQL HANDLE STMT hDBC amp sRet hStmt SQLPrepare hStmt szStatement SQL NTS int iValue 5 SQLLEN iLOI SQLBindParameter hStmt 1 SQL PARAM INPUT SQL C LONG SQL INTEGER sizeof iValue 0 amp iValue sizeof iValue amp iLOI SQLExecute hStmt JDBC java sql PreparedStatement prep connection prepareStatement SELECT FROM users WHERE USERNAME AND PASSWORD prep setString 1 username prep setString 2 password prep executeQuery Cold Fusion 编辑 lt cfquery name Recordset1 datasource cafetownsend gt SELECT FROM COMMENTS WHERE COMMENT ID lt cfqueryparam value URL COMMENT ID cfsqltype cf sql numeric gt lt cfquery gt 取自 https zh wikipedia org w index php title 參數化查詢 amp oldid 71749981, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。