【Redis持久化】服务器突然挂了!Redis缓存都在内存中啊

该日志由 samool 发表于 2020-09-27 14:29:53

我是Redis,一个叫Antirez的男人把我带到了这个世界上。

“快醒醒!快醒醒!”,隐隐约约,我听到有人在叫我。

慢慢睁开眼睛,原来旁边是MySQL大哥。

“我怎么睡着了?”

“嗨,你刚才是不是出现了错误,整个进程都崩溃了!害得一大堆查询请求都给我怼过来了!”,MySQL说到。

刚刚醒来,脑子还有点懵,MySQL大哥扶我起来继续工作。

“糟了!我之前缓存的数据全都不见了!”

“WTF?你没有做持久化吗?”,MySQL大哥一听脸色都变了。

我尴尬的摇了摇头,“我都是保存在内存中的,所以才那么快啊”

“那也可以在硬盘上保存一下啊,遇到这种情况全部从头再来建立缓存,这不浪费时间嘛!”

我点了点头,“让我琢磨一下,看看怎么做这个持久化”。

RDB持久化

没几天,我就拿出了一套方案:RDB

既然我的数据都在内存中存放着,最简单的就是遍历一遍把它们全都写入文件中。

为了节约空间,我定义了一个二进制的格式,把数据一条一条码在一起,生成了一个RDB文件。

不过我的数据量有点大,要是全部备份一次得花不少时间,所以不能太频繁的去做这事,要不然我不用干正事了,光花时间去备份了。

还有啊,要是一直没有写入操作,都是读取操作,那我也不用重复备份,浪费时间。

思来想去,我决定提供一个配置参数,既可以支持周期性备份,也可以避免做无用功。

就像这样:

  • save 900 1 # 900秒(15分钟)内有1个写入
  • save 300 10 # 300秒(5分钟)内有10个写入
  • save 60 10000 # 60秒(1分钟)内有10000个写入

多个条件可以组合使用,只要上面一个条件满足,我就会去进行备份。

后来我又想了一下,这样还是不行,我得fork出一个子进程去做这件事,不能浪费我的时间。

有了备份文件,下次我再遇到崩溃退出,甚至服务器断电罢工了,只要我的备份文件还在,我就能在启动的时候读取,快速恢复之前的状态啦!

MySQL:binlog

我带着这套方案,兴冲冲的拿给了MySQL大哥看了,期待他给我一些鼓励。

“老弟,你这个方案有点问题啊”,没想到,他竟给我浇了一盆冷水。

“问题?有什么问题?”

“你看啊,你这个周期性去备份,周期还是分钟级别的,你可知道咱们这服务每秒钟都要响应多少请求,像你这样不得丢失多少数据?”,MySQL语重心长的说到。

我一下有些气短了,“可是,这个备份一次要遍历全部数据,开销还是挺大的,不适合高频执行啊”

“谁叫你一次遍历全部数据了?来来来,我给你看个东西”,MySQL大哥把我带到了一个文件目录下:

  • mysql-bin.000001
  • mysql-bin.000002
  • mysql-bin.000003
  • ···

“看,这些是我的二进制日志binlog,你猜猜看里面都装了些什么?”,MySQL大哥指着这一堆文件说到。

我看了一眼,全是一堆二进制数据,这哪看得懂,我摇了摇头。

“这里面呀记录了我对数据执行更改的所有操作,像是INSERTUPDATEDELETE等等动作,等我要进行数据恢复的时候就可以派上大用场了”

听他这么一说,我一下来了灵感!告别了MySQL大哥,回去研究起新的方案来了。

AOF持久化

你们也知道,我也是基于命令式的,每天的工作就是响应业务程序发来的命令请求。

回来以后,我决定照葫芦画瓢,学着MySQL大哥的样子,把我执行的所有写入命令都记录下来,专门写入了一个文件,并给这种持久化方式也取了一个名字:AOF(Append Only File)

不过我遇到了RDB方案同样的问题,我该多久写一次文件呢?

我肯定不能每执行一条写入命令就记录到文件中,那会严重拖垮我的性能!我决定准备一个缓冲区,然后把要记录的命令先临时保存在这里,然后再择机写入文件,我把这个临时缓冲区叫做aof_buf

说干就干,我试了一下,竟然发现数据没有写入到文件中去。多方打听才知道,原来操作系统也有个缓存区,我写的数据被他缓存起来了,没有给我写入到文件中去,这不是坑爹呢嘛!

看来,我写完了还得要去刷新一下,把数据真正给写下去,思来想去,我还是提供一个参数,让业务程序去设置什么时候刷新吧。

appendfsync参数,三个取值:

  • always: 每个事件周期都同步刷新一次
  • everysec: 每一秒都同步刷新一次
  • no: 我只管写,让操作系统自己决定什么时候真正写入吧

AOF重写

这一次我不像之前那么冲动,我决定先试运行一段时间再去告诉MySQL大哥,免得又被他戳到软肋。

试用了一段时间,各方面都运行良好,不过我发现随着时间的推移,我写的这个AOF备份文件越来越大,越来越大!不仅非常占硬盘空间,复制移动,加载分析都非常的麻烦耗时。

我得想个办法把文件给压缩一下,我把这个过程叫做AOF重写

一开始,我打算去分析原来的AOF文件,然后将其中的冗余指令去掉,来给AOF文件瘦瘦身,不过我很快放弃了这个想法,这工作量实在太大了,分析起来也颇为麻烦,浪费很多精力跟时间。

原来的一条条记录这种方式实在是太笨了,数据改来改去,有很多中间状态都没用,我何不就把最终都数据状态记录下来就好了?

比如:

  • RPUSH name_list'编程技术宇宙'
  • RPUSH name_list'帅地玩编程'
  • RPUSH name_list'后端技术学堂'

可以合并成一条搞定:

  • RPUSH name_list '编程技术宇宙' '帅地玩编程' '后端技术学堂'

AOF文件重写的思路我是有了,不过这件事干起来还是很耗时间,我决定和RDB方式一样,fork出一个子进程来做这件事情。

谨慎如我,发现这样做之后,子进程在重写期间,我要是修改了数据,就会出现和重写的内容不一致的情况!MySQL大哥肯定会挑刺儿,我还得把这个漏洞给补上。

于是,我在之前的aof_buf之外,又准备了一个缓冲区:AOF重写缓冲区

从创建重写子进程开始的那一刻起,我把后面来的写入命令也copy一份写到这个重写缓冲区中,等到子进程重写AOF文件结束之后,我再把这个缓冲区中的命令写入到新的AOF文件中。

最后再重命名新的AOF文件,替换掉原来的那个臃肿不堪的大文件,终于大功告成!

再三确定我的思路没有问题之后,我带着新的方案再次找到了MySQL大哥,我都做到这份儿上了,这一次,想必他应该无话可说了吧?

MySQL大哥看了我的方案露出了满意的笑容,只是问了一个问题:

这AOF方案这么好了,RDB方案是不是可以不要了呢?

万万没想到,他居然问我这个问题,我竟陷入了沉思,你觉得我该怎么回答好呢?

彩蛋

“你怎么又崩溃了?”

“不好意思,又遇到bug了,不过不用担心,我现在可以快速恢复了!”

“那老崩溃也不是事儿啊,你只有一个实例太不可靠了,去找几个帮手吧!”

该日志标签: 技术, 进程, 查询, 动作, 工作, 目录, 错误, 日志, 漏洞, 世界, 内容, 文件, 程序, 运行, 实例, 男人, mysql, 编程, bug, 周期, 问题, 命令, 同步, 数据, 记录, 时间, 参数, 指令, 内存, 崩溃, , 时候, aof, 写入, 重写

sql中特殊日期代码

该日志由 samool 发表于 2010-07-14 21:55:36

1 ---上个月月初第一天
select CONVERT(varchar(12) , DATEADD(mm,DATEDIFF(mm,0,dateadd(mm,-1,getdate())),0), 112 )
---上个月月末最后一天
select CONVERT(varchar(12),dateadd(ms,-3,DATEADD(mm,DATEDIFF(m,0,getdate()),0)), 112 )

1. 显示本月第一天
SELECT DATEADD(mm,DATEDIFF(mm,0,getdate()),0)
select convert(datetime,convert(varchar(8),getdate(),120)+'01',120)
2. 显示本月最后一天
select dateadd(day,-1,convert(datetime,convert(varchar(8),dateadd(month,1,getdate()),120)+'01',120))
SELECT dateadd(ms,-3,DATEADD(mm,DATEDIFF(m,0,getdate())+1,0))

阅读剩余部分...

该日志标签: sql, 查询

ThinkPHP第一天:数据库查询功能很强大

该日志由 samool 发表于 2008-03-13 17:14:34

ThinkPHP提供强大的数据查询功能,很多查询操作函数在系统中已经内置有了,不需要手动连接数据库,只需要作一下简单的数据连接配置,直接数组参数方式配置和DSN参数进行连接数据库,所有操作都是傻瓜式的,很方便,呵呵,以下内容来源于《ThinkPHP开发指南》。

1、普通查询 

$condition = new HashMap(); 

//  查询 name 为 thinkphp  的记录
$condition‐>put('name','thinkphp'); 

//  使用数组作为查询条件 
$condition = Array(); 
$condition['name'] = 'thinkphp'; 

使用 Map 方式查询和使用数组查询的效果是相同的,并且是可以互换的。 

2、条件查询 

在查询条件里面,如果仅仅使用 

$map‐>put(‘name’,’thinkphp’); 

查询条件应该是  name = ‘thinkphp’ 

如果需要进行其它方式的条件判断,可以使用 

$map‐>put(‘name’,array(‘like’,’thinkphp%’)); 

这样,查询条件就变成  name like ‘thinkphp%’ 

$map‐>put(‘id’,array(‘gt’,100)); 

查询条件  id > 100 

$map‐>put(‘id’,array(‘in’,’1,3,8’)); 

//  或者使用数组范围

$map‐>put(‘id’,array(‘in’,array(1,3,8))); 

上面表示的查询条件都是  id in (1,3,8) 

支持的查询表达式有EQ |NEQ |GT|EGT|LT |ELT |LIKE|BETWEEN|IN|NOT IN 

3、区间查询 

ThinkPHP 支持对某个字段的区间查询,例如: 

$map‐>put('id',array(1,10)); // id >=1 and id<=10 

$map‐>put('id',array('10','3','or')); //id >= 10 or id <=3 

$map‐>put('id',array(array('neq',6),array('gt',3),'and')); // id != 6 and id > 3 

4、组合查询 

如果进行多字段查询,那么字段之间的逻辑关系是 逻辑与  AND,但是用下面的规则可以更改默认的 

逻辑判断,例如下面的查询条件: 

$map‐>put('id',array('neq',1)); 

$map‐>put('name','ok'); 

// 现在的条件是 id !=1 and name like '%ok%' 

$map‐>put('_logic','or'); 

// 现在的条件变为 id !=1 or name like '%ok%' 

5、多字段查询 

ThinkPHP还支持直接对进行多字段查询的方法, 可以简化查询表达式和完成最复杂的查询方法, 例如: 

$map‐>put('id,name,title',array(array('neq',1),array('like','aaa'),array('like','bbb'),’or’)); 

查询条件是  ( id != 1) OR ( name like ‘aaa’) OR ( title like ‘%bbb%’) 

如果结合上面的几种方式,我们可以写出下面更加复杂的查询条件 

$map‐>put(‘id’,array(‘NOT IN’,’1,6,9’)); 

$map‐>put(‘name,email’,array(array(‘like’,’thinkphp’),array(‘like’,’liu21st’),’or’)); 

以上查询条件变成:( id NOT IN(1,6,9) ) AND ( ( name like ‘aaa’) OR ( title like ‘%bbb%’) ) 

6、查询缓存 

ThinkPHP 内建查询缓存支持,可以包括对 SQL 查询缓存、数据对象缓存的缓存支持。对于同一个数据对象的多次查询并不会导致多次数据库的查询开销,系统内置会进行缓存判断。 

7、统计查询 

在应用中我们经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等,ThinkPHP 为这些统计操作提供了一系列的内置方法。 

  //  获取用户数 

  $userCount = $User‐>count(); 

  //  获取用户的最大积分 

  $maxScore = $User‐>max(‘score’); 

  //  获取积分大于 0  的用户的最小积分 

  $minScore = $User‐>min(‘score’,’score>0’); 

  //  获取用户的平均积分 

  $avgScore = $User‐>avg(‘score’); 

  //  统计用户的总成绩 

  $sumScore = $User‐>sum(‘score’); 

8、定位查询 

ThinkPHP 支持定位查询,可以使用getN 方法直接返回查询结果中的某个位置的记录。例如: 

  //  返回符合条件的第 2 条记录
  $User‐>getN(2,’score>80’,’score desc’); 

  还可以获取最后第二条记录 
  $User‐>getN(‐2,’score>80’,’score desc’); 

  如果要查询第一条记录,还可以使用 
  $User‐>first(’score>80’,’score desc’);

  //  获取最后一条记录 
  $User‐>last(’score>80’,’score desc’); 

  //  获取积分最高的前 5 条记录 
  $User‐>top(5,’’,’score desc’); 

9、动态查询 

借助  PHP5 语言的特性,ThinkPHP 实现了动态查询。该查询方式针对数据表的字段进行查询。例如,User 对象拥有 id,name,email,address  等属性,那么我们就可以使用下面的查询方法来直接根据某个属性来查询符号条件的记录。 

  $user = $User‐>getByName(‘liu21st’); 
  上面的查询会转化为$User‐>getBy(‘name’,’liu21st’)的查询语言来执行 

  $user = $User‐>getByEmail(‘liu21st@gmail.com’);
  $user = $User‐>getByAddress(‘中国深圳’); 
  暂时不支持多数据字段的动态查询方法,请使用 find 方法和 findAll 方法进行查询。 

  ThinkPHP 还提供了另外一种动态查询方式,就是获取符合条件的前 N 条记录 

  例如,我们需要获取当前用户中积分大于 0,积分最高的前 5 位用户
  $User‐>top5(‘score>0’,’*’,’score desc’); 

  而在另外一个频道,我们需要获取点击最多的前 10 位主播 
  $Master‐>top10(‘’,’*’,’visit desc’); 

10、SQL 查询 

ThinkPHP 支持原生的 SQL 查询,在某些特殊的情况下可以满足应用的需要。 SQL 查询的返回值因为是直接返回的 Db 类的查询结果,没有做任何的处理,所以永远是返回的数据集对象或者惰性数据查询对象。而且可以支持查询缓存、延迟加载和事务锁 (悲观锁)。 

SQL 查询使用 query 方法 
$list = $User‐>query(“select id,name from think_user”);

如果没有使用延迟加载,返回结果是   ArrayObject  对象,如果启用了延迟加载,那么返回的是ResultIterator 对象。 

11、事务支持 

ThinkPHP 提供了单数据库的事务支持,如果要在应用逻辑中使用事务,可以参考下面的方法: 

//  启动事务 
$User‐>startTrans() 

//  提交事务 
$User‐>commit() 

//  事务回滚 
$User‐>rollback(); 

在有些对多个数据的批量操作中,已经内建了事务支持。 

该日志标签: sql, 查询, php

SEO工具 站长必备

该日志由 samool 发表于 2007-11-14 16:49:28

内容与结构工具

搜索引擎抓取内容模拟器

可以模拟蜘蛛抓取指定网页Text,Link,Keywords及Description信息
http://www.webconfs.com/search-engine-spider-simulator.php

相似页面检测工具

检验两个页面的相似度.如果相似度达80%以上,将可能受到惩罚
http://www.webconfs.com/similar-page-checker.php

Google Sitemaps 在线创建

在线创建 Google Sitemaps 网站地图文件

中文:http://www.xinqj.com/sitemap/sitemap.asp

英文:http://www.xml-sitemaps.com/

Google Sitemaps Builder .Net

Google Sitemaps 创建软件, 可以很方便的创建网站的Sitemaps
http://www.seobbs.net/read.php?tid=10620

综合查询工具

网站收录查询

同时查询Google,百度,Yahoo等8个搜索引擎的收录状况
http://tool.cndw.com/Shoulu/Index.asp

关键词排名查询
可以同时在3个搜索引擎中查询指定网页指定关键词的排名情况.
http://www.seores.com/search/keywordrank.asp

搜索引擎优化监视器(SEO Monitor)

一个仅321K的小软件,可以同时查询多个搜索引擎,多个关键词的排名情况.并自动记录历史排名情况.
http://www.seobbs.net/read.php?tid=2490

Google各服务器关键词排名查询

查询在Google各个服务器中,指定网页指定关键词的排名情况,可以作为一个升降的参考
http://tool.cndw.com/Rank/Index.asp

关键词工具

Google Adwords关键词工具

查询指定关键词的扩展匹配,搜索量,趋势和受欢迎度.
https://adwords.google.com/select/KeywordToolExternal

百度相关搜索

按热门程序排序,列出指定关键词相关的扩展匹配及热门程度
http://d.baidu.com/rs.php

关键词密度分析工具

分析指定关键词在指定页面中出现的次数,及相应的百分比密度

中文:http://tool.cndw.com/Seo/Key_Density.asp

英文:http://www.keyworddensity.com/

关键词热门排行及指数

百度排行榜:http://top.baidu.com/

百度指数:http://index.baidu.com/

Yahoo排行榜:http://misc.yahoo.com.cn/top_index.html

搜狗指数:http://www.sogou.com/top/?IPLOC=CN1102

搜搜龙虎榜:http://www.soso.com/lhb/s_i_sosolhb.shtml

Google工具

Google Sitemaps

Google推出的一项免费服务,一个杰出的SEO工具
http://www.google.com/webmasters/sitemaps/docs/zh_CN/about.html

Google Analytics

Google推出的免费分析服务.在市场营销和内容优化上提供很多专业报表.对搜索引擎营销有很大帮助.
http://www.google.com/analytics/zh-CN/

Google Dance 查询工具

不仅可以查询Dance情况,还可以通过E-mail及时获得每月google dance通知
http://www.seochat.com/googledance/

查看在GOOGLE各服务器上的PR值

利用这个工具,可以判断PR是否更新,预测更新后的PR值
http://www.seochat.com/seo-tools/future-pagerank

Google PR历史更新时间表

看看Google 2000看至今更新PR的具体时间和周期时长
http://www.seocompany.ca/pagerank/page-rank-update-list.html

链接工具

链接广泛度检测工具

反向链接查询工具.同时支持Google,百度,Yahoo等8个搜索引擎
http://tool.cndw.com/LinkIn/Index.asp

查询Google中链接的工具.可以抓取文本标题和链接.中文标题显示的是乱码
http://www.webconfs.com/google-backlink-checker.php

Yahoo新推出的链接检查工具,可以查询网站中所有被检索的页面以及反向链接情况
http://siteexplorer.search.yahoo.com/

同时查询Google,Yahoo,MSN中的链接数量
http://www.trafficzap.com/linkpopularity.php

无效链接检查工具

检查指定页面内的链接.包括链接有效性检查,链接文字,链接类型
http://www.seores.com/search/checkurl.asp

W3C GLink Checker
http://validator.w3.org/checklink

其他工具

国外主要搜索引擎和人工目录的关系表

一个Flash,解析国外主流搜索引擎与人工目录的关系,对海外推广很有帮助
http://www.seobbs.net/read.php?tid=911

网站历史查询工具

美国互联网档案馆(The Internet Archive)保存了自1996年开始,借助Alexa搜索引擎获取的网站资料
http://web.archive.org/collections/web/advanced.html

分类目录收录查询

检查网站是否登录多个重要分类目录
http://www.123promotion.co.uk/directory/index.php

Alexa世界排名查询
http://alexa.chinaz.com/Index.asp

查同一IP上绑定的域名情况
http://whois.webhosting.info/IP地址/

查看网站历史
http://web.archive.org/web/*/http://www.域名.com

本文由樂思蜀整理,转发请注明出处及链接!

首发:点石互动
http://www.dunsh.org/2006/09/12/seo-tools/

该日志标签: 查询, 工具, 链接

SQL查询语句精华使用简要

该日志由 samool 发表于 2006-12-04 10:58:20

一、 简单查询

  简单的Transact-SQL查询只包括选择列表、FROM子句和WHERE子句。它们分别说明所查询列、查询的表或视图、以及搜索条件等。
  例如,下面的语句查询testtable表中姓名为"张三"的nickname字段和email字段。

  SELECT nickname,email
  FROM testtable
  WHERE name='张三'

  (一) 选择列表

  选择列表(select_list)指出所查询列,它可以是一组列名列表、星号、表达式、变量(包括局部变量和全局变量)等构成。

  1、选择所有列

  例如,下面语句显示testtable表中所有列的数据:

  SELECT *
  FROM testtable

  2、选择部分列并指定它们的显示次序

  查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。
  例如:

  SELECT nickname,email
  FROM testtable

  3、更改列标题

  在选择列表中,可重新指定列标题。定义格式为:
  列标题=列名
  列名 列标题
  如果指定的列标题不是标准的标识符格式时,应使用引号定界符,例如,下列语句使用汉字显示列标题:

  SELECT 昵称=nickname,电子邮件=email
  FROM testtable

  4、删除重复行

  SELECT语句中使用ALL或DISTINCT选项来显示表中符合条件的所有行或删除其中重复的数据行,默认为ALL。使用DISTINCT选项时,对于所有重复的数据行在SELECT返回的结果集合中只保留一行。

  5、限制返回的行数

  使用TOP n [PERCENT]选项限制返回的数据行数,TOP n说明返回n行,而TOP n PERCENT时,说明n是表示一百分数,指定返回的行数等于总行数的百分之几。
  例如:

  SELECT TOP 2 *
  FROM testtable
  SELECT TOP 20 PERCENT *
  FROM testtable

  (二)FROM子句

  FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。
  在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定:

  SELECT username,citytable.cityid
  FROM usertable,citytable
  WHERE usertable.cityid=citytable.cityid

  在FROM子句中可用以下两种格式为表或视图指定别名:
  表名 as 别名
  表名 别名

  (二) FROM子句

  FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。
  在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定:

  SELECT username,citytable.cityid
  FROM usertable,citytable
  WHERE usertable.cityid=citytable.cityid

  在FROM子句中可用以下两种格式为表或视图指定别名:
  表名 as 别名
  表名 别名
  例如上面语句可用表的别名格式表示为:

  SELECT username,b.cityid
  FROM usertable a,citytable b
  WHERE a.cityid=b.cityid

  SELECT不仅能从表或视图中检索数据,它还能够从其它查询语句所返回的结果集合中查询数据。

  例如:

  SELECT a.au_fname+a.au_lname
  FROM authors a,titleauthor ta
  (SELECT title_id,title
  FROM titles
  WHERE ytd_sales>10000
  ) AS t
  WHERE a.au_id=ta.au_id
  AND ta.title_id=t.title_id

  此例中,将SELECT返回的结果集合给予一别名t,然后再从中检索数据。

  (三) 使用WHERE子句设置查询条件

  WHERE子句设置查询条件,过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据:

  SELECT *
  FROM usertable
  WHERE age>20

  WHERE子句可包括各种条件运算符:
  比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!<
  范围运算符(表达式值是否在指定的范围):BETWEEN...AND...
  NOT BETWEEN...AND...
  列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2......)
  NOT IN (项1,项2......)
  模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE
  空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL
  逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR

  1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30
  2、列表运算符例:country IN ('Germany','China')
  3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配。可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询。
  可使用以下通配字符:
  百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%。
  下划线_:匹配单个任意字符,它常用来限制表达式的字符长度。
  方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。[^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
  例如:
  限制以Publishing结尾,使用LIKE '%Publishing'
  限制以A开头:LIKE '[A]%'
  限制以A开头外:LIKE '[^A]%'

  4、空值判断符例WHERE age IS NULL

  5、逻辑运算符:优先级为NOT、AND、OR

  (四)查询结果排序

  使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为:
  ORDER BY {column_name [ASC|DESC]} [,...n]
  其中ASC表示升序,为默认值,DESC为降序。ORDER BY不能按ntext、text和image数据类型进行排
  序。
  例如:

  SELECT *
  FROM usertable
  ORDER BY age desc,userid ASC

  另外,可以根据表达式进行排序。

  二、 联合查询

  UNION运算符可以将两个或两个以上上SELECT语句的查询结果集合合并成一个结果集合显示,即执行联合查询。UNION的语法格式为:

  select_statement
  UNION [ALL] selectstatement
  [UNION [ALL] selectstatement][...n]

  其中selectstatement为待联合的SELECT查询语句。

  ALL选项表示将所有行合并到结果集合中。不指定该项时,被联合查询结果集合中的重复行将只保留一行。

  联合查询时,查询结果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名、列标题或者列序号。

  在使用UNION 运算符时,应保证每个联合查询语句的选择列表中有相同数量的表达式,并且每个查询选择表达式应具有相同的数据类型,或是可以自动将它们转换为相同的数据类型。在自动转换时,对于数值类型,系统将低精度的数据类型转换为高精度的数据类型。

  在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序。例如:

  查询1 UNION (查询2 UNION 查询3)

  三、连接查询

  通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。

  在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,尔后通过连接进行查询。

  连接可以在SELECT 语句的FROM子句或WHERE子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与WHERE子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。

  SQL-92标准所定义的FROM子句的连接语法格式为:

  FROM join_table join_type join_table
  [ON (join_condition)]

  其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自连接。

  join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。

  交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

  连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成。

  无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接。例如:

  SELECT p1.pub_id,p2.pub_id,p1.pr_info
  FROM pub_info AS p1 INNER JOIN pub_info AS p2
  ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)

  (一)内连接
  内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分三种:
  1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。
  2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
  3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。
  例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:

  SELECT *
  FROM authors AS a INNER JOIN publishers AS p
  ON a.city=p.city
  又如使用自然连接,在选择列表中删除authors 和publishers 表中重复列(city和state):
  SELECT a.*,p.pub_id,p.pub_name,p.country
  FROM authors AS a INNER JOIN publishers AS p
  ON a.city=p.city

  (二)外连接
  内连接时,返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。如下面使用左外连接将论坛内容和作者信息连接起来:

  SELECT a.*,b.* FROM luntan LEFT JOIN usertable as b
  ON a.username=b.username

  下面使用全外连接将city表中的所有作者以及user表中的所有作者,以及他们所在的城市:

  SELECT a.*,b.*
  FROM city as a FULL OUTER JOIN user as b
  ON a.username=b.username

  (三)交叉连接
  交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等于6*8=48行。

  SELECT type,pub_name
  FROM titles CROSS JOIN publishers
  ORDER BY type
  [Post=0][/Post]

该日志标签: sql, 精华, 查询