关于SQL
它的名字叫结构化查询语言(Structured Query Language)——是用于访问和处理数据库的标准计算机语言。
(题外话:这里我最喜欢的字眼就是“语言”,何时起,我的思维里就定式了类似C/JAVA/C++这样的才是语言,可是SQL/XML/HTML/脚本等等都是语言啊,而且名字里还故意的带着一个L!当然应该有更多其它的语言会接着颠覆我这一点点定式思维。)
ANSI的SQL就是标准的普通话,各主流数据库管理系统又有自己的扩展版方言。我们现在使用最多的都是关系型数据库,就是啥table啊那种。如果我们把数据单纯的存储在二进制文本中,然后编写一个程序提供读取写入更新删除或者其他管理等功能,这基本也就算一个数据库管理系统了,当然你这个数据库管理系统可能又不健壮功能又少制约还多,但完全可以算是一个数据库管理系统了。当其他程序使用你这个数据库管理系统进行数据存储和管理的时候,只能用你的程序懂的方式或者你程序留出来的接口进行使用,这就是你的数据库管理系统支持的方言,可能很偏僻很偏僻,可能跟什么SQL没有任何关系。但,你也完全可以按照SQL的标准进行相关操作的定义。
使用SQL
最近在开发一个自动生成PDF月度报告的程序,报告的结构和内容概要在XML中定义,程序读入XML后解析出报告的结构并根据内容概要完成对数据的组织。而组织数据上,最多的来源是数据库。因此比较单纯的使用了众多SQL语句查询提取数据。数据库是SQL SERVER 2005.
使用和学习是分不开的,下面在编写具体SQL的同时稍微系统的学习梳理一下SQL语法语义什么的。
SELECT 列名 FROM 表名称 WHERE 条件
这就是一个查询的基本格式,它返回符合条件的所有记录,每一条记录只展示你需要的列的(在SELECT和FROM中间列出的那些列名)内容,使用 * 表示每条记录包含所有列的内容。默认升序(asc)排序。
INSERT INTO 表名称 VALUES (值1,值2,... )或者INSERT INTO 表名称 (列1,列2,...)VALUES(值1,值2,...)
插入一行记录的两种方式,第一种必须满额插入,即使某字段值是NULL也要显式的写出NULL,顺序与表定义的字段顺序一一对应;第二种方式,插入值的顺序跟前方列名顺序对应,列名中必须包含主键、可以不列出所有列,未列明的默认NULL。
UPDATE 表名称 SET 列名 = 值 WHERE 条件
更新数据表中符合条件的记录的某列的值,如果多条记录符合要求,全部修改。如果要修改多个列的值,可以在SET后列出所有的“列名=值”其间使用逗号分隔。
DELETE FROM 表名称 WHERE 条件
将表中所有符合条件的记录删除,如果不加WHERE筛选条件,则将表中的记录全部删除,表的结构等不受影响。
SELECT DISTINCT列名1,列名2 FROM 表名称
查询的一个限制条件。即去除重复的记录,返回的记录都是唯一的。如何识别两条记录是否重复呢?将你列出来的列名组合起来作为标识来判断记录是否重复。下面的小例子可以清晰看出,列出了2个列名,所以就以2个列名组合起来进行重复性判定。
SELECT TOP number(或者number PERCENT)* FROM 表名称
此查询返回前number条记录(或者前百分之number条记录,小数丢弃)。如果想查询第101条到200条记录怎么办?可以这样:SELECT TOP 100 * FROM 表名称 WHERE id NOT IN (SELECT TOP 100 id FROM 表名称)就可以了。
WHERE/AND/OR/ORDER BY貌似没有太特别的。只是ORDER BY可以这样:order by a desc,b asc(按照a降序排列,如果a字段相同就按照b字段升序排列。
SLECET 列名 FROM 表名称 WHERE 列名 LIKE 'XXX%'
LIKE 在WHERE子句中进行模式匹配,搭配通配符使用来完成模糊查询。
通配符:% 表示0个或者多个字符,_ 表示一个字符,[charlist]表示字符列中的任何单一字符,[^charlist]不在字符列中的任何单一字符。例如:
SELECT * FROM 表名称 WHERE 列名 LIKE '%D[ABC]%' 此句返回表中所有某列内容包含DA/DB/DC之一的记录,此处注意SQL大小写不敏感,所以如果内容中出现Da或者dB等也都是匹配成功的。
SELCET * FROM 表名称 WHERE 列名 IN (值1,值2,值3)
IN 应用于WHERE子句,其实跟LIKE都是"="的扩展,表示列名的内容如果是值1、值2、值3之一的即为符合要求的记录。
BETWEEN AND依旧应用于WHERE子句中,具体的数据库实现可能对两个端点是否被包含而有所不同,注意些。
另外
文本值需要用单引号环绕,数值就决不能用引号。
多表联合查询
使用JOIN进行多表连合查询,可以使用INNER JOIN/JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN其格式均是一致的:
SELECT 列名称 FROM 表1名称 JOIN 表2名称 ON 表1.列名 = 表2.列名
其中INNER JOIN与JOIN一样。根据连接条件,返回所有匹配的记录,至少存在一个匹配才会返回。
LEFT JOIN 会从左表那里返回所有的行,即使在右表中没有按照连接条件匹配的行。当然如果有就填充相应字段,如果没有就是NULL。
左连接对应的还有右连接,RIGHT JOIN是返回右表中所有的行,即使在左表中没有按照连接条件匹配的行。
FULL JOIN 会从左边和右表中返回所有的行。即使不存在匹配的行也返回。极端的境况下是没有任何匹配,那么两个表中的所有行都会返回,然后表中不存在的字段填充为NULL.
感觉上,INNER JOIN向交集,而FULL JOIN是并集。
函数
COUNT(列名) 返回指定列的值的数目,NULL不计入内。
COUNT(DISTINCT 列名) 返回指定列的不同值的数目。
MAX/MIN可以用于文本,以获得按字母顺序的最高或者最低值。
其他还有AVG/COUNT(*)/SUM等
对于COUNT/AVG/SUM等合计函数,另一关键点就是GROUP BY了。
GROUP BY 根据一个或者多个列对结果进行分组。这个分组在合计统计时太重要了,既然是统计,那么就需要有个统计对象,比方说使用COUNT统计数目,统计谁的数目?如果不加分组,统计的就是表中所有记录的数目,但是如果使用一个列或者几个列指定分组,那么你统计的就是这个分组的数目。比方说你统计1到100之间的整数的数目,那么返回就是一行:结果100,但是如果你使用奇数偶数把这100个整数分成了两组,那么统计的就是分组的数目,结果就是奇数50、偶数50.大致就是这么个回事。
HAVING 增加 HAVING 子句原因是,WHERE 字句中无法使用合计函数,因此需要使用合计函数你定筛选条件时在group by子句的后面加上这个子句。