当前位置: 首页 > 图文教程 > 数据库 > 数据库技巧 > 带参数的sql和不带参数的sql存储过程区别

数据库技巧
执行Insert Exec时的隐藏开销 分析
datastage server job之dsjob 命令
sql Union和Union All的使用方法
对分区表进行alter-switch时遇到的错误
sql left join 命令详解
sql 插入数据的三种常用方法及小贴士
SQL 优化经验总结34条
数据库 SQL千万级数据规模处理概要
数据库分页查询方法
postgres 数据库中的数据转换
ORACLE 系统函数大全SQLSERVER系统函数的异同
数据库 三范式最简单最易记的解释
主键与聚集索引
数据库触发器(Trigger)的一点使用心得
postgresql sql批量更新记录
sql join on 用法
SQL 按特定字段值排序
jdbc 数据库的连接(sqlserver oracle)
让你的insert操作速度增加1000倍的方法
数据库 关系连接

数据库技巧 中的 带参数的sql和不带参数的sql存储过程区别


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 528 ::
收藏到网摘: n/a

来执行我们sql语句,看到很多分页存储过程都是直接拼凑sql语句然后用exec('')执行起来了,这个从效率和安全上面来说,都是不推荐的。 带参数的sql语句,在数据库端,执行的是
exec sp_executesql
eg:
exec sp_executesql N'insert into LCS_Sys_Model ([Model_GUID],[Model_Name],[Model_Desp],[Model_IsSys]) values ( @Model_GUID,@Model_Name,@Model_Desp,@Model_IsSys)', N'@Model_GUID uniqueidentifier,@Model_Name nvarchar(50),@Model_Desp nvarchar(500),@Model_IsSys bit', @Model_GUID = 'F3CD1369-58C0-4A1F-AF88-05FCF734E079', @Model_Name = N'测试实体模型', @Model_Desp = N'实体模型描述', @Model_IsSys = 0

没有带值的sql语句。其执行是直接的sql语句。
insert into lcs_Sys_Model ([Model_GUID],[Model_Name],[Model_Desp],[Model_IsSys]) values ( 'F3CD1369-58C0-4A1F-AF88-05FCF734E079','name','desp',1 )

看上面的执行代码,你会不会认为是下面的高效啊?说实话我也没有仔细测试过。可是据我所知,sqlserver能够缓存参数信息和sql编译后的信息,第一句带参 数的sql因为前面一部是不变的(红色部分)。所以能够缓存起来(就像执行存储过程一样)。而下面的一句sql。因为value后面的值总是不固定,因此 sqlserver总是认为是不同的sql语句。因此每次都要重新编译生成。
以上结论来源于下面的测试代码。
System.Data.SqlClient.SqlParameter[] parameters = {
new SqlParameter("@Model_GUID", SqlDbType.UniqueIdentifier),
new SqlParameter("@Model_Name", SqlDbType.NVarChar,50),
new SqlParameter("@Model_Desp", SqlDbType.NVarChar,500),
new SqlParameter("@Model_IsSys", SqlDbType.Bit)
};
parameters[0].Value = new Guid("F3CD1369-58C0-4A1F-AF88-05FCF734E079");
parameters[1].Value = "测试实体模型";
parameters[2].Value = "实体模型描述";
parameters[3].Value = false;

string connStr = @"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=officially;Data Source=LCSNB"SQL2K";
string cmdStr = "insert into LCS_Sys_Model ([Model_GUID],[Model_Name],[Model_Desp],[Model_IsSys]) values ( @Model_GUID,@Model_Name,@Model_Desp,@Model_IsSys)";
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr);
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(cmdStr);
cmd.Connection = conn;
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
来执行我们sql语句,看到很多分页存储过程都是直接拼凑sql语句然后用exec('')执行起来了,这个从效率和安全上面来说,都是不推荐的。
cmd.Connection.Open();
cmd.ExecuteNonQuery();
//第一次执行结束
cmd.Parameters.Clear();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
//System.Diagnostics.Debug.Assert(cmd.ExecuteScalar()==null);
Console.WriteLine(cmd.ExecuteScalar().ToString());
//第二次执行结束
cmd.Connection.Close();
Console.WriteLine("第一次测试结束");
Console.Read();
cmd.CommandText = "insert into lcs_Sys_Model ([Model_GUID],[Model_Name],[Model_Desp],[Model_IsSys]) values ( 'F3CD1369-58C0-4A1F-AF88-05FCF734E079','name','desp',1 )";
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
Console.WriteLine(cmd.ExecuteScalar().ToString());
cmd.Connection.Close();
Console.WriteLine("第二次测试结束");
Console.Read();

本来想用参数化的sql插入一条记录再取回自增的值的。发现数据库端是这个执行方式。那就没戏啦。。。只能改变sql语句。把自增放到sql的最后去取啦。。
exec sp_executesql N'insert into LCS_Sys_Model ([Model_GUID],[Model_Name],[Model_Desp],[Model_IsSys]) values ( @Model_GUID,@Model_Name,@Model_Desp,@Model_IsSys)', N'@Model_GUID uniqueidentifier,@Model_Name nvarchar(50),@Model_Desp nvarchar(500),@Model_IsSys bit', @Model_GUID = 'F3CD1369-58C0-4A1F-AF88-05FCF734E079', @Model_Name = N'测试实体模型', @Model_Desp = N'实体模型描述', @Model_IsSys = 0
SELECT SCOPE_IDENTITY()

在查询分析器里面最后确认运行一下。。。这二个是不同的范围的,是取不到值的。。

最后提配一点,为了性能和安全,我们在写存储过程的时候也要使用
exec sp_executesql '带参数的sql语句','参数定义语句,多个参数用,号分隔',参数赋值1,参数赋值2,参数赋值3```
来执行我们sql语句,看到很多分页存储过程都是直接拼凑sql语句然后用exec('')执行起来了,这个从效率和安全上面来说,都是不推荐的。