参数化查询
✍ dations ◷ 2025-06-06 17:49:05 #数据库,网络安全,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 之内。
相关
- 霾霾(英语:haze,又称雾霾、烟霾、烟霞等)是一种由固体颗粒形成的空气污染,其核心物质是空气中悬浮的灰尘颗粒,气象学上称为气溶胶颗粒。霾中含有数百种大气化学颗粒物质,它们在人们毫
- 法国亦陷入反殖民战争泥潭阿尔及利亚战争是1954年至1962年期间阿尔及利亚争取独立的武装力量与法国之间的战争,最终法国同意阿尔及利亚独立。美国政府支持法国维持他们的殖民地。贾迈勒·阿卜杜-纳赛
- 子宫内膜息肉子宫内膜息肉,为子宫内膜局限性增长,在宫颈内形成息肉样突起。其发病原因包括两类,一个是机体一系列功能紊乱。另一个为子宫内膜基底层发生的小肿瘤,增殖发育进入内膜功能差,月经
- 峇峇娘惹料理娘惹菜是流行于东南亚新加坡,马来西亚,印度尼西亚和泰国等地的美食。起源来自于早期定居于槟城,马六甲,新加坡的中国移民。娘惹菜取名于娘惹,指的是中国移民和马来原住民通婚的女
- 货物崇拜科学货物崇拜科学(英文:Cargo cult science)出自美国物理学家理查·费曼于1974年于加州理工学院的一场毕业典礼演说,描述某些事物类似科学,却遗漏了“科学的品德,也就是进行科学思考时
- 奥兰治亲王国奥兰治亲王国(法语:Principauté d'Orange),又称奥兰治公国,是一个位于现今法国南部普罗旺斯地区、亚维侬以北一段罗纳河左岸的亲王国(公国)。1163年,时任神圣罗马帝国皇帝腓特烈一
- 帕斯夸尔·约尔旦帕斯夸尔·约尔旦(德语:Pascual Jordan,1902年10月18日-1980年7月31日),又译约当,德国理论和数学物理学家,他在量子力学和量子场论方面做出非常重要的贡献。他在数学形式的矩阵力学
- 土蜗属见内文土蜗属(学名:)为一种会呼吸空气的淡水螺物种,属于椎实螺科的有肺类腹足纲软体动物。本属最广为人知的物种为截口土蜗()。本属物种已知从侏罗纪就已出现,到现在仍有现生种本属
- 北碚鳄属北碚鳄属(学名:)是种已灭绝海鳄类,属于真蜥鳄科,生存于侏罗纪托阿尔阶的中国;2003年在吉尔吉斯的卡洛维阶地层,也发现北碚鳄的破碎化石。模式种是长鼻北碚鳄()。
- 伊万·瓦西里耶维奇·斯皮里多诺夫伊万·瓦西里耶维奇·斯皮里多诺夫(俄语:Иван Васильевич Спиридонов,1905年10月10日(23日)-1991年7月7日)他是苏联最高苏维埃联盟院主席、苏联共产党中央