在ADO.NET中经常需要跟各种数据库打交道,在不实用存储过程的情况下,使用参数化SQL语句一定程度上可以防止SQL注入,同时对一些较难赋值的字段(如在SQL Server中Image字段,在Oracle中Clob字段等)使用参数化SQL语句很容易就能赋值,所以本人经常在ADO.NET中使用参数化SQL语句,近几年来陆续跟SQL Server/Oracle/ MySQL/Access打交道,积累了一些心得,现在整理出来供大家参考。
我们假设数据可的结构如下图(设置的数据库为Oracle10g):
它在SQL Server中的创建语句是:
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
///
发表网址:http://blog.csdn.net/zhoufoxcn/archive/2008/03/19/2195618.aspx
///
</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
///
发表网址:
http://blog.csdn.net/zhoufoxcn/archive/2008/03/19/2195618.aspx
///
</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
///
发表网址:http://blog.csdn.net/zhoufoxcn/archive/2008/03/19/2195618.aspx
///
</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
;
}
}
在Access中增加同样一条记录的代码如下:
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
///
发表网址:
http://blog.csdn.net/zhoufoxcn/archive/2008/03/19/2195618.aspx
///
</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一样使用”@”),如果那位朋友看过本文,我想他就会解开这个疑虑了。