1、Like运算符:将字符串表达式与 SQL表达式中的模式进行比较匹配。

语法 :expression Like 'pattern' ,expression为匹配字段,pattern为匹配字符串。可以通过 Like 运算符来查找与所指定的模式相匹配的字段值。对于 pattern,可以指定完整的值(例如 Like "Smith"),也可以使用通配符来查找某个范围内的值(例如 Like "Sm*")。

下表展示了如何通过 Like 来测试不同模式的表达式。


匹配类型

模式
匹配
(返回 True
不匹配
(返回 False
多个字符 a*a  或  a%a aa, aBa, aBBBa aBC
  *ab*  或  %ab% abc, AABB, Xab aZb, bac
特殊字符 a[*]a a*a aaa
多个字符 ab*  或  ab% abcdefg, abc cab, aab
单个字符 a?a  或  a_a aaa, a3a, aBa aBBBa
单个数字 a#a a0a, a1a, a2a aaa, a10a
字符范围 [a-z] f, p, j 2, &
范围之外 [!a-z] 9, &, % b, a
非数字值 [!0-9] A, a, &, ~ 0, 1, 9
复合值 a[!b-m]# An9, az0, a99 abc, aj0

可以用于 Like 运算符的通配符,如下表:

pattern 中的字符 expression 中的匹配
? 或 _(下划线) 任何单个字符
* 或 % 零个或多个字符
# 任何单个数字 (0 — 9)
[charlist] 在 charlist 中的任何单个字符。
[!charlist] 不在 charlist 中的任何单个字符。

2、T-sql大小写

大写T-SQL 语言的所有关键字都使用大写,规范要求。

3、使用终止符" ; "

使用" ; "作为 Transact-SQL 语句终止符。虽然分号不是必需的,但使用它是一种好的习惯,对于合并操作MERGE语句的末尾就必须要加上" ; ",(cte表表达式除外)。

4、避免使用以下数据类型以下

避免使用ntext、text 和 image 数据类型,用 nvarchar(max)、varchar(max) 和 varbinary(max)替代。后续版本会取消ntext、text 和 image 该三种类型。

5、查询条件不要使用计算列

例如year(createdate)=2014 , 使用 createdate >= '20140101' and createdate <= '20141231' 来取代。

(1)使用计算列查询(走的是索引扫描);(2)不使用计算列查询(走的是索引查找)。对比两个查询显然绝大部分情况下走索引查找的查询性能要高于走索引扫描,特别是查询的数据库不是非常大的情况下,索引查找的消耗时间要远远少于索引扫描的时间。

6、建表时字段不允许为null,可设默认值

很多人在建表的时候不会注意这一点,在接下来的工作中当你需要查询数据的时候你往往需要在WHERE条件中多加一个判断条件IS NOT NULL,这样的一个条件不仅仅增加了额外的开销,而且对查询的性能产生很大的影响,有可能就因为多了这个查询条件导致你的查询变的非常的慢;还有一个比较重要的问题就是允许为空的数据可能会导致你的查询结果出现不准确的问题。如下:

T-SQL是三值逻辑(true,flase,unknown)
IF OBJECT_ID('DBO.Customer','U') IS NOT NULL DROP TABLE DBO.Customer
GO
CREATE TABLE DBO.Customer
(Customerid int not null );
GO
IF OBJECT_ID('DBO.OrderS','U') IS NOT NULL DROP TABLE DBO.OrderS
GO
CREATE TABLE DBO.OrderS
(Orderid int not null,
custid int);
GO
INSERT INTO Customer VALUES(1),(2),(3);
INSERT INTO OrderS VALUES(1,1),(2,2),(3,NULL); ----查询没有订单的顾客
SELECT Customerid FROM DBO.Customer WHERE Customerid NOT IN(SELECT custid FROM OrderS); ---分析为什么查询结果没有数据
/*
因为true,flase,unknown都是真值
因为not in 是需要结果中返回flase值,not true=flase,not flase=flase,not unknown=unknown
因为null值是unknown所以not unknownn无法判断结果是什么值所以不能返回数据
*/ --可以将查询语句修改为
SELECT Customerid FROM DBO.Customer WHERE Customerid NOT IN(SELECT custid FROM OrderS WHERE custid is not null);
--或者使用EXISTS,因为EXISTS是二值逻辑只有(true,flase)所以不存在未知。
SELECT Customerid FROM DBO.Customer A WHERE NOT EXISTS(SELECT custid FROM OrderS WHERE OrderS.custid=A.Customerid ); ---in查询可以返回值,因为in是true,子查询true,flase,unknown都是真值所以可以返回子查询的true
SELECT Customerid FROM DBO.Customer WHERE Customerid IN(SELECT custid FROM OrderS); ----如果整形字段可以赋0,字符型可以赋值空(这里只是给建议)这里的空和NULL是不一样的意思 --增加整形字段可以这样写
ALTER TABLE TABLE_NAME ADD COLUMN_NAME INT NOT NULL DEFAULT(0) --增加字符型字段可以这样写
ALTER TABLE TABLE_NAME ADD COLUMN_NAME NVARCHAR(50) NOT NULL DEFAULT('')

7、分组统计时避免使用count(*)

---如果使用count(*)
SELECT Customerid,COUNT(*) FROM Customer TA LEFT JOIN OrderS TB ON TA.Customerid=TB.custid
GROUP BY Customerid ;

  

实际情况customerid=3是没有订单的,数量应该是0,但是结果是1,count()里面的字段是左连接右边的表字段,如果你用的是主表字段结果页是错误的。

----正确的方法是使用count(custid)
SELECT Customerid,COUNT(custid) FROM Customer TA LEFT JOIN OrderS TB ON TA.Customerid=TB.custid
GROUP BY Customerid;

  


7、子查询的表加上表别名

执行查询:SELECT Customerid FROM Customer  WHERE Customerid IN(SELECT Customerid FROM OrderS WHERE Orderid=2 );

      

正确查询结果下查询出的结果是没有customerid为3的值,仔细看应该会发现子查询的orders表中没有Customerid字段,所以SQL取的是Customer表的Customerid值作为相关子查询的匹配字段。

所以我们应该给子查询加上表别名,如果加上表别名,此时会有错误标示:“列名 'Customerid' 无效。”

SELECT Customerid FROM Customer WHERE Customerid IN(SELECT TB.Customerid FROM OrderS TB WHERE TB.Orderid=2 );

8、建立自增列时单独再给自增列添加唯一约束

CREATE TABLE TEST
(ID INT NOT NULL IDENTITY(1,1),
orderdate date NOT NULL DEFAULT(CURRENT_TIMESTAMP),
NAME NVARCHAR(30) NOT NULL,
CONSTRAINT CK_TEST_NAME CHECK(NAME LIKE '[A-Za-z]%' )
); GO
INSERT INTO TEST(NAME)
VALUES('A中'),('a名'),('Aa'),('ab'),('AA'),('az'); ----4.插入报错后,自增值依旧增加
INSERT INTO TEST(NAME)
VALUES('中');
GO
SELECT IDENT_CURRENT('TEST');
SELECT * FROM TEST; ---插入正常的数据
INSERT INTO TEST(NAME)
VALUES('cc'); SELECT IDENT_CURRENT('TEST')
SELECT * FROM TEST; ----5.显示插入自增值
SET IDENTITY_INSERT TEST ON INSERT INTO TEST(ID,NAME)
VALUES(8,'A中'); SET IDENTITY_INSERT TEST OFF ----会发现ID并不是根据自增值排列的,而且根据插入的顺序排列的
SELECT IDENT_CURRENT('TEST');
SELECT * FROM TEST; ----6.插入重复的自增值
SET IDENTITY_INSERT TEST ON INSERT INTO TEST(ID,NAME)
VALUES(8,'A中'); SET IDENTITY_INSERT TEST OFF SELECT IDENT_CURRENT('TEST')
SELECT * FROM TEST;
---所以如果要保证ID是唯一的,单单只设置自增值不行,需要给字段设置主键或者唯一约束
DROP TABLE TEST;

9、查询时一定要指定字段查询

(1)查询时一定不能使用" * "来代替字段来进行查询,无论你查询的字段有多少个,就算字段太多无法走索引也避免了解析" * "带来的额外消耗;

(2)查询字段值列出想要的字段,避免出现多余的字段,字段越多查询开销越大而且可能会因为多列出了某个字段而引起查询不走索引。

所以建议在查询语句中列出你需要的字段,而不是为了方便用*来查询所有的字段,如果真的需要查询所有的字段也同样建议把所有的字段列出来取代" * "。

10、尽量使用存储过程

优势:

[1]减少网络通信量。调用一个行数不多的存储过程与直接调用SQL语句的网络通信量可能不会有很大的差别,可是如果存储过程包含上百行SQL语句,那么其性能绝对比一条一条的调用SQL语句要高得多。

[2]执行速度更快。有两个原因:首先,在存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程缓存计划,这样下次再执行同样的存储过程时,可以从内存中直接调用。

[3]更强的适应性:由于存储过程对数据库的访问是通过存储过程来进行的,因此数据库开发人员可以在不改动存储过程接口的情况下对数据库进行任何改动,而这些改动不会对应用程序造成影响。

[4]布式工作:应用程序和数据库的编码工作可以分别独立进行,而不会相互压制。

[5]更好的封装移植性。

[6]安全性,它们可以防止某些类型的 SQL 插入攻击。

注:执行存储过程在第一次执行SQL语句时产生,缓存在内存中,这个缓存的计划一直可用,直到 SQL Server 重新启动,或直到它由于使用率较低而溢出内存。
默认情况下,存储过程将返回过程中每个语句影响的行数。如果不需要在应用程序中使用该信息,请在存储过程中使用 :SET NOCOUNT ON 语句以终止该行为。根据存储过程中包含的影响行的语句的数量,这将删除客户端和服务器之间的一个或多个往返过程。尽管这不是大问题,但它可以为高流量应用程序的性能产生负面影响。

SqlServer日常积累(二)的更多相关文章

  1. SqlServer日常积累(一)

    1. 将一个表的数据插入另一个表 情况一:目标表已存在 (1)如果2张表的字段一致,并且希望插入全部数据,可以用这种方法: Insert Into 目标表 Select * From 来源表; --例 ...

  2. SqlServer日常积累(三)

    1.TRUNCATE 和 DELETE TRUNCATE操作没有记录删除操作日志 主要的原因是因为 TRUNCATE 操作不会激活触发器,因为TRUNCATE操作不会记录各行删除操作的日志,所以当你需 ...

  3. 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)

    解剖SQLSERVER 第十二篇   OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...

  4. 日常英语---二、注册google的api的key

    日常英语---二.注册google的api的key 一.总结 一句话总结:register google api key register_google_api_key 1.请通过电子邮件向我发送有关 ...

  5. SqlServer存储过程应用二:分页查询数据并动态拼接where条件

    前言 开发中查询功能是贯穿全文的,我们来盘一盘使用存储过程分页查询,并且支持动态拼接where条件. 划重点:支持动态拼接where条件 对存储过程的使用有疑问的同学去[SqlServer存储过程的创 ...

  6. C# 之 日常积累(二)

    主要涉及(1)数字前补0:(2)去掉decimal类型后边无效的0相关问题. 1.数字前补0 ; ) { returnnumber.ToString(); } else { returnnumber. ...

  7. c/c++(c++和网络编程)日常积累(二)

    Linux下C编程通过宏定义打开和关闭调试信息 https://www.cnblogs.com/robinsons/p/3667032.html https://blog.csdn.net/u0134 ...

  8. SQL-Server使用点滴(二)

    二,对象的建立和使用 1,了解MSSql的[系统表] 对于SQL-Server中的所有对象,包括数据库,数据表,记录,字段,触发器,索引,数据类型等元素,均有对应的系统表记性记录.系统表是禁止直接删改 ...

  9. LINUX日常操作二

    参见:Linux日常操作一  selinux 开启和关闭 一.查看SELinux状态:1./usr/sbin/sestatus -v      ##如果SELinux status参数为enabled ...

随机推荐

  1. bzoj 3282

    回顾一下LCT,容易写错的地方: 1.每次断掉Splay中的边,必须update一下父亲节点,再根据具体情况是否splay父亲节点. 2.养成没有用的值(比如当pre[u]不为0时的pnt[u])不去 ...

  2. Python学习笔记(六)—元组的操作

    元祖也是一个列表,它和list的区别是元祖里面的元素无法修改: 如果元祖里面只有一个元素的话,那么你必须在这个元素后边加上逗号,这样才是元祖的类型:否则类型会显示其他类型 元组的定义: 元祖中的方法: ...

  3. document.all理解

    The all collection includes one element object for each valid HTML tag. If a valid tag has a matchin ...

  4. 百度地图api改变覆盖物背景实例及css颜色值简介

    在此鸣谢buptwusuopu的技术支持 在调用百度地图api的时候,为了改变覆盖物的颜色,如图中椭圆型的填充色.可以到百度api的库中查找方法http://developer.baidu.com/m ...

  5. dubbo白名单通过filter,spring web通过拦截器或者filter即可

    在开发中,有时候需要限制访问的权限,白名单就是一种方法.对于Java Web应用,Spring的拦截器可以拦截Web接口的调用:而对于dubbo接口,Spring的拦截器就不管用了. dubbo提供了 ...

  6. 【微信小程序】在微信开发工具上七牛云的图片可以看到,但是在真机上看不到的原因解决

    在开发微信小程序过程中,在微信开发者工具上,七牛云的图片都可以展示出来,但是在真机上,七牛云的图片却展示不出来,也没有报404找不到或者不能加载图片的问题, 必须保证: 1.图片是用image加载的: ...

  7. Spring Quartz 持久化解决方案

    Quartz是实现了序列化接口的,包括接口,所以可以使用标准方式序列化到数据库. 而Spring2.5.6在集成Quartz时却未能考虑持久化问题. Spring对JobDetail进行了封装,却未实 ...

  8. Windows和Linux下如何查看端口被哪个进程占用

    Windows: C:/Users/ewanbao>netstat -aon|findstr "123"  TCP    127.0.0.1:55123        0.0 ...

  9. pom-4.0.0.xml中心仓库

    <!--Licensed to the Apache Software Foundation (ASF) under oneor more contributor license agreeme ...

  10. Ganglia开源集群监视项目

    Ganglia是UC Berkeley发起的一个开源集群监视项目,设计用于测量数以千计的节点.Ganglia的核心包含gmond.gmetad以及一个Web前端.主要 是用来监控系统性能,如:cpu ...