参数化查询
✍ dations ◷ 2025-11-10 17:42:11 #数据库,网络安全,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 之内。
相关
- 群岛群岛(英语:archipelago或islands),又称岛群、列岛,是由一连串岛屿所组成的地形。英语的archipelago本字来自爱琴海(希腊语:αρχιπέλαγος),原指“主要的海”,源自希腊语arkhi
- 奥格尔索普县奥格尔索普县(Oglethorpe County, Georgia)是美国乔治亚州北部的一个县。面积1,145平方公里。根据美国2000年人口普查,共有人口12,635人。县治勒星顿(Lexington)。成立于1793年12
- ΝNu(大写Ν,小写ν,中文音译:纽),是第十三个希腊字母。大写Ν因形同拉丁字母N而不单独使用。小写ν用于:拉丁字母N及斯拉夫字母Н都是由Nu演变而成。
- 贝叶斯概率贝叶斯概率(英语:Bayesian probability)是由贝叶斯理论所提供的一种对概率的解释,它采用将概率定义为某人对一个命题信任的程度的概念。贝叶斯理论同时也建议贝叶斯定理可以用作
- 乾闼婆乾闼婆 gān tà pó(梵语:गन्धर्व,转写:Gandharva,巴利语:Gandhabba),在印度宗教中,是一种以香味为食的男性神,能表演音乐、节目;又音译为.mw-parser-output ruby.zy{text-alig
- 罗西尼焦阿基诺·安东尼奥·罗西尼(意大利语:Gioachino Antonio Rossini,1792年2月29日-1868年11月13日),意大利作曲家,他生前创作了39部歌剧以及宗教音乐和室内乐。罗西尼的父母都是音乐
- 北京话北京话、北京方言,属于汉语官话北京官话的京师片(亦称幽燕片京承小片),流传于北京市区。通常指的北京话是指北京市区的口音,不包括北京郊县的方言。说话人带有明显的儿化尾音,有人
- 虚构集《虚构集》(西班牙语:Ficciones)是阿根廷作家和诗人豪尔赫·路易斯·博尔赫斯最受欢迎的短篇小说集,经常被视为了解博尔赫斯作品的最佳入门读物。1941年,博尔赫斯第二部小说集《
- 王白渊王白渊(1902年11月3日-1965年10月3日),台湾彰化县二水乡惠民村人 ,新诗诗人,日文世代作家。自1918年从二水公学校毕业,考进台北师范学校,他在就读台北师范学校这段期间,认识日后与他
- 秀林秀林(满语:ᠰᡳᡠᠯᡳᠨ,穆麟德:,?年-1810年),又名秀琳,富察氏。清朝政治人物。监生出身。 乾隆四十一年(1776年)任吏部司务。四十五年(1780年)升吏部主事。四十六年(1781年)升吏部员外郎。