为查询和管理关系型数据库管理系统(RDBMS--RelationalDatabaseManagementSystem)中的数据而专门设计的一种标准语言。
RDBMS是一种基于关系模型的数据库管理系统,而关系模型则是一种用于表示数据的语义模型。该模型基于两种数学理论:集合论和谓词逻辑。
关系模型是独立于语言的,除了SQL外,还可以用其他的语言来实现关系模型,例如,C#的类模型。
SQL是基于关系模型的ANSI和ISO标准语言。
SQL有几种不同类型的语句:
数据定义语言(DDL--DataDefinitionLanguage):用于处理数据对象的定义,包括Create、Alter、Drop语句。
数据处理语言(DML--DataManipulationLanguage):用于查询和修改数据,包括Select、Insert、Update、Delete、Merge语句。
数据控制语言(DCL--DataControlLanguage):用于处理权限管理,包括Grant,Revoke语句。
此书重点介绍的是DML数据处理语言。
集合
所谓集合是把我们直观或思维中确定的、不同的哪些对象作为一个整体来考虑的结果。这些对象就是集合的元素或成员。
谓词逻辑:TrueorFalse
约束:通过规则或约束来确保关系模型数据的完整性。
范式:
第一范式,表中的行必须是唯一的。属性应该是原子的(即列不可再拆分)。
第二范式,有两条,第一:首先必须满足第一范式;
第二要求非键属性和候选键属性之间必须满足一定的条件,对于每个候选键,每个非键属性都必须完全函数依赖于整个候选键。
第三范式,有两条,第一:首先必须满足第二范式;
第二所有非键属性必须非传递依赖于候选键。第二、第三范式概括起来讲:每个非键属性都依赖与键。
自己的话概括,第一范式,表中的各个列不可拆分,有明确的属性;
第二范式,在满足第一范式的同时,每个表还要有一个唯一的主键标识,通过主键可以查到这个实例的表中所有信息;
第三范式:在满足第二范式的同时,两表联合,不能通过两表的主键与主键联接,因存在表1的主键与表2的非主键联合。(救命实在是不知道怎么表达了...)
例子,员工表(employe),部门表(department),员工表中有员工编号,员工姓名,员工性别,员工住址,所属部门编号等等;部门表中有部门编号,部门名称,部门信息等等。
数据生命周期
联机事务处理(OLTP--OnLineTransctionalProcessing):重点是数据输入,主要处理的事务包括插入、更新删除数据。
数据仓库(DW--DataWarehouse):专门针对数据检索和生成报表而设计的环境。
当这样的环境服务于整个企业时,就称之为数据仓库;而只服务于企业一部分时,如一个特定的部门,就称之为数据集市(datamart)。
数据集市主要是为了支持数据检索,而对数据库仓库中的数据模型进行设计和优化。
联机分析处理(OLAP--OnLineAnalyticalProcessing)系统,支持对聚合后的数据进行动态的在线分析。
数据挖掘(DM--DataMining)由数据挖掘算法梳理数据,从中筛选出有用的信息。
文件扩展名
.mdf(MasterDataFile主数据文件)
.ndf(NotMasterDataFile非主数据文件)
.ldf(LogDataFile日志数据文件)
架构(Schema)和对象:
一个数据库包含多个架构,而每个架构又包含多个对象(对象可以是表,视图,存储过程等)。
可以在架构级别上控制对象的访问权限。表是属于架构,而架构又是属于数据库的。
CREATESCHEMAxxxAUTHORIZATIONdbo;
建表:
DB_ID(databaseName)returnint,函数接受一个数据库名称作为输入,返回它的内部数据库ID如果输入的数据库不存在,那么返回的将是NULL,这是检查数据库是否存在的简单方法。
--如果不存在testdb的数据库,那么重新创建一个叫testdb的数据库IFDB_ID('testdb')ISNULLCREATEDATABASEtestdb
select
select语句的目的是对表进行查询、应用一定的逻辑处理,并返回结果。
查询处理顺序
1.from
2.where
3.groupby
4.having
5.select
6.orderby
逻辑处理顺序
SELECTempid,YEAR(orderdate)ASorderyear,COUNT(*)ASnumordersFROMSales.OrdersWHEREcustid=71GROUPBYempid,YEAR(orderdate)HAVINGCOUNT(*)>1ORDERBYempid,orderyear--按照查询逻辑顺序--1.from--2.where--3.groupby--4.having--5.select--6.orderby--上面的select查询语句可解释成FROMSales.Orders--从Sales.Orders表中查询记录WHEREcustid=71--数据筛选,只留下custid=71的数据GROUPBYempid,YEAR(orderdate)--按照雇员id和订单年份进行分组HAVINGCOUNT(*)>1--分组后筛选,一年中下单超过1份的留下,不包括1SELECTempid,YEAR(orderdate)ASorderyear,COUNT(*)ASnumorders--select查询出来ORDERBYempid,orderyear--按照雇员id和年份排序
From子句
from子句是在逻辑阶段第一个要处理的查询子句。这个子句用于指定要查询的表名,以及对这些表进行操作的表运算符。
为了避免SQLServer自己主动隐式去解析一个对象的架构,我们有必要通过显示指定架构名称,这样既能保证得到的对象确实是你原来想要的又减少了一些额外的代价(隐式推算架构),还减少了有可能产生的错误。
Where子句
在where子句中,可以指定一个谓词或者逻辑表达式,从而过滤由from阶段返回的行,where阶段只返回让逻辑表达式为True的哪些行。
这里需要强调记忆的是:T-SQL使用的是三值谓词逻辑,True,False,Unknow
GroupBy子句
Groupby阶段可以将前面逻辑查询处理阶段返回的行按“组”进行组合。因为聚合函数只为每个组返回一个值,所以一个元素如果不在Groupby列表中出现。就只能作为聚合函数(count、sum、avg、min、max)的输入。
Having子句
Having子句用户指定对组装进行过滤的谓词或逻辑表达式。Having子句只会留下逻辑表达式为True组的数据,False和Unknow将会被过滤。
Select子句
select子句用于指定需要在查询返回的结果集中包含的属性(列),select列中的表达式可以直接基于正在查询的表的各个列上做进一步的处理。
关于别名
在select查询中,T-SQL允许查询返回没有名称的结果集列(但会没有列名),但关系模型不允许这样,所以最好是加上别名。
取别名的三种方式
除了<表达式>as<别名>这种格式,T-SQL还支持<别名>=<表达式>(别名等于表达式)和<表达式><别名>(表达式空格别名)三种方式,
不过最好还是用<...>as<...>这种方式,直观,方便阅读。关于取别名还有一个要注意的是,如:
把selectcol1,col2fromtable_1写成了selectcol1col2fromtable_1它还是成立的,只是本来查两列的,成了一列而且列名为col2了,这样的bug很不好被发现,所以要小心编写。
另一个易犯的错
select子句是在from、where、groupby、having子句之后处理的。这意味着对select子句之前处理的那些子句,在select子句中为表达式分配的别名不存在。如:
SELECTorderid,YEAR(orderdate)ASorderyearFROMSales.OrdersWHEREorderyear>2006这样做,是会报错的!因为逻辑顺序from,where...select,处理where阶段的时候,并没有别名orderyear,所以会报错:Invalidcolumnname'orderyear'.
Orderby子句(ASC升序<默认>DESC降序)
Orderby子句用于展示数据对输出结果中的进行排序。SQL最重要的一点:表不保证是有序的,因为表是为了代表一个集合,而集合是无序的。
Top选项
Top选项是T-SQL特有的,用于限制查询返回的行数或百分比。依靠了Orderby就会起到双重作用。在select阶段。
在Top选项中,还可以使用Percent关键字,如:selecttop(1)percent,id,name,agefromtabName
在top选项中,我们还可以加入withties选项
1.
SELECTTOP5*FROMSales.OrdersORDERBYcustidDESCSELECTTOP5WITHTIES*FROMSales.OrdersORDERBYcustidDESC
2.
DECLARE@tableTABLE(idINTNULL,AidINTNULL)INSERTINTO@table(id,Aid)VALUES(1,1)INSERTINTO@table(id,Aid)VALUES(2,1)INSERTINTO@table(id,Aid)VALUES(3,1)INSERTINTO@table(id,Aid)VALUES(4,2)INSERTINTO@table(id,Aid)VALUES(5,2)INSERTINTO@table(id,Aid)VALUES(6,2)INSERTINTO@table(id,Aid)VALUES(7,3)INSERTINTO@table(id,Aid)VALUES(8,3)INSERTINTO@table(id,Aid)VALUES(9,4)INSERTINTO@table(id,Aid)VALUES(10,4)INSERTINTO@table(id,Aid)VALUES(11,4)INSERTINTO@table(id,Aid)VALUES(12,5)INSERTINTO@table(id,Aid)VALUES(13,5)INSERTINTO@table(id,Aid)VALUES(14,6)INSERTINTO@table(id,Aid)VALUES(15,6)INSERTINTO@table(id,Aid)VALUES(16,6)INSERTINTO@table(id,Aid)VALUES(17,6)SELECTTOP5*FROM@tableORDERBYAiddescSELECTTOP5WITHTIES*FROM@tableORDERBYAidDESC
加入withties选项之后,可以筛选出更多的与最后一行相同值的其他行,更多更详细可看参考二。
Over子句开窗函数(windowfunction)
Over子句用于为行(row)一个窗口,以便进行特定的运算。可以把行的窗口简单的认为是运算将要操作的一个行的集合。
如果想对行(row)进行限制或者分区,这可以使用Partitionby子句。
如下,第一个查询的是所有行,二个查询的是所有价格的总和,三个则是查询当前客户(和当前行具有相同custid的所有行)的总价格,
Sum(val)Over(Partitionbycustid)
--1SELECTorderid,custid,valFROMSales.OrderValuesORDERBYcustidASC--2SELECTorderid,custid,val,SUM(val)OVER()AStotalValueFROMSales.OrderValuesORDERBYcustidASC--3SELECTorderid,custid,val,SUM(val)OVER(PARTITIONBYcustid)ASCurrTotalValueFROMSales.OrderValues
Over子句的一个有点就是能够在返回基本列的同时,在同一行对它们进行聚合;也可以在表达式中混合使用基本列和聚合值列。
SELECTorderid,custid,val,100*val/SUM(val)OVER()ASalltotal,--每行val占总val的百分比100*val/SUM(val)OVER(PARTITIONBYcustid)AStotalbyaustid--每行val占当行custid的总val的百分比FROMSales.OrderValuesOver子句也支持四种排名函数:ROW_NUMBER(行号)、RANK(排名)、DENSE_RANK(密集排名)NTILE。
SELECTorderid,custid,val,ROW_NUMBER()OVER(ORDERBYval)AS[rownum],RANK()OVER(ORDERBYval)AS[rank],DENSE_RANK()OVER(ORDERBYval)AS[dense_rank],NTILE(10)OVER(ORDERBYval)AS[ntile]FROMSales.OrderValues--图片1
row_number函数用于为查询的结果集中的各行分配递增的序列号,其逻辑顺序通过over子句中的orderby语句进行指定。
rank和dense_rank函数与row_number类似,但它们为具有相同逻辑排序值的所以行生产相同的排名。
rank和dense_rank函数的区别是如图1,如果rank有相同的val值,两个都是7,那么下一个rank的值是9,跳过了8;而dense_rank却不同,上两个是7,下面接上还是8;
ntile函数可以把结果中的行关联到组(tile,相当于由行组成的指定数目的组),并为每一行分配一个所属的组的编号。
比如,现在有一个集合是20条数据,利用ntile(5)函数,我将1-4条分为一组,组号为1,5-8一组,组号2这样以此类推。
ntile函数在逻辑上需要依赖与row_number函数。
整个过程是先根据对val的排序结果,为每一行分配行号,再等量分组,如果除不尽,如有22条数据要分10组,ntile(10),那么一二组将会有3条记录。
SELECT*,NTILE(10)OVER(ORDERBYval)AS[ntile]FROM(SELECTorderid,custid,val,ROW_NUMBER()OVER(ORDERBYval)AS[rownum]FROMSales.OrderValues)vWHERErownumBETWEEN1AND22图二
和聚合开窗函数一样,排名函数也支持在over子句中使用partitionby语句。rank、dense_rank与row_number差不多
SELECTorderid,custid,val,rank()OVER(PARTITIONBYcustidORDERBYval)AS[rownum]FROMSales.OrderValuesSELECTorderid,custid,val,NTILE(2)OVER(PARTITIONBYcustidORDERBYval)AS[rownum]FROMSales.OrderValues图三
加入了overdistincttop之后的SQL逻辑处理顺序
5.1over
5.2distinct
5.3top
如果想利用不同的val生成行号,不可以row_number和distinct同级使用,因为row_number是在distinct之前处理的,而且row_number是唯一的后面的distinct无效。
但我们可以采用下面两中方案。方法一,使用groupby,因为groupby是在select查询前执行的,二,利用子查询,筛除重复值后排序
--一SELECTval,ROW_NUMBER()OVER(ORDERBYval)AS[rownum]FROMSales.OrderValuesGROUPBYval--二SELECT*,ROW_NUMBER()OVER(ORDERBYval)AS[rownum]FROM(SELECTDISTINCTvalFROMSales.OrderValues)v图四
谓词和运算符
谓词:T-SQL支持的谓词包括IN、Between、以及Like。
in用于检查一个值(或标量表达式)是否与一组元素中的至少一个相等。
如:selectc1,c2,c3fromtab_1whereidin(1001,1101)
between用于检查一个值是否在一定的范围内,包括两个指定的边界值。
如:selectc1,c2,c3fromtab_1whereidbetween1and5--包括1和5
like用于检查一个字符串值是否与指定的模式匹配。
如:selectc1,c2,c3fromtab_1wherenamelike'%D%'
运算符:T-SQL支持的比较运算符=、>、<、>=、<=、<>、!=、!>、!<,最后三个运算符不是标准运算符
小数运算5/2整数等于2而不是2.5,如果想得到小数的话,可以这样
SELECTCAST(5ASNUMERIC(12,2))/CAST(2ASNUMERIC(12,2))
NUMERIC(12,2)这个数据类型的精确度为12,带有2位小数
SQL运算符的优先级1.()2.*,/,%3.+,-4.=,>,<,>=,<=,<>,!=,!>,!<(比较)5.not6.and7.between,in,like,or8.=(赋值)如下句子
SELECT*FROMSales.OrdersWHEREcustid=1ANDempidIN(1,3,5)ORcustid=85ANDempidIN(2,4,6)
因为and比or的优先级高,所以是先出现由客户1下的并由雇员1,3,5处理的订单,在返回由客户85下的并由雇员2,4,6处理的订单。
SELECT*FROMSales.OrdersWHERE(custid=1ANDempidIN(1,3,5))OR(custid=85ANDempidIN(2,4,6))圆括号的优先级最高,虽然我们在这里加上了,并没有改变他的逻辑运算,但明显的提高了代码的可读性,逻辑清晰了很多,这个一个很好的编程习惯!
Case表达式case表达式是一个标量表达式,它基于条件逻辑来返回一个值。
在这里值得注意的是,case是一个表达式,而不是一条语句,也就是说,不能用它来控制活动的流程,也不能根据条件逻辑来做某些处理。相反,它只是根据条件逻辑来返回某个值。
因为case是一个标量表达式,所以他可以支持任何标量表达式(如:select、where、having、orderby子句)check约束等等。case表达式有两种格式:简单表达式和搜索表达式。
简单格式:将一个值(或者一个标量表达式)与一组可能的取值进行比较,并返回第一个匹配的结果。
如果列表没有值等于测试值,case表达式就返回其else子句中列出的值。如果case表达式中没有else子句,这默认将其视为elsenull。
SELECTc1,c2,c3,c4,CASEempidWHEN1THEN'Monday'WHEN2THEN'Tuesday'WHEN3THEN'Wednesday'WHEN4THEN'Thursday'WHEN5THEN'Friday'WHEN6THEN'Saturday'WHEN7THEN'Sunday'ELSE'Unknow'ENDAS'aweek'FROMtable_1下面一个例子利用case与开窗函数(over),将集合中的数据根据val生成三个层次Low、Medium、High
SELECTorderid,custid,val,NTILE(3)OVER(ORDERBYval)ASTile,CASENTILE(3)OVER(ORDERBYval)WHEN1THEN'Low'WHEN2THEN'Medium'WHEN3THEN'High'ELSE'Unknow'ENDAS'TitleDesc'FROMSales.OrderValues图2部分截图
Case搜索表达式case简单表达式只有一个测试值(或表达式),它紧跟在case关键字后面,与where子句中的一组可能值进行比较。
而case搜索表达式要更灵活些,他可以在when子句中指定谓词或逻辑表达式,而不是只进行相等比较。
case搜索表达式返回结果为true的第一个when逻辑表达式所关联的then子句中指定的值。
如果没有任何when表达式结果为true,case表达式就返回else子句中出现的值(如果else子句也没指定,就返回null)。
SELECTorderid,custid,val,CASEWHENval<1000.00THEN'Lessthen1000'WHENvalBETWEEN1000.00AND3000.00THEN'Between1000and300'WHENval>3000.00THEN'Morethen3000'ELSE'Unkown'ENDAS'ValueCategory'FROMSales.OrderValues
NULL值
SQL用NULL符号来表示缺少的值。
null与三值谓词逻辑,
表达式salary>0,当salary等于1时,表达式的结果为true
当salary等于-1时,表达式的结果为false
当salary等于null时,表达式的结果为unknow
表达式null=null,其结果是unknow,不管什么值与null比较得到的逻辑值都是unknow在三值谓词逻辑中,接受true则会拒绝unknow,而拒绝false则会接受unknow。
where条件后面只接受为true的逻辑结果,如果想得到指定的值和列为NULL的集合,可以这样
SELECTc1,c2,c3,c4,c5FROMtableNameWHEREc1=''ORc1ISNULL在SQL中,有的时候又会认为两个NULL彼此相等,当进行分组和排序时,两个NULL值是相等的。
对于多个NULL的排序,ANSISQL把它留给了具体的产品实现。T-SQL是把NULL值排在了有效值之前。
ANSISQL有两种unique约束,一种是将多个null值视为相等的(值允许有一个null值),另一个则将多个null值视为不同的(允许有多个null值)。SQLServer只实现了前者。
同时操作(All-At-Once-Operation)这一章不是很理解,第二的例子完全在打P
概念:在同一逻辑查询处理阶段中出现的所有表达式都是同时进行计算的。
--来看SELECTorderid,orderdate,YEAR(orderdate)ASyearDate,yearDate+1ASnextyeatFROMSales.Orders--这样是不行的,看起来可行,但其实是会报错的Invalidcolumnname'yearDate'.--再来看SELECT*FROMSales.OrderDetailsWHEREcol1<>0ANDcol2/col1>2因为SQL存在同时操作的概念,上面的语句,我们担心出问题,so将条件改动,因为如果是col2/col1>2,遇到col=0就sb了。
--1SELECT*FROMSales.OrderDetailsWHERECASEWHENcol1=0THEN'no'WHENcol2/col1>2THEN'yes'ELSE'no'END='yes'--2SELECT*FROMSales.OrderDetailsWHEREcol1<>0ANDcol2>2*col1--3SELECT*FROMSales.OrderDetailsWHEREcol1<>0ANDcol2/2>col1数据类型
SQLServer支持两种字符数据类型:普通字符和Unicode字符
普通的字符数据类型包括char、varchar、变量表示'XXX'
Unicode字符数据类型包括Nchar、Nvarchar变量表示N'XXX'
二者的区别普通字符使用一个字节(byte)来保存每个字符,而Unicode字符则需要两个字节。普通字符只能代表256(2^8)个不同的字符,Unicode可以代表65536(2^16)个不同的字符。
char、Nchar都是固定长度的。比例char(25)长度就是25个字符,无法扩展。
Nchar、Nvarchar是可变长的。SQL会按照实际长度来保存数据,外加两个额外的自己以保存数据的偏移值。比例varchar(25)最多只能保存25个字符。
排序规则
排序规则是字符数据的一个属性,封装了几个方面的特征,包括多语言支持(和Unicode类型有关,因为它支持所有语言)、排序规则、区分大小写、区分重音,等等。
要得到系统中目前支持的所有排序规则及其描述,可以查询表函数sys.fn_helpcollations()
SELECT[name],[description]FROMsys.fn_helpcollations()例如,排序规则Latin1_General_CI_AS
Latin1_General支持的语言是英语
字典排序基于字段顺序对字符数据进行排序和比较('A'和'a'<'B'和'b')。
CI数据不区分大小写
AS数据区分重音
SQLServer实例的排序规则是在安装时设置的,他决定了所有系统数据库的排序规则,同时也是用户数据库默认使用的排序规则。
当创建用户数据库时,可以使用COLLATE子句指定数据库的排序规则。如果不指定,则默认采用SQLServer实例的排序规则。
如果想在列的排序规则是不区分大小写的前提下,让过滤条件区分大小写的,则可以按照如下所示的方法来修改表达式的排序规则:
--默认排序规则SELECTempid,firstname,lastnameFROMHR.EmployeesWHERElastname=N'davis'--利用表达式修改排序规则SELECTempid,firstname,lastnameFROMHR.EmployeesWHERElastnameCOLLATELatin1_General_CS_AS=N'davis'
分隔符
在标准SQL中,单引号用于分割文字字符串,而双引号用于分割不规则的标识符(表名或列名包含空格或以数据作为开始)。除了双引号分割符外,还有[]作为分隔符。
运算符和函数
--1SELECTregion,country,region+N','+countryAS'Address'FROMSales.Customers--如果region列的值为null的话,Address拼接的值也为NULL。--通过SETCONCAT_NULL_YIELDS_NULLOFF会话就可以改变SQLServer处理串联的方式--2SETCONCAT_NULL_YIELDS_NULLOFFSELECTregion,country,region+N','+countryAS'Address'FROMSales.CustomersSETCONCAT_NULL_YIELDS_NULLON--但是!强烈建议避免修改SQLServer的标准行为,大多数程序员(或接口)都默认代码会以标准行为来进行处理。--如果只是将NULL值用''替换,我们能用coalesce函数。--3SELECTregion,country,COALESCE(region,'')+N','+countryAS'Address'FROMSales.Customers
函数
T-SQL提供了一套字符串处理函数,其中包括substring、left、right、len、charindex、patindex、replace、replicate、stuff、upper、lower、rtrim、ltrim等等。
substring函数用于从字符串中提取子串。
语法substring(string,start,length)
start:从1开始,不能超过输入字符串的长度
length:从1开始,可超过输入字符串的长度,但只能取得输入长度的最长值。
该函数对输入的字符串进行处理,提取从指定位置开始,遇有特定长度的子字符串。
如:PRINTSUBSTRING('jolinson',1,10)--jolinson
left和right函数
left和right函数是substring函数的简略形式,他们分别返回输入字符串从左边或右边开始指定个数的字符。
left(string,n),right(string,n)
string要处理的字符串
n从字符的左边或右边提取的字符个数
PRINTLEFT('jolinson',8)--jolinson
PRINTRIGHT('jolinson',8)--jolinson
len和datalength函数
len函数返回输入字符串中的字符数。
语法
len(string)
datalength函数返回字符串字节数的长度。
datalength(string)
PRINTLEN('jolinson')--8PRINTDATALENGTH('jolinson')--8PRINTLEN(N'jolinson')--8PRINTDATALENGTH(N'jolinson')--16还有一个区别:len和datalength函数,前者不包含尾随空格,而后者会包含尾随的空格。
PRINTLEN('jolinson')--9PRINTDATALENGTH('jolinson')--10PRINTLEN(N'jolinson')--9PRINTDATALENGTH(N'jolinson')--20
charindex函数
charindex函数返回字符串中某个字符串第一次出现的起始位置。
charindex(substring,string,[,start_pos])
substring要搜索的字符
string输入的字符串,从这里找
start_pos开始位置,可选,如果没有从字符串第一个字符开始搜索
返回找到则出现第一次出现的位置,没找到则返回0
PRINTCHARINDEX('on','jolinson',6)--7
patindex函数
patindex函数返回字符串中某个模式第一次出现的起始位置。
patindex(pattern,string)
pattern通配符
string输入的string
PRINTPATINDEX('%[0-9]%','sdfas1321asdf')--6
replace函数
replace函数将字符串中出现的所有某个子字符串替换为另一个字符串。
replace(string,substring1,substring2)
将string中的substring1替换为substring2
PRINTREPLACE('1-2,2-3','-',':')--1:2,2:3
还可以利用replace函数计算出某个substring在string中出现的次数
SELECTcustid,contactname,LEN(contactname)-LEN(REPLACE(contactname,'a',''))AS'count'FROMSales.Customers
replicate函数
replicate函数以指定的次数复制字符串值
replicate(string,n)
string要被赋值的字符串
n复制的次数
PRINTREPLICATE('jolinson',3)--jolinsonjolinsonjolinson
利用replicate、right函数,成生列以0开头10位数字的数据
SELECTRIGHT(REPLICATE('0',9)+CAST(supplieridASVARCHAR(10)),10)ASstrsupplieridFROMProduction.Suppliers00000000290000000028000000000400000000210000000002000000002200000000140000000011首先利用replicate函数将0复制了9个,然后拼接supplierid,再利用right函数从右边开始截取10个字符.
stuff函数
stuff函数对输入参数string,从输入参数pos指定的位置开始删除delete_length参数指定长度的字符,然后将insertstring参数指定的字符串插入到pos指定的位置
stuff(string,pos,delete_length,insertstring)
string被输入的stringpos开始删除位置,位置从1开始。从0开始的话会得到一个null
delete_length删除长度,是0,是0的话,将不删除任何字符将字符插在string最前面
insertstring重新插入的字符串
printSTUFF('jolinson',1,1,'J')--Jolinson
upper和lower函数
upper和lower函数将输入字符串中的所有字符都转为大写或小写字符。
upper(string)lower(string)
PRINTUPPER('jolinson')--JOLINSON
PRINTLOWER('JOLINSON')--jolinson
rtrim和ltrim函数
用于删除输入字符串中的尾部空格或开头处空格。
rtrim(string)、ltrim(string)
PRINTRTRIM('jolinson')--jolinson
如果既想删除开头空格又想删除末尾空格可以使用两个函数嵌套
SELECTLTRIM(RTRIM('jolinson'))--jolinson
模式匹配
Like谓词用于检查字符串是否能够匹配指定的模式。
%(百分号)通配符代表任意长度的字符串,包括空字符串。'A%'----匹配任意A字符开头的字符串。
_(下划线)代表任意单个字符。'A_C'----匹配A开头C结尾中间一个为任意字符的字符串
[<字符列>]通配符,方括号中包含一列字符(例如'[ABC]'),表示必须匹配列指定字符中的一个字符。'[ABC]%'----匹配A、B或者C开头的字符串。
[<字符>-<字符>]通配符方括号中包含一个字符范围(例如['A-Z']),表示必须匹配指定范围内的一个字符。'[A-G]'匹配的只能是ABCDEFG其中的一个字符。
[^<字符列或范围>]通配符表示不属于指定字符列或范围内的任意单个字符串。'[^A-G]'匹配的只能是除ABCDEFG以外的任一个字符
转移字符,当搜索的通配符中出现了特定的通配符如'%','_','[',']'的时候,我们需要把他们转义。LIKE'%!_%'ESCAPE'!'或者LIKE'%[!]_%'
数据类型存储大小(字节)日期范围准确度推荐格式及示例
datetime81753-01-01到9999-12-313.33毫秒'YYYYMMDDhh:mm:ss:nnn''2009021212:30:15:123'
smalldatetime41900-01-01到2079-06-061分钟'YYYYMMDDhh:mm''2009021212:30'
date30001-01-01到9999-12-311天'YYYYMMDD'
time3-500:00:00.0000000到23:59:59.9999999100纳秒'hh:mm:ss.nnnnnn''12:30:15.1234567'
datetime26-80001-01-0100:00:00.0000000到100纳秒'YYYYMMDDhh:mm:ss.nnnnnn'9999-12-3123:59:59.9999999'2009021212:30:15.1234567'
Datetimeoffset8-100001-01-0100:00:00.0000000到100纳秒'YYYYMMDDhh:mm:ss.nnnnnn[+|-]'hh:mm9999-12-3123:59:59.9999999'2009021212:30:15.1234567+02.00'
最后三种数据类型(time、datetime2、datetimeoffset)的存储空间大小要依赖于所选择的精度,可以通过0-7之间的整数来指定其精度
DECLARE@timeDATETIME2=GETDATE()DECLARE@time0DATETIME2(0)=GETDATE()DECLARE@time1DATETIME2(1)=GETDATE()DECLARE@time2DATETIME2(2)=GETDATE()DECLARE@time3DATETIME2(3)=GETDATE()DECLARE@time4DATETIME2(4)=GETDATE()DECLARE@time5DATETIME2(5)=GETDATE()DECLARE@time6DATETIME2(6)=GETDATE()DECLARE@time7DATETIME2(7)=GETDATE()SELECT@time,@time0,@time1,@time2,@time3,@time4,@time5,@time6,@time7--2014-03-0316:09:30.3030000--2014-03-0316:09:30--2014-03-0316:09:30.3--2014-03-0316:09:30.30--2014-03-0316:09:30.303--2014-03-0316:09:30.3030--2014-03-0316:09:30.30300--2014-03-0316:09:30.303000--2014-03-0316:09:30.3030000setlanguage命令改写会话中默认语言(不推荐,因为代码中的某些地方可能会依赖与用户的默认语言)
dateformat设置是由字符d、m、y的组合表示的。例如us_english语言设计会把dateformat设置为mdy,而british语言设置则将dateformat设置为dmy。
当一个表达式涉及了两种不同类型的操作数,会将其中类型隐式转换成另外一种类型在进行比对,总是将数据类型优先级低的向高的转换。
数据类型优先级当两个不同数据类型的表达式用运算符组合后,数据类型优先级规则指定将优先级较低的数据类型转换为优先级较高的数据类型。如果此转换不是所支持的隐式转换,则返回错误。
当两个操作数表达式具有相同的数据类型时,运算的结果便为该数据类型。
SQLServer对数据类型使用以下优先级顺序:
1.用户定义数据类型(最高)
2.sql_variant
3.xml
4.datetimeoffset
5.datetime2
6.datetime
7.smalldatetime
8.date
9.time
10.float
11.real
12.decimal
13.money
14.smallmoney
15.bigint
16.int
17.smallint
18.tinyint
19.bit
20.ntext
21.text
22.image
23.timestamp
24.uniqueidentifier
25.nvarchar(包括nvarchar(max))
26.nchar
27.varchar(包括varchar(max))
28.char
29.varbinary(包括varbinary(max))
30.binary(最低)
为了潜在地有效利用索引,就需要对谓词进行调整,一边对过滤条件中的列不进行处理----在谓词条件中不做过多的处理
cast和convert函数
cast和convert函数用于转换值的数据类型。
cast(valueasdatatype)
convert(datatype,value,[style_number])
这两个函数都可以将输入的值转换为指定的数据类型。在一些情况下,还能用convert提供的第三个参数来指定转换的样式。
注意cast是ANSI标准SQL,而convert不是,所以除非需要使用样式值,否则推荐优先使用cast函数。
DateAdd函数
dateadd(part,n,dt_val)
日期部分的有效值包括year、quarter、month、dayofyear、day、week、weekday、hour、minite、second、millisecond、microsecond、nanosecond,最后两个是SQL2008新增加的。
也可以用缩写代替如year(yy).
SELECTDATEADD(YEAR,2,'20120228')--2014-02-2800:00:00.000
datadiff函数
datediff(part,dt_val,dt_val2)
返回两个值之间的相差的天数SELECTDATEDIFF(DAY,'20130228','20140228')--365
--返回两个值之间的相差的天数SELECTDATEDIFF(DAY,'20130228','20140228')--365--当天午夜SELECTDATEADD(DAY,DATEDIFF(DAY,0,CURRENT_TIMESTAMP),0);--2014-02-2600:00:00.000--当月第一天SELECTDATEADD(month,DATEDIFF(month,0,CURRENT_TIMESTAMP),0);--2014-02-0100:00:00.000--当月的最后一天SELECTDATEADD(month,DATEDIFF(month,'19911231',CURRENT_TIMESTAMP),'19911231');--2014-02-2800:00:00.000
datepart函数
patepart(part,dt_val)
part参数的有效值包括year、quater、month、dayofyear、day、week、weekday、hour、minute、second、milliseconde、milliseconde、microsecond,manosecond,
TZoffset、ISO_WEEK
year、month、day函数
year(dt_val)
month(dt_val)
day(dt_val)
datename函数
datename(part,dt_val)
SELECTDATENAME(year,'20240225')--2024SELECTDATENAME(month,'20240225')--FebruarySELECTDATENAME(day,'20240225')--25datename返回的月份名称是依赖语言的。
isdate函数
语法isdate(string)
selectISDATE('20240225')--1
查询元数据
如果想列出数据库中的各个表,以及他们的框架名称,查询sys.tables
SELECTSCHEMA_NAME([schema_id])AStable_schema_name,nameAStable_nameFROMsys.tables上面利用了SCHEMA_NAME()函数把表示框架Id的整数转换成它的名称。
如果你想得到有关某个表的列的信息,你可以查询sys.columns表。
SELECTnameAScolumn_name,--列名TYPE_NAME(system_type_id)AScolumn_type,--数据类型max_length,--最大长度collation_name,--排序规则is_nullable--名称FROMsys.columnsWHEREobject_id=OBJECT_ID(N'Sales.orders')更多资料更多内容可在SQLServer联机丛书的“查询SQLServer系统目录(queryinttheSQLServerSystemCatalog)”章节中查找