1、基本操作
INSERT
-- 插入单条数据insert into table1(col1,col2,…) values(value1,value2,…)
-- 插入多条数据
insert into table1(col1,col2,…) values(value1,value2,…),(value1,value2,…),…
-- 插入来自select查询的数据
insert into table1(col1,col2,…) select col1,col2,… from table2 […left join …] [where …]
-- 插入来自存储过程返回的结果集
insert into table1(col1,col2,…) exec procedure1
SELECT
(1)一般使用语法
select [ * | col1,col2,… |[count(*)|sum(col3)|max(col4)...] ]from table1
[…join …on …]
[…join …on …]
[where …]
[group by col1,col2]
[order by …]
注意:
①与Group by一起使用时,才能够使用count,sum,max,min,avg等函数,且在group by后不能指定text,ntext,image数据类型的字段分组。
②聚合函数(count,sum,max,min,avg)对NULL的处理:count(1)和count(*)结果一样,都包括对null的统计,只是执行效率有高低;count(column)不包括对null值的统计,可以用isnull函数进行转换,聚合函数avg、max、min、sum 都是忽略null值的,都须通过isnull转换。
③当跨数据库(或数据库服务器)时,有时会因为用于Join的两个表所在数据库的字符集不一致,在join… on后面直接用“t1.Name = t2.Title”会得不到预期的结果,而应该等号之前加“collate Chinese_PRC_CI_AS”,如“t1.Name collate Chinese_PRC_CI_AS = t2.Title”;
(2)Select嵌套使用
select * from (select [ * | col1,col2,…] from table1
[…join …on …]
[…join …on …]
[where …]
[group by …]) as t
[…join …on …]
[…join …on …]
[where …]
[group by …]
[order by …]
(3)返回取值(只用于调试时可用print取代)
select @name -- @name是变量(4)从表给变量赋值
select @name = col1 from table1 where id = 1 -- @name指定值(5)给变量赋值(作用类似于set命令)
select @name = 'AAA' -– 类似于set @name='AAA'(6)复制表结构及数据
select * into b from table1 -- b是物理表,复制表结构与数据select * into #b from table1 -- #b是内存表,复制表结构与数据
select * into #b from table1 where 1 <> 1 -- 只复制表结构
UPDATE
(1) 根据条件更新
update table1 set col1 = value1,col2 = value2,… [where …]
(2) 根据基它表条件更新
update table1 set col1 = t2.col1,col2 = t2.col2 from table2 as t2 [...join…on…] where t2.Id = t.Fid and …(3) 根据其它表条件更新
update table1 set col1 = t2.col1,col2 = t2.col2 from table1 as t left join table2 as t2 on t2.Id = t.Fid [where …]DELETE(用法同UPDATE)
(1) 根据条件删除
delete [from] table1 [where…]
(2) 根据其它表条件删除
delete [from] table1 from table2 as t2 […join…on…] where t2.Id = t.Fid [and ...]delete [from] table1 from table1 as t
left join table2 as t2 on t2.Id = t.Fid where …
注:养成良好习惯,在对数据进行批量Update、Delete时谨慎操作,一定先把要更新的数据用select查询出现,在检查无误后,再写update/delete语句,然后从select查询语句中把查询条件(where)直接Copy过来使用!
2、常用查询条件
普通运算符:=(等于),<>(不等于或用!=),>(大于),<(小于),>=(大于等于),<=(小于等于),between(介于A与B之间) 包含运算:IN
select Id,Name,Info from table1 where Id IN (1,2,3)
select Id,Name,Info from table1 where Id IN (select Id from table2 )
【注】在IN之后使用的select子句时,一定要注意排除NULL值,否则会得到意外的结果!【见示例《SQL基本操作》】
模糊运算:LIKE 否运算:NOT 条件组合关系:AND(且),OR(或)空判断:IS NULL | IS NOT NULL 存在判断:Exists | NOT Exists3、常用函数
判断是否空:ISNULL
日期计算:DATEDIFF,DATEADD,取日期部分Year()、Month()、Day()
字符串处理:STUFF,replace,LTRIM,RTRIM
数据类型转换:Cast,Convert
二、数据集运算
UNION 运算符
UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2。
EXCEPT 运算符EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。
INTERSECT 运算符INTERSECT 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL 随 INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。
注:使用运算词的几个查询结果行必须是一致的。
-- 从TableA取值,排除TableB、TableC中存在的记录(select a from tableA ) except (select a from tableB) except (select a from tableC)
三、连接(Join)
1、inner Join内联接:根据条件联接,且条件中的字段在两个表都不为NULL
2、left [Outer] Join 左联接:在左表为中心,让右表(join之后指定的表)根据条件联接,当条件中引用左表字段值在右表中不存在时,自动用NULL填充。
3、right [Outer] Join 右联接:与左联接相反。
4、Full [Outer] Join 全联接:是left join与right join的全集
declare @oldTable table(Num int)
declare @newTable table(Num int)
-- ============= 1、比较union与union all的区别 =============
-- (1) union
insert into @oldTable
select '52003' union
select '52004' union
select '52004' union
select '52005'
---- (2) union all
--select '52003' union all
--select '52004' union all
--select '52004' union all
--select '52005'
--select * from @oldTable
-- ============= 2、查找重复编码、多余编码 =============
insert into @oldTable
select '52003' union all
select '52004' union all
select '52005'
insert into @newTable
select '52004' union all
select '52005' union all
select '52006' union all
select '52007'
--select COUNT(*) from @oldTable
--select COUNT(*) from @newTable
--select * from @newTable where Num not in(select Num from @oldTable)
--select * from @oldTable where Num not in(select Num from @newTable)
--select * from(select Num,COUNT(*) count from @oldTable group by Num) t where t.count <> 1
--select * from(select Num,COUNT(*) count from @newTable group by Num) t where t.count <> 1
-- ============= 3、测试Join =============
-- (1) Inner Join
select * from @oldTable t1 inner join @newTable t2 on t2.Num = t1.Num
-- (1) Left [Outer] Join
select * from @oldTable t1 left join @newTable t2 on t2.Num = t1.Num
-- (1) Right [Outer] Join
select * from @oldTable t1 right join @newTable t2 on t2.Num = t1.Num
-- (1) Full [Outer] Join
select * from @oldTable t1 full join @newTable t2 on t2.Num = t1.Num
四、几种特性SQL
以下的几种特性常用于报表中。
1、行列转置Pivot-- ========================= PIVOT 行列转置 ===========================
-- 1、【行列转置PIVOT】
declare @Score table(StuNo varchar(10), StuName varchar(50), CourseName varchar(50), Score int)
insert into @Score
select '1', 'Tom', 'Math', 80 union all
select '1', 'Tom', 'English', 82 union all
select '1', 'Tom', 'Geography', 84 union all
select '2', 'Jone', 'Math', 79 union all
select '2', 'Jone', 'English', 88 union all
select '2', 'Jone', 'Geography',86
select * from @Score
SELECT StuNo, StuName, Math, English, [Geography]
FROM @Score as t PIVOT (MAX(Score) FOR CourseName in (Math, English, [Geography])) AS ScoreList
ORDER BY StuNo
-- 用简单的替换语句实现?
select StuNo,StuName,
MAX(CASE WHEN CourseName = 'Math' THEN Score ELSE NULL END) as [Math],
MAX(CASE WHEN CourseName = 'English' THEN Score ELSE NULL END) as [English],
MAX(CASE WHEN CourseName = 'Geography' THEN Score ELSE NULL END) as [English]
from @Score
group by StuNo,StuName
-- 执行动态SQL解决行列转置时需要指定转置列的问题?
declare @expression nvarchar(200) = '@Score',
@pvtCol nvarchar(50) = 'CourseName',
@pvtValue nvarchar(50) = 'MAX([Score])',
@keepCols nvarchar(200) = 'StuNo,StuName',
@order nvarchar(50) = 'StuNo',
@cols nvarchar(200) = '',
@query nvarchar(4000)
if @cols = '' or @cols is null
begin
declare @colsql nvarchar(200) = 'set @a = STUFF((select distinct '',['' + '
+ @pvtCol + ' + '']'' from ' + @expression + ' for xml path('''')),1,1,'''')'
exec sp_executesql @colsql,N'@a nvarchar(200) output',@cols output
end
set @query = 'SELECT ' + @keepCols
+ (case when LEN(@keepCols) > 0 then ',' else '' end)
+ @cols
+' FROM ' + @expression + ' as t PIVOT ('+ @pvtValue +' FOR ' + @pvtCol + ' in ('
+ @cols + ')) AS pvt ORDER BY '
+ @order
exec(@query)
-- 2、【列行转置UNPIVOT】
declare @ScoreList table(StuNo varchar(10), StuName varchar(50), Math int, English int, [Geography] int)
insert into @ScoreList
select '1', 'Tom', 80, 82, 84 union all
select '2', 'Jone', 79, 88, 86
select * from @ScoreList
SELECT StuNo, StuName, CourseName, Score
FROM @ScoreList UNPIVOT (Score FOR CourseName in (Math, English, [Geography]) ) AS ScorePvtTable
ORDER BY StuNo
2、递归取数CTE
-- ==================== Common Table Expression(CTE) ========================
declare @Object table(Id INT, ParentId INT, Name NVARCHAR(10))
INSERT INTO @Object
SELECT 1 , 0 , N'食品' UNION ALL
SELECT 2 , 1 , N'水果' UNION ALL
SELECT 3 , 1 , N'蔬菜' UNION ALL
SELECT 4 , 2 , N'香蕉' UNION ALL
SELECT 5 , 2 , N'苹果' UNION ALL
SELECT 6 , 3 , N'青菜' UNION ALL
SELECT 11 , 0 , N'计算机' UNION ALL
SELECT 12 , 11 , N'软件' UNION ALL
SELECT 13 , 11 , N'硬件' UNION ALL
SELECT 14 , 12 , N'Office' UNION ALL
SELECT 15 , 12 , N'Emeditor' UNION ALL
SELECT 16 , 13 , N'内存'
select * from @Object
-- 1、【得到所有水果】
;WITH cte AS
(
-- 起始条件
SELECT Id,ParentId,Name FROM @Object as t WHERE id=2
UNION ALL
-- 递归条件
SELECT a.Id,a.ParentId,a.Name FROM @Object a,cte b WHERE a.ParentId=b.Id
)
SELECT * FROM cte
-- 限制递归次数(默认值100),超出时会报错!
OPTION(MAXRECURSION 100)
-- 2、【得到当前及所有父级】
;WITH cte AS
(
SELECT Id,ParentId,Name FROM @Object WHERE id=16
UNION ALL
SELECT a.Id,a.ParentId,a.Name FROM @Object a,cte b WHERE a.Id=b.ParentId
)
SELECT * FROM cte
-- 3、【得到所有路径】
;WITH cte AS
(
SELECT Id,ParentId,Name,[Path]=CAST(Name AS VARCHAR(MAX)) FROM @Object WHERE parentid=0
UNION ALL
SELECT a.Id,a.ParentId,a.Name,CAST(b.[Path] +'/'+a.Name AS VARCHAR(MAX)) FROM @Object a,cte b WHERE a.ParentId=b.Id
)
SELECT * FROM cte
-- Id ParentId Name Path
-- ----------- ----------- ---------- -------------------------
-- 1 0 食品 食品
-- 11 0 计算机 计算机
-- 12 11 软件 计算机/软件
-- 13 11 硬件 计算机/硬件
-- 16 13 内存 计算机/硬件/内存
-- 14 12 Office 计算机/软件/Office
-- 15 12 Emeditor 计算机/软件/Emeditor
-- 2 1 水果 食品/水果
-- 3 1 蔬菜 食品/蔬菜
-- 6 3 青菜 食品/蔬菜/青菜
-- 4 2 香蕉 食品/水果/香蕉
-- 5 2 苹果 食品/水果/苹果
3、汇总特性介绍