当前位置: 首页 > 图文教程 > 数据库 > MSSQL > LINQ to SQL:处理char(1)字段的方式会引起全表扫描问题

MSSQL
无数据库日志文件恢复数据库方法两则(一)
SQLServer编写存储过程小工具(一)
SQLServer编写存储过程小工具(二)
SQLServer编写存储过程小工具(三)
Eclipse+JBoss+MySQL开发环境设置
MYSQL使用简述
一些有用的sql语句实例
枚举SQLServer的实例
SQLServer应用程序中的高级SQL注入
SQL Server数据库超级管理员账号防护知识
讲解如何实现互联网上数据库的安全
SQL 2005数据库转到SQL 2000的步骤讲解
带你轻松接触数据库生成xml的两个方法
用MS SQL Reporting Services生成报表
保护SQL Server的十个步骤
关于SQL SERVER的一些安全问题
SQL Server 2008数据库中使用表值参数
SQL Server 2005中用存储过程实现搜索功能
MS SQL数据库置疑解决办法
SQL Server密码管理的六个危险判断

MSSQL 中的 LINQ to SQL:处理char(1)字段的方式会引起全表扫描问题


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

1.相关内容: 在SQL Server 2000中,如果数据库的排序规则为Chinese_PRC_CI_AS,那么查询时是不分大小写的,例如下列这二条SQL语句,查询的结果是一样的。

image

如果表中的字段类型为 char(1) 时,Linq to SQL生成char (System.Char)的属性,如下图

image image
表定义 生成的实体

2.

如果要查询LineCode=='A'的记录,可以这样定义Linq查询语句

var test1 = from p in db.ProductLines
where p.LineCode =='A'
select p;

生成的SQL语句是这样的

SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount]
FROM [dbo].[ProductLine] AS [t0]
WHERE UNICODE([t0].[LineCode]) = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [65]
-- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.21022.8

注意到Where语句了吗?是WHERE UNICODE([t0].[LineCode]) = 65,这里先取LineCode列内容的UNICODE再和'A'的UNICODE比较。我们知道'A'和'a'的UNICODE是不同的。UNICODE('A') =65,UNICODE('a')=97,也就是说,我们在Linq to SQL中这二个查询的结果是不一样的。

Linq 语句
var test1 = from p in db.ProductLines
where p.LineCode =='a'
select p;
var test1 = from p in db.ProductLines
where p.LineCode =='A'
select p;
生成SQL语句
SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount]
FROM [dbo].[ProductLine] AS [t0]
WHERE UNICODE([t0].[LineCode]) = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [97]
SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount]
FROM [dbo].[ProductLine] AS [t0]
WHERE UNICODE([t0].[LineCode]) = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [65]

明显,在Linq to sql是查询char(1)类型字段是区分大小写的

这还会导致一个比较严重的问题,我们知道在SQL Server中,任何在运算符左边的操作都会使SQL采用全表扫描。也就是说,Linq的这个查询,会引起全表扫描,即使[LineCode]列上定义了聚合索引。而如果是where [linecode]='A',则可以使用索引。我们看下这二种情况时的查询执行计划对比。

image

图中可以看出,Linq to SQL 生成的SQL语句是表扫描,而后者则是索引查找。

3.

对策

在DBML设计器中将LineCode改成string类型。

image

看一下改了之后的查询

var test1 = from p in db.ProductLines
where p.LineCode == "a"
select p;
SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount]
FROM [dbo].[ProductLine] AS [t0]
WHERE [t0].[LineCode] = @p0
-- @p0: Input VarChar (Size = 1; Prec = 0; Scale = 0) [a]
-- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.21022.8
Linq sql

改为string后,生成的SQL不再用UNICODE函数了,就解决了区分大小写和引起全表扫描的问题。但又引起一个新的问题,因为数据库中存储的数据长度是1,在Insert和Update时就要注意,LineCode不要输入过长的内容,否则会出错了。