參數化查詢

https://zh.wikipedia.org/wiki/%E5%8F%83%E6%95%B8%E5%8C%96%E6%9F%A5%E8%A9%A2

参数化查询(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的参数格式是以"?"字元加上参数名称而成。

 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

客户端程序撰写方法[编辑]

在客户端代码中撰写使用参数的代码,例如:

 
 

对于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);

 

posted @ 2016-01-13 17:32  jimshi  阅读(245)  评论(0编辑  收藏  举报