在ADO.NET中经常需要跟各种数据库打交道,在不实用存储过程的情况下,使用参数化SQL语句一定程度上可以防止SQL注入,同时对一些较难赋值的字段(如在SQL Server中Image字段,在Oracle中Clob字段等)使用参数化SQL语句很容易就能赋值,所以本人经常在ADO.NET中使用参数化SQL语句,近几年来陆续跟SQL Server/Oracle/ MySQL/Access打交道,积累了一些心得,现在整理出来供大家参考。
我们假设数据可的结构如下图(设置的数据库为Oracle10g):
create table S_Admin ( UserName varchar ( 60 ) not null , Password varchar ( 60 ) not null , Remark varchar ( 50 ) null , Mail varchar ( 120 ) not null , AddDate datetime null default GETDATE (), LoginDate datetime null default GETDATE (), LoginIP varchar ( 50 ) null , Active smallint null default 1 , LoginCount int null default 1 , Power int null default 0 , Departid int null default 0 , constraint PK_S_ADMIN primary key nonclustered (UserId) ) go 下面假设数据库的主键都采用了数据库的本地化技术解决了(例如在Access、SQL Server和MySQL中采用自增字段,在Oracle中使用了sequence结合触发器),假如在Oracle中向表中插入一记录的代码如下:
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data.OracleClient; /// <summary> /// 在Oracle中使用参数化SQL的例子 /// 代码编写:周公 /// 日期:2008-3-19 /// 发表网址: /// </summary> public class OracleUtil { public OracleUtil() { } public bool InsertAdmin( string userName, string password, string remark, string mail, int departId, int power) { string sql = " insert into S_Admin(UserName,Password,Remark,Mail,DepartId,Power)values(:UserName,:Password,:Remark,:Mail,:DepartId,:Power) " ; OracleConnection connection = new OracleConnection(); connection.ConnectionString = "" ; // 此处设置链接字符串 OracleCommand command = new OracleCommand(sql, connection); command.Parameters.Add( " :UserName " , OracleType.NVarChar, 60 ).Value = userName; command.Parameters.Add( " :Password " , OracleType.NVarChar, 60 ).Value = password; command.Parameters.Add( " :Remark " , OracleType.NVarChar, 60 ).Value = remark; command.Parameters.Add( " :Mail " , OracleType.NVarChar, 60 ).Value = mail; command.Parameters.Add( " :DepartId " , OracleType.Int32, 4 ).Value = departId; command.Parameters.Add( " :Power " , OracleType.Int32, 4 ).Value = power; connection.Open(); int rowsAffected = command.ExecuteNonQuery(); connection.Close(); command.Dispose(); return rowsAffected > 0 ; } } 在MySQL中增加同样一条记录的代码如下(需要到MySQL官方网站下载.net驱动程序):
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using MySql.Data; using MySql.Data.MySqlClient; /// <summary> /// 在MySQL中使用参数化SQL的例子 /// 代码编写:周公 /// 日期:2008-3-19 /// 发表网址: /// </summary> public class MySqlUtil { public MySqlUtil() { } public bool InsertAdmin( string userName, string password, string remark, string mail, int departId, int power) { string sql = " insert into S_Admin(UserName,Password,Remark,Mail,DepartId,Power)values(?UserName,?Password,?Remark,?Mail,?DepartId,?Power) " ; MySqlConnection connection = new MySqlConnection(); connection.ConnectionString = "" ; // 此处设置链接字符串 MySqlCommand command = new MySqlCommand(sql, connection); command.Parameters.Add( "? UserName " , MySqlDbType.VarChar, 60 ).Value = userName; command.Parameters.Add( "? Password " , MySqlDbType.VarChar, 60 ).Value = password; command.Parameters.Add( "? Remark " , MySqlDbType.VarChar, 60 ).Value = remark; command.Parameters.Add( "? Mail " , MySqlDbType.VarChar, 60 ).Value = mail; command.Parameters.Add( "? DepartId " , MySqlDbType.Int32, 4 ).Value = departId; command.Parameters.Add( "? Power " , MySqlDbType.Int32, 4 ).Value = power; connection.Open(); int rowsAffected = command.ExecuteNonQuery(); connection.Close(); command.Dispose(); return rowsAffected > 0 ; } } 在SQL Server中增加同样一条记录的代码如下:
using System; using System.Data; using System.Data.SqlClient; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; /// <summary> /// 在SQL Server中使用参数化SQL的例子 /// 代码编写:周公 /// 日期:2008-3-19 /// 发表网址: /// </summary> public class SqlUtil { public SqlUtil() { } public bool InsertAdmin( string userName, string password, string remark, string mail, int departId, int power) { string sql = " insert into S_Admin(UserName,Password,Remark,Mail,DepartId,Power)values(@UserName,@Password,@Remark,@Mail,@DepartId,@Power) " ; SqlConnection connection = new SqlConnection(); connection.ConnectionString = "" ; // 此处设置链接字符串 SqlCommand command = new SqlCommand(sql, connection); command.Parameters.Add( " @UserName " ,SqlDbType.NVarChar, 60 ).Value = userName; command.Parameters.Add( " @Password " , SqlDbType.NVarChar, 60 ).Value = password; command.Parameters.Add( " @Remark " , SqlDbType.NVarChar, 60 ).Value = remark; command.Parameters.Add( " @Mail " , SqlDbType.NVarChar, 60 ).Value = mail; command.Parameters.Add( " @DepartId " , SqlDbType.Int, 4 ).Value = departId; command.Parameters.Add( " @Power " , SqlDbType.Int, 4 ).Value = power; connection.Open(); int rowsAffected = command.ExecuteNonQuery(); connection.Close(); command.Dispose(); return rowsAffected > 0 ; } } using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data.OleDb; /// <summary> /// 在Access中使用参数化SQL的例子 /// 代码编写:周公 /// 日期:2008-3-19 /// 发表网址: /// </summary> public class AccessUtil { public AccessUtil() { } public bool InsertAdmin( string userName, string password, string remark, string mail, int departId, int power) { string sql = " insert into S_Admin(UserName,Password,Remark,Mail,DepartId,Power)values(?,?,?,?,?,?) " ; OleDbConnection connection = new OleDbConnection(); connection.ConnectionString = "" ; // 此处设置链接字符串 // 注意下面参数的顺序一定要按照sql语句中的插入的列的顺序赋值,否则一定会报异常 OleDbCommand command = new OleDbCommand(sql, connection); command.Parameters.Add( " ? " , OleDbType.LongVarWChar, 60 ).Value = userName; command.Parameters.Add( " ? " , OleDbType.LongVarWChar, 60 ).Value = password; command.Parameters.Add( " ? " , OleDbType.LongVarWChar, 60 ).Value = remark; command.Parameters.Add( " ? " , OleDbType.LongVarWChar, 60 ).Value = mail; command.Parameters.Add( " ? " , OleDbType.Integer, 4 ).Value = departId; command.Parameters.Add( " ? " , OleDbType.Integer, 4 ).Value = power; connection.Open(); int rowsAffected = command.ExecuteNonQuery(); connection.Close(); command.Dispose(); return rowsAffected > 0 ; } } 需要说明的是,除了Access之外,操作其它数据库可以不必要按照参数在SQL语句中出现的顺序添加进去一样可以正确执行,但是在Access中一定按照插入的列的顺序添加参数,因为“OLE DB.NET Framework 数据提供程序使用标有问号 (?) 的定位参数,而不使用命名参数(MSDN)”,所以给添加参数和赋值一定要按照列的顺序。
通过上面的例子,基本上可以总结出一个规律:在参数化 SQL 中参数名的格式跟其在存储过程中生命存储过程参数一致,例如在 Oracle 中存储过程参数一律以 ”:” 开头,在 MS SQL Server 中存储过程参数一律以 ”@” 开头,而在 MySQL 中存储过程( MySQL 从 5.0 以后版本支持存储过程)参数一律以“?”开头,所以在参数化 SQL 语句中参数名有些不一样(记得在 csdn 上有朋友提到过不知道为什么 MySQL 中参数化 SQL 语句中要用“? ” 而不是和 SQL Server 一样使用 ”@” ),如果那位朋友看过本文,我想他就会解开这个疑虑了。 本文转自周金桥51CTO博客,原文链接: http://blog.51cto.com/zhoufoxcn/167031,如需转载请自行联系原作者