1. 特殊符号单引号“'”的使用
如果使用SQL语句拼接中用到了单引号“'”,此时需要双单引号“''”进行转义形式进行拼接替代;如果在字符串查询中遇到了单引号,此时也需要用双单引号“''”进行转义形式进行拼接替代,即可以用Replace函数进行替换处理,把出现的特殊的单引号“'”替换成双单引号“''”处理,这样才能正确查询;或者也可以使用char函数进行取代处理,具体为:char(39)替代,只能在SQL中替换处理,不能用在C#的DataTable中的Select函数中,因为它不支持char函数的查询。
2. Distinct、Group by、having、order by使用注意事项
SELECT COUNT(*) AS COUNT,REQUEST,METHOD FROM REQUESTMETH GROUP BY
REQUEST,METHOD HAVING (REQUEST ='FC.OCEAN.JOB.SERVER.CBIZOZBKHEADER' OR REQUEST='FC.Ocean.Job.Server.CBizOzDocHeader')
AND COUNT(*) >3
ORDER BY REQUEST
如上语句的注意事项
HAVING后的条件不能用别名COUNT>3 必须使用COUNT(*) >3,否则报:列名 'COUNT' 无效。
having 子句中的每一个元素并不一定要出现在select列表中,如上面的语句可以写成:
SELECT REQUEST,METHOD FROM REQUESTMETH GROUP BY
REQUEST,METHOD HAVING (REQUEST ='FC.OCEAN.JOB.SERVER.CBIZOZBKHEADER' OR REQUEST='FC.Ocean.Job.Server.CBizOzDocHeader')
AND COUNT(*) >3
ORDER BY REQUEST
SELECT COUNT(*) AS COUNT,REQUEST,METHOD FROM REQUESTMETH GROUP BY
REQUEST,METHOD ORDER BY REQUEST
如果把该语句写成:
SELECT COUNT(*) AS COUNT,REQUEST,METHOD FROM REQUESTMETH GROUP BY
REQUEST ORDER BY REQUEST
那么将报:
选择列表中的列 'REQUESTMETH.method' 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
注意:
1、使用GROUP BY 子句时,SELECT 列表中的非汇总列必须为GROUP BY 列表中的项。
2、分组时,所有的NULL值分为一组。
3、GROUP BY 列表中一般不允许出现复杂的表达试、显示标题以及SELECT列表中的位置标号。
如:SELECT REQUEST,METHOD, COUNT(*) AS COUNT FROM REQUESTMETH GROUP BY
REQUEST,2 ORDER BY REQUEST 是错误的。
错误信息为:每个 GROUP BY 表达式都必须包含至少一个列引用。
SELECT COUNT(*) AS COUNT, MAX(BOOKID) AS MAXBOOKID,CATEGORYID FROM BOOK
WHERE DOTNUMBER >10 GROUP BY CATEGORYID
HAVING MAX(BOOKID) < 50
ORDER BY CATEGORYID
以上语句:先过滤出点击率大于10的,然后按类型(CATEGORYID )进行分组,再过滤出每组的最大值小于50个
行,最后进行按CATEGORYID进行排序。
GROUP BY 中使用 ORDER BY注意事项:
SELECT COUNT(*) AS COUNT FROM REQUESTMETH GROUP BY REQUEST,METHOD ORDER BY REQUEST,METHOD
--这样是允许的, ORDER BY后面的字段包含在GROUP BY 子句中
SELECT COUNT(*) AS COUNTS FROM REQUESTMETH GROUP BY REQUEST ORDER BY COUNT(*) DESC
--这样是允许的,ORDER BY后面的字段包含在聚合函数中,结果集同下面语句一样
SELECT COUNT(*) AS COUNTS FROM REQUESTMETH GROUP BY REQUEST ORDER BY COUNTS DESC
--这样是允许的,区别于HAVING,HAVING后不允许跟聚集函数的别名作为过滤条件
SELECT COUNT(*) AS COUNTS FROM REQUESTMETH GROUP BY REQUEST ORDER BY METHOD
--这样是错误的:ORDER BY 子句中的列 "REQUESTMETH.method" 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
SELECT DISTINCT 中使用 ORDER BY注意事项:
SELECT DISTINCT BOOKID FROM BOOK ORDER BY BOOKNAME
以上语句将报:
--如果指定了SELECT DISTINCT,那么ORDER BY 子句中的项就必须出现在选择列表中。
因为以上语句类似
SELECT BOOKID FROM BOOK GROUP BY BOOKID ORDER BY BOOKNAME
其实错误信息也为:
--ORDER BY子句中的列"BOOK.BookName" 无效,因为该列没有包含在聚合函数或GROUP BY 子句中。
应该改为:SELECT DISTINCT BOOKID,BOOKNAME FROM BOOK ORDER BY BOOKNAME
SELECT DISTINCT BOOKID,BOOKNAME FROM BOOK
SELECT BOOKID,BOOKNAME FROM BOOK GROUP BY BOOKID,BOOKNAME
以上两句查询结果是一致的,DISTINCT的语句其实完全可以等效的转换为GROUP BY语句。
3. 聚合函数:Max,Min,Count,Sum等
当聚合函数出现在查询列中时,查询的其他列要么出现在聚合函数中要么出现在分组当中,即其他列使用聚合函数或者出现在Group by当中;这是由聚合函数的含义决定的,当然SQL语法也必然要求这样做的。
4. Top语句,分页查询
当使用Top语句时,SQL内部查询机制要求必须使用order by进行排序(虽然语法不要求,即不会报错),但是如果不进行排序使用Top语句,查询的结果就会出现按正常次序随机获取,可能达不到我们预想的查询结果,例如:分页查询
5. In子查询
当使用not in子句时,不能使用条件查询的不等号"<>"进行替换,含义不一样。下面简单模拟其区别:例如:学生表Student有10条记录,而成绩表Result有7条记录,要查询没有参加考试的学生信息(3个学生没有参加考试)。使用not in能正确地查询出来,即:select * from Student where StudentNo not in(select StudentNo from Result)
如何使用不等号"<>"进行替换进行查询,查询语句如下:
select * from Student inner join Result on Student.StudentNo<>Result.StudentNo
其查询的结果为:10*7-7条记录,即有63个查询结果,与我们使用not in子句差别非常大。重要原因是因为不等号"<>"的这种内连接查询把一个表中的每条记录与另一个表中的每条记录都进行比较查询,即类似"cross join"交叉连接比较的含义。
从而也能得出并不是所有的子查询都能用表连接替换,但是由于子查询的含义非常丰富,表连接的含义比较单调,所以表连接都能用子查询进行替换。
6. 索引(Index)使用
SQL Server索引在实际操作中其他的注意事项,“水可载舟,亦可覆舟”,SQL Server数据库的索引也一样。索引有助于提高检索性能,但过多或不当的索引也会导致系统低效。
因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片。
所以说,我们要建立一个“适当”的索引体系,特别是对聚合SQL Server索引的创建,更应精益求精,以使您的数据库能得到高性能的发挥。
当然,在实践中,作为一个尽职的数据库管理员,您还要多测试一些方案,找出哪种方案效率最高、最为有效。
改善SQL语句
很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解。比如:
select * from table1 where name=''zhangsan'' and tID > 10000和执行: select * from table1 where tID > 10000 and name=''zhangsan''
一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合SQL Server索引,那么后一句仅仅从表的10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name=''zhangsan''的,而后再根据限制条件条件tID>10000来提出查询结果。
事实上,这样的担心是不必要的。SQL SERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。
虽然查询优化器可以根据where子句自动的进行查询优化,但大家仍然有必要了解一下“查询优化器”的工作原理,如非这样,有时查询优化器就会不按照您的本意进行快速查询。
在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用SQL Server索引快速获得所需数据。
SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的AND连接。形式如下:
列名 操作符 <常数 或 变量>
或
<常数 或 变量> 操作符列名列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如:
Name=’张三’
价格>5000
5000<价格
Name=’张三’ and 价格>5000如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个SQL Server索引对于不满足SARG形式的表达式来说是无用的。