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. 【转载】VC操作剪切板

    1.在剪切板上放置数据 if(OpenClipboard())    //打开剪切板{    EmptyClipboard(); //清空剪切板    CString str;       //从控件 ...

  2. pygame系列_pygame的各模块叙述

    在pygame中,有很多模块,每个模块对应着不同的功能,如果我们知道这些模块是做什么的,那么,对我们的游戏开发会起到关键性的作用. 我们就说说pygame中的各个模块吧!!! #pygame modu ...

  3. Codeforces Round #361 (Div. 2) C. Mike and Chocolate Thieves 二分

    C. Mike and Chocolate Thieves 题目连接: http://www.codeforces.com/contest/689/problem/C Description Bad ...

  4. C#中常见的系统内置委托用法详解(抄录)

    C#中常见的系统内置委托 Action类.Func类.Predicate<T>.Comparison<T>委托 Action类的委托 Action委托 封装一个方法,该方法不具 ...

  5. PostgreSQL增强版命令行客户端(pgcli)

    效果: 安装: https://www.pgcli.com/install 官网: https://www.pgcli.com/

  6. Redis在Windows+linux平台下的安装配置(转)

    window平台Redis安装 下载地址: http://code.google.com/p/servicestack/wiki/RedisWindowsDownload Redis文件夹有以下几个文 ...

  7. java转换emoji表情

    /** * @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式(表情占4个字节,需要utf8mb4字符集) * @param str * 待转换字符串 ...

  8. Xcode GDB 调试

    关于GDB 对于大多数Cocoa程序员来说,最常用的debugger莫过于Xcode自带的调试工具了.而实际上,它正是gdb的一个图形化包装.相对于gdb,图形化带来了很多便利,但同时也缺少了一些重要 ...

  9. win7 启动管理器修改默认启动项

    最近给我的超级本做了系统备份,以防万一,但是备份完成后,系统启动的时候总会首先进入Windows启动管理器,且默认启动项是Ghost,还需要选择一下才能进入Win7系统,如何解决这个问题呢? 方案一: ...

  10. Selenium2+python自动化29-js处理多窗口

    前言 在打开页面上链接的时候,经常会弹出另外一个窗口(多窗口情况前面这篇有讲解:Selenium2+python自动化13-多窗口.句柄(handle)),这样在多个窗口之间来回切换比较复杂,那么有没 ...