SqlServer日常积累(二)
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日常积累(二)的更多相关文章
- SqlServer日常积累(一)
1. 将一个表的数据插入另一个表 情况一:目标表已存在 (1)如果2张表的字段一致,并且希望插入全部数据,可以用这种方法: Insert Into 目标表 Select * From 来源表; --例 ...
- SqlServer日常积累(三)
1.TRUNCATE 和 DELETE TRUNCATE操作没有记录删除操作日志 主要的原因是因为 TRUNCATE 操作不会激活触发器,因为TRUNCATE操作不会记录各行删除操作的日志,所以当你需 ...
- 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)
解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...
- 日常英语---二、注册google的api的key
日常英语---二.注册google的api的key 一.总结 一句话总结:register google api key register_google_api_key 1.请通过电子邮件向我发送有关 ...
- SqlServer存储过程应用二:分页查询数据并动态拼接where条件
前言 开发中查询功能是贯穿全文的,我们来盘一盘使用存储过程分页查询,并且支持动态拼接where条件. 划重点:支持动态拼接where条件 对存储过程的使用有疑问的同学去[SqlServer存储过程的创 ...
- C# 之 日常积累(二)
主要涉及(1)数字前补0:(2)去掉decimal类型后边无效的0相关问题. 1.数字前补0 ; ) { returnnumber.ToString(); } else { returnnumber. ...
- c/c++(c++和网络编程)日常积累(二)
Linux下C编程通过宏定义打开和关闭调试信息 https://www.cnblogs.com/robinsons/p/3667032.html https://blog.csdn.net/u0134 ...
- SQL-Server使用点滴(二)
二,对象的建立和使用 1,了解MSSql的[系统表] 对于SQL-Server中的所有对象,包括数据库,数据表,记录,字段,触发器,索引,数据类型等元素,均有对应的系统表记性记录.系统表是禁止直接删改 ...
- LINUX日常操作二
参见:Linux日常操作一 selinux 开启和关闭 一.查看SELinux状态:1./usr/sbin/sestatus -v ##如果SELinux status参数为enabled ...
随机推荐
- HDU 2553 N皇后问题(深搜DFS)
N皇后问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- python mac环境搭建
安装 virtualenv $ sudo pip install virtualenv 然后建立一个测试目录: $ mkdir testvirtual $ cd testvirtual 就可以成功创建 ...
- Windows下ftp服务器搭建及配置
Win系统使用ser-u软件进行FTP服务器的搭建下载地址:https://www.serv-u.com/操作步骤如下:1. 点击执行程序进行按照SU-FTP-Server-Windows-v15.1 ...
- SoC嵌入式软件架构设计之七:嵌入式文件系统设计
嵌入式的系统区(system disk,SD)包含操作系统.驱动.中间件.应用和字库.UI资源等文件,本文讲述SD区的文件系统设计.文件系统最基本的目标是为了实现单个文件的定位和读写.由于一般代码都是 ...
- Red Hat Enterprise Linux 7.4配置VSFTP服务器
vsftpd(very secure ftp daemon,非常安全的FTP守护进程)是一款运行在Linux操作系统上的FTP服务程序,不仅完全开源而且免费,此外,还具有很高的安全性.传输速度,以及支 ...
- java异常知识点汇总
异常处理方法 对于非运行时异常(checked exception),必须要对其进行处理,否则无法通过编译. 处理方式有两种: 1.使用try..catch..finally进行捕获: 2.在产生异常 ...
- Mongodb安全认证及Java调用
Mongodb安全认证在单实例和副本集两种情况下不太一样,单实例相对简单,只要在启动时加上 --auth参数即可,但副本集则需要keyfile. 一.单实例 1.启动服务(先不要加auth参数) 2. ...
- QtWebKit
WekKit官网:http://www.webkit.org/ QtWebKit官网及安装:http://trac.webkit.org/wiki/QtWebKit#GettingInvolved Q ...
- Python操作Excel表格,xlwt模块的使用
Python可以操作Excel的模块不止一种,我习惯使用的写入模块是xlwt(一般都是读写模块分开的) 按照模块使用pip install xlwt 就行了,很常规的方式 直接进代码解析,本文源码 w ...
- Android中样式及主题
Android应用程序中不可避免的需要使用的样式和主题,样式指定一般指定View的高度.字体.字体颜色.背景,Android里的样荐定义在Style.xml文件里.主题也是一种样式,只不过它是应用在整 ...