参数化查询
✍ dations ◷ 2025-08-01 07:40:34 #数据库,网络安全,SQL
参数化查询(parameterized query 或 parameterized statement)是指在设计与数据库链接并访问资料时,在需要填入数值或资料的地方,使用参数(parameter)来给值,这个方法目前已被视为最有效可预防SQL注入攻击的攻击手法的防御方式。
除了安全因素,相比起拼接字符串的SQL语句,参数化的查询往往有性能优势。因为参数化的查询能令不同的数据通过参数到达数据库,从而共享同一条SQL语句。大多数数据库会缓存解释SQL语句产生的字节码而省下重复解析的开销。如果采取拼接字符串的SQL语句,则会由于操作数据是SQL语句的一部分而非参数的一部分,而反复大量解释SQL语句产生不必要的开销。
在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有具破坏性的指令,也不会被数据库所运行。
在撰写SQL指令时,利用参数来代表需要填入的数值,例如:
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用于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 之内。
相关
- 红大马哈鱼红鲑(学名:Oncorhynchus nerka),又称蓝背鲑(blueback salmon)、sockeye salmon,其陆封型又称为kokanee salmon,是一种生活在太平洋水域的鲑鱼。是粉红鲑和狗鲑以后第三多的品种。soc
- 捷1号作战捷号作战(しょうごうさくせん)是太平洋战争中日本大本营立案的作战计划之一。马里亚纳海战胜利的美军,在1944年7月9日,占领塞班岛。面临绝对国防圈被突破,7月24日,大本营策定‘陆
- 汤姆·威尔萨克托马斯·詹姆斯·维尔萨克(Thomas James Vilsack,1950年12月12日-),美国律师、政治家,美国民主党人。曾任爱荷华州州长(1999年-2007年),前任美国农业部长(2009-2017),他是奥巴马政府中完
- 抽象与具体抽象和具体(英语:Abstract and concrete)是这样一种分类,标志着一个术语描述的对象是否有物理上的指示物(英语:referent)。抽象对象(抽象客体,英语:abstract object)没有物理的实指,但是
- 无危物种无危物种又称低关注度物种,是国际自然保护联盟对物种保护现状分类之一,指现存的物种中被评估为不属于其他分类的物种。它们既不是濒危物种、也不是近危物种,亦不是需要保护生存
- 氯化亚金氯化亚金(氯化金(I)),又称一氯化金。是金元素的一种氯化物,化学式为AuCl。氯化亚金可以通过三氯化金的热分解来制备。虽然更高温度下如果氯气的压强合适它可以保持稳定,但是它在
- 维利·鲍迈斯特维利·鲍迈斯特(Willi Baumeister,1889年1月22日-1955年8月31日),德国画家、景观设计师、艺术教授、印刷工艺师。他从师于斯图加特大学赫尔策教授,早期的作品受法国绘画影响,色彩轻
- 樊维城樊维城(?-1643年),字紫盖,湖广黄冈县人,明朝政治人物。父樊玉衡,官全椒县知县。以太常寺少卿致仕。樊维城于万历四十七年(1619年)中进士。除浙江海盐县知县,迁礼部主事。天启七年(1627年
- 基里尔·科迪夫基里尔·科迪夫 (保加利亚语:Кирил Котев)(1982年4月18日-) 是一位保加利亚足球运动员,司职后卫,现效力于切尔诺莫雷。科迪夫的足球生涯从Gorublyane Vihar俱乐部开始。
- 高新武高新武(1949年11月30日-2010年5月3日),台湾新竹人,曾任检察官,是台湾司法改革运动的先驱,新党创党元老。高新武毕业于台湾大学法律系,司法官第十八期结业。1981年,担任桃园地检署检察