2005年10月31日

http://flash.qianlong.com/up_video/dh_thomas.rm

Je suis désolé我很抱歉
Je n’ai que deux pieds我只有两只脚
Je n’ai que deux pieds我只有两只脚

Franchement désolé我确实非常抱歉

La vaisselle envahit l’évier我的衬衫很脏
Et le linge déborde du panier我的洗衣机也坏掉了
J’ai les ch’veux sales, je suis barbu,我的头发也脏了,我一塌糊涂
Mais m’en vais mon café bu但是我仍把咖啡喝下

Je suis désolé我很抱歉
Je n’ai que deux pieds我只有两只脚
Je n’ai que deux pieds 我只有两只脚

Franchement désolé我确实非常抱歉

Dans la rue il y a des travaux道路正在施工
Et moi j’aime regarder les travaux而我喜欢注视工作的人群
On me dit : "du balai,他们对我说,你喜欢什么都不做,
plus vite que ?a s’il vous pla?t"

Je suis désolé我很抱歉,
Je n’ai que deux pieds我只有两只脚

Je n’ai que deux pieds我只有两只脚

Franchement désolé我确实非常抱歉

Elle me dit que je suis en retard她说我迟到了
Que je me coiffe avec un pétard因为我去理发
Elle veut déplacer les meubles她想搬家
J’ suis pas là pour déplacer les meubles !我却不在那里为她搬家具

Je suis désolé我很抱歉
Je n’ai que deux pieds我只有两只脚

Je n’ai que deux pieds我只有两只脚

Franchement désolé我确实非常抱歉

2005年10月28日

Windows XP凭借极高的安全性和稳定性,赢得了广大用户的青睐。我们可以通过建立个人账户、设定密码来保护自己的个人隐私,还可以用Administrators(超级管理员)的身份任意设置账户,为每一个账户设置不同的权限,可以说拥有至高无上的权利,也拥有系统的“生杀大权”,享有系统最高级别的安全保障。 

  但是,如果我告诉你,我能不费吹灰之力就可以将你这个Administrators给废掉, 
取而代之的是我成为Administrators,你信不信?呵呵,你不信?好,我们来试一试:

   步骤一 重新启动计算机,在出现启动菜单时按F8键进入高级选项菜单,选择“安全模式”进入系统;

   步骤二 打开“控制面板”,找到“用户和密码”选项,看看是不是账户中包括Administrators?好,现在将Administrators账户删除,重新创建一个Administrators,或是更改原来的Administrators账户密码;
   步骤三 重新启动计算机后,只有输入新的密码才能登录Windows XP。
  为什么会出现这种问题呢?原因很简单:Windows XP真正的超级管理员账号应该是在安全模式下的Administrators,并不是在正常模式下的Administrators。在默认情况下,安全模式下的Administrators密码为空。无论用户在正常模式下将Administrators密码设置得多么复杂,安全性多么高,如果没有设置安全模式下的Administrators密码,你的电脑将毫无秘密可言。  现在,你是不是对Windows XP的安全性有些担忧了?那怎么办?这还不简单:赶紧进入安全模式,设置Administrators密码,将自己提升为真正的Administrators!当然,这次设置的密码要记牢了,否则下次你就真的无法进入Windows XP了!安全模式下的Administrators,的确厉害!

但是最厉害的还是
1、用DOS启动盘进入纯DOS
2、进入系统目录下的system32目录        (cd system32)
   备份logon.scr、cmd.exe两文件      (copy …… ……)
   删除logon.scr                              (del logon.scr)
   并将cmd.exe改名为logon.scr            (ren cmd.exe logon.scr)
3、重启进入Windows,出现登陆画面等一会,一般会进入屏保logon.scr(此时已为cmd.exe)
4、可以在DOS下一展身手了,可用net <user> <password>修改密码再输入explorer,进去了!!! 
所以说赶快设置上你的 bios  才是硬道理!

2005年10月27日

检测内存泄漏:
检测内存泄漏的关键是要能截获住对分配内存和释放内存的函数的调用。截获住这两个函数,我们就能跟踪每一块内存的生命周期,比如,每当成功的分配一块内存后,就把它的指针加入一个全局的list中;每当释放一块内存,再把它的指针从list中删除。这样,当程序结束的时候,list中剩余的指针就是指向那些没有被释放的内存。这里只是简单的描述了检测内存泄漏的基本原理,详细的算法可以参见Steve Maguire的<<Writing Solid Code>>。
如果要检测堆内存的泄漏,那么需要截获住malloc/realloc/free和new/delete就可以了(其实new/delete最终也是用malloc/free的,所以只要截获前面一组即可)。对于其他的泄漏,可以采用类似的方法,截获住相应的分配和释放函数。比如,要检测BSTR的泄漏,就需要截获SysAllocString/SysFreeString;要检测HMENU的泄漏,就需要截获CreateMenu/ DestroyMenu。(有的资源的分配函数有多个,释放函数只有一个,比如,SysAllocStringLen也可以用来分配BSTR,这时就需要截获多个分配函数)
在Windows平台下,检测内存泄漏的工具常用的一般有三种,MS C-Runtime Library内建的检测功能;外挂式的检测工具,诸如,Purify,BoundsChecker等;利用Windows NT自带的Performance Monitor。这三种工具各有优缺点,MS C-Runtime Library虽然功能上较之外挂式的工具要弱,但是它是免费的;Performance Monitor虽然无法标示出发生问题的代码,但是它能检测出隐式的内存泄漏的存在,这是其他两类工具无能为力的地方。
以下我们详细讨论这三种检测工具:
VC下内存泄漏的检测方法
用MFC开发的应用程序,在DEBUG版模式下编译后,都会自动加入内存泄漏的检测代码。在程序结束后,如果发生了内存泄漏,在Debug窗口中会显示出所有发生泄漏的内存块的信息,以下两行显示了一块被泄漏的内存块的信息:
E:\TestMemLeak\TestDlg.cpp(70)     : {59} normal block at 0×00881710, 200 bytes long.
Data: <abcdefghijklmnop>     61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70
第一行显示该内存块由TestDlg.cpp文件,第70行代码分配,地址在0×00881710,大小为200字节,{59}是指调用内存分配函数的Request Order,关于它的详细信息可以参见MSDN中_CrtSetBreakAlloc()的帮助。第二行显示该内存块前16个字节的内容,尖括号内是以ASCII方式显示,接着的是以16进制方式显示。
一般大家都误以为这些内存泄漏的检测功能是由MFC提供的,其实不然。MFC只是封装和利用了MS C-Runtime Library的Debug Function。非MFC程序也可以利用MS C-Runtime Library的Debug Function加入内存泄漏的检测功能。MS C-Runtime Library在实现malloc/free,strdup等函数时已经内建了内存泄漏的检测功能。
注意观察一下由MFC Application Wizard生成的项目,在每一个cpp文件的头部都有这样一段宏定义:
#ifdef     _DEBUG
#define     new DEBUG_NEW
#undef     THIS_FILE
static     char THIS_FILE[] = __FILE__;
#endif
有了这样的定义,在编译DEBUG版时,出现在这个cpp文件中的所有new都被替换成DEBUG_NEW了。那么DEBUG_NEW是什么呢?DEBUG_NEW也是一个宏,以下摘自afx.h,1632行
#define     DEBUG_NEW new(THIS_FILE, __LINE__)
所以如果有这样一行代码:
char*     p = new char[200];
经过宏替换就变成了:
char*     p = new( THIS_FILE, __LINE__)char[200];
根据C++的标准,对于以上的new的使用方法,编译器会去找这样定义的operator new:
void*     operator new(size_t, LPCSTR, int)
我们在afxmem.cpp 63行找到了一个这样的operator new 的实现
void*     AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
    return     ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
}
void*     __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int     nLine)
{
    …
           pResult = _malloc_dbg(nSize, nType,     lpszFileName, nLine);
           if (pResult != NULL)
               return pResult;
    …
}
第二个operator new函数比较长,为了简单期间,我只摘录了部分。很显然最后的内存分配还是通过_malloc_dbg函数实现的,这个函数属于MS C-Runtime Library 的Debug Function。这个函数不但要求传入内存的大小,另外还有文件名和行号两个参数。文件名和行号就是用来记录此次分配是由哪一段代码造成的。如果这块内存在程序结束之前没有被释放,那么这些信息就会输出到Debug窗口里。
这里顺便提一下THIS_FILE,__FILE和__LINE__。__FILE__和__LINE__都是编译器定义的宏。当碰到__FILE__时,编译器会把__FILE__替换成一个字符串,这个字符串就是当前在编译的文件的路径名。当碰到__LINE__时,编译器会把__LINE__替换成一个数字,这个数字就是当前这行代码的行号。在DEBUG_NEW的定义中没有直接使用__FILE__,而是用了THIS_FILE,其目的是为了减小目标文件的大小。假设在某个cpp文件中有100处使用了new,如果直接使用__FILE__,那编译器会产生100个常量字符串,这100个字符串都是这个cpp文件的路径名,显然十分冗余。如果使用THIS_FILE,编译器只会产生一个常量字符串,那100处new的调用使用的都是指向常量字符串的指针。
再次观察一下由MFC Application Wizard生成的项目,我们会发现在cpp文件中只对new做了映射,如果你在程序中直接使用malloc函数分配内存,调用malloc的文件名和行号是不会被记录下来的。如果这块内存发生了泄漏,MS C-Runtime Library仍然能检测到,但是当输出这块内存块的信息,不会包含分配它的的文件名和行号。
要在非MFC程序中打开内存泄漏的检测功能非常容易,你只要在程序的入口处加入以下几行代码:
int     tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag     |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(     tmpFlag );
这样,在程序结束的时候,也就是winmain,main或dllmain函数返回之后,如果还有内存块没有释放,它们的信息会被打印到Debug窗口里。
如果你试着创建了一个非MFC应用程序,而且在程序的入口处加入了以上代码,并且故意在程序中不释放某些内存块,你会在Debug窗口里看到以下的信息:
{47}     normal block at 0×00C91C90, 200 bytes long.
Data: <            > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
内存泄漏的确检测到了,但是和上面MFC程序的例子相比,缺少了文件名和行号。对于一个比较大的程序,没有这些信息,解决问题将变得十分困难。
为了能够知道泄漏的内存块是在哪里分配的,你需要实现类似MFC的映射功能,把new,maolloc等函数映射到_malloc_dbg函数上。这里我不再赘述,你可以参考MFC的源代码。
由于Debug Function实现在MS C-RuntimeLibrary中,所以它只能检测到堆内存的泄漏,而且只限于malloc,realloc或strdup等分配的内存,而那些系统资源,比如HANDLE,GDI Object,或是不通过C-Runtime Library分配的内存,比如VARIANT,BSTR的泄漏,它是无法检测到的,这是这种检测法的一个重大的局限性。另外,为了能记录内存块是在哪里分配的,源代码必须相应的配合,这在调试一些老的程序非常麻烦,毕竟修改源代码不是一件省心的事,这是这种检测法的另一个局限性。
对于开发一个大型的程序,MS C-Runtime Library提供的检测功能是远远不够的。接下来我们就看看外挂式的检测工具。我用的比较多的是BoundsChecker,一则因为它的功能比较全面,更重要的是它的稳定性。这类工具如果不稳定,反而会忙里添乱。到底是出自鼎鼎大名的NuMega,我用下来基本上没有什么大问题。

2005年10月10日

  电脑在各个领域的应用越来越广泛,学习电脑大有成为社会上各工作岗位技能必修课之势,而汉字输入法作为使用电脑的基础,所以多数人都是先以学习汉字输入法做为电脑入门学习的。

  一、五笔输入法作为最快捷、最方便的一种输入法,学习的人也日益增多了,在这个大环境下,部分培训学校和某些五笔自学软件及一些书籍声称其能在一周内甚至更短的时间内就让初学者熟练地使用五笔进行汉字录入,其实对初学者而言,在一周后能熟练地进行英文盲打都不太可能,更不用说熟练地使用五笔输入法录入汉字了,这正是学习五笔的第一不要——“不要急功近利”!学习五笔一定“要循序渐进将基础打好”,明白这一点对初学者非常重要!不然的话就会让初学者产生厌烦情绪,试想一周后如果学习者并不能熟练地使用五笔,甚至连英文盲打都不利索的话,这位同志还会再继续学习下去吗?不会了,因为他这时会认为五笔很难学,甚至会认为是自己太笨,根本就不是学五笔的材料,对学习电脑的其它应用也会因此而逐渐失去兴趣,很可能从此半途而废……

  所以说,您不妨用一两周的时间先将英文盲打练熟以后再进行五笔的学习,正所谓万丈高楼平地起就是这个道理。注:很多人都是因此而“弃五从拼”的,甚至有人已练成了“一指神功”而“独步键林”!真不愧是“眼观二十六路”啊……

  二、明白并做到了上面的一要一不要后基本就能安下心来学习五笔了,在学习五笔字根的过程中多数人都会进入死记硬背的误区,这又会导致一大部分人因记性不太好或不经常使用电脑而放弃五笔的学习,这就是第二个不要——在记忆字根时“不要死记硬背”!“要进行模糊记忆”!

  上面的话可能有些同志不太理解,下面我就举几个例子并结合字根表进行说明,

如:N键中的折字根有很多,如果您一个一个地去记的话,天哪……不要害怕啊!其实这是有个规律可循的,只要是一笔能写下来的折字根全都是按N键,如“乃”的这个大折;又如:手的食指能按到的第一个键内必有一个字根为一,之后依次就是二三(四)字根了,横区内有一(G)二(F)三(D)横、竖区内有一(H)二(J)三(K)四(L)竖、撇区内有一(T)二(R)三(E)撇、点区内有一(Y)二(U)三(I)四(O)点,怎么样,有意思吧,这也是个规律,而且未笔识别码的编排也有非常类似的规律。诸如以上之类的规律还有很多,笔者就不逐一列举了,总而言之,真正需要我们牢牢记住的字根并不是很多,只要记住字根口决字面中的字根就足够了,其它的字根都是采用模糊记忆法就能记住的支脉字根。

  三、下面我再说一下第三个要与不要,“要理解记忆汉字拆分的四大原则”,“不要认为把字根和拆字原则背牢了就可以将所有的汉字全部拆开了”。在拆字时除了按书写顺序拆字为主原则外还要遵循四大原则,下面我就详细分析一下这四大拆字原则:1、取大优先,在遵循总原则的条件下拆字时应以“再添一个笔画便不能使其成为另一个字根”为限,每次都拆取一个“尽可能大”的,即尽可能笔画多的字根,例如“世”字第一种拆法为“一、凵、乙”(误),第二种拆法为“廿、乙”(正),显然前者是错误的,因为其第二个码元“凵”,完全可以向前“凑”到“一”上,形成一个“更大”的已知码元“廿”;2、兼顾直观,在拆分汉字时,为了照顾汉字码元的完整性,有时不得不暂且牺牲一下“书写顺序”和“取大优先”的原则,形成个别例外的情况,如“自”字按“取大优先”应拆成“亻、乙、三”,但这样拆,不仅不直观,而且也有悖于“自”字的字源(这个字的字源是“一个手指指着鼻子”)故只能拆作“丿、目”,这就叫做“兼顾直观”;3、能连不交,当一个字既可拆成相连的几个部分,也可拆成相交的几个部分时,我们认为“相连”的拆法是正确的,因为一般来说,“连”比“交”更为“直观”,如“丑”字可拆成乙土(二者是相连的)或刀二(二者是相交的),这时我们就认为前者拆法是正确的;4、能散不连,笔画和字根之间,字根与字根之间的关系,可以分为“散”、“连”和“交”的三种关系,其中就属散的优先权为最高,比如“倡”字就是散。另外您最好能记住笔者总结的一个重要原则:无论如何也不能连的字就以“取大优先”为重要原则,只要是能连下来的字就以“兼顾直观”为重要原则。注:上述几项原则相互之间相辅相成,并非相互独立。

  四、把上面提到的几点理解记牢了,就可较为熟练地使用五笔打字了,但是有些需要输入未笔识别码的字明明已将字根和未笔拆出来了,却无论如何也打不出来这个字,其实这八成是您将这个字的未笔拆错了,所以这就要求您一定“要记住一些特殊未笔”,“不要被书写习惯所束缚”。下面我就简单说一些特殊未笔:一、当“力、刀、九、匕”这些字根参加未笔“识别”时,一律以其“伸”得最长的“折”笔作为末笔;二、“我、戋、成”等字的“末笔”要遵从“从上到下”的原则,一律规定“丿”为其末笔;三、对于“义、太、勺”等字中的“单独点”而言其离码元的距离很难确定,可远可近,我们干脆认为这种“单独点”与其附近的码元是“相连”的,既然是“连”在了一起,这些字便属于杂合型而并非为上下型汉字。“四”、“连”、“逐”等字的未笔按书写习惯来写应该是“辶”的最后一捺,但由于带“辶”的字太多,所以在这里就要选用“车”或“豕”字的最后一笔为未笔了。

  五、下面要说的是第五不要与要,某些字在拆其字根时“不要中规中矩”,“要采用象形拆法”。比如“拽”字的最后一个字根不是叉,而是“匕”,这与“使”的最后一个字根是不一样的,但多数人拆这个字时都会拆成叉或折、撇等,诸如此类的字还有很多(如傲、氏、余等),所以您只能是看它最像什么就把它当作什么字根,不然的话,您也就只能使用“万能五笔”之类的混合型输入软件了,您是永远不可能完全屏弃拼音而单独使用五笔的。注:本项对学习五笔的人来说至关重要!实为重中之重!

  好了,不多说了,其实五笔并不是像大家想象的那么难学,当然也不会像某些广告和某些人所说的那么容易学,五笔输入法也并非是某些人口中所说的“熟练工”,当然,熟练还是很重要的,正所谓是熟成生巧,总而言之,只要您多注意一下五笔的一些规律的话,我相信您一定能成为五笔高手的,您迟早都会发现五笔要比拼音好用百倍的!GOOD LUCK!

  注:本文中提到的五要五不要在学习五笔输入法的人群中是很常见的一些问题,笔者在此只是简单地做了一下总结而已,您要真的想学习好五笔输入法的话还是需要您自己不断地去参悟其中的规律,其实光靠老师讲、看教材以及听取他人经验都不会对五笔的学习有多大益处的,用一句东北话说就是:“谁说也不好使!”

2005年10月09日

KOF经典动画~ 可做精彩签名

























2005年10月08日
By Trudy Pelzer
翻译:guipei
随着mysql 4.1版的发布,现在有两种方法可以使用一个单独的查询从多个数据表中取得数据:使用连接(join)或者使用子查询(subquery)。我们来举例说明,假设你有一下的表格:
 
CREATE TABLE clients (
  clno INT,
  fname VARCHAR(15),
  lname VARCHAR(15),
  job VARCHAR(15),
  account_balance DECIMAL(7,2));
 
INSERT INTO clients VALUES
  (10, ’sam’,’smith’,'auditor’,5525.75),
  (20,’james’,'jones’,'manager’,8960.25);
 
CREATE TABLE firms (
  clno INT,
  company VARCHAR(15),
  city VARCHAR(15));
 
INSERT INTO firms VALUES
  (10,’abc co’,'leduc’),
  (20,’def ltd’,'nisku’),
  (30,’ghi inc’,'nisku’);
下面我们使用连接(join)方法取得client表格中id为10的数据。
SELECT
  fname, lname, city, job, company, account_balance
  FROM clients c, firms f
  WHERE c.clno = f.clno
    AND c.clno = 10;
但是你并非总是可以通过使用连接(join)方式查询你所需要的数据。举一个例子,假如你需要最大的帐户表中的客户信息。下面的查询,看起来好像应该可以正确返回你所需要的数据,但是实际上会发生错误:
SELECT
  fname, lname, city, job, company, account_balance
  FROM clients c, firms f
  WHERE c.clno = f.clno
    AND c.account_balance = MAX(c.account_balance);
错误的原因是:invalid use of group function,就是这个聚合函数,Max,不允许出现在where子句当中。这也就是子查询诞生的原因,在本文当中,我将简短的描述添加到mysql数据库系统的子查询功能。
子查询就是包含在括号中选择语句
简单的将,子查询就是一个被写在另一个sql语句(一般情况下,是select语句,但是不总是这样)中的查询语句。判断是否是子查询的方式是看查询语句是否在括号中间,下面是一个例子。
SELECT * FROM clients WHERE clno IN                — outer query
   (SELECT clno FROM firms WHERE city = ‘leduc’);  — inner query
 
SELECT * FROM clients WHERE clno IN                — 外部查询
   (SELECT clno FROM firms WHERE city = ‘leduc’);  — 内部查询
 
这个查询将会返回表clients中clno中所有城市为’leduc’的记录。为了得到结果,dbms首先会取得内部查询的结果,查找所有 表 clno中所有城市为‘leduc’的记录。然后比较表clients,返回符合clno值的每一行。因为只有一个值符合子查询,实际上,等效于下面语句:
SELECT * FROM clients WHERE clno = 10;
当然,这个查询语句也可以写成以下方式:
SELECT
  c.clno, fname, lname, job, account_balance
  FROM clients c INNER JOIN firms f USING (clno)
  WHERE city = ‘leduc’;
目前,就上面提到的问题,可以通过子查询解决(查询这些客户clno值最大的记录):
SELECT fname, lname FROM clients WHERE clno =
  (SELECT MAX(clno) FROM firms);
如果内部查询返回空结果集,子查询会返回错误,举例说明,参看下面查询:
SELECT * FROM clients WHERE clno =
  (SELECT clno FROM firms WHERE city = ‘gibbons’);
如果内部查询单独运行的话,很显然结果为空:因为这个表中没有city等于’gibbons’的记录。但是空的结果集不能作为值来比较。SQL 标准要求子查询的结果集,空的结果集,或者为空。因为没有任何东西等于null,查询返回空消息。
一般来说,子查询是嵌套在其他的查询当中,MySql支持子查询嵌套在其他sql语句当中,这是一个很好的功能。
Types of Subqueries
子查询类型
子查询共有三种类型,区分它们的方法是根据返回结果的列数和行数。
如果一个子查询返回仅仅一列一行数据,被成为数量级子查询。一个数量级子查询可以用在任何适合数据值比较的地方(一个列值或者文本)。它常常被使用在where子句当中,跟随在比较操作符号后面。
如果子查询返回多个列,并且是一行记录的话,它被称为行级子查询。行级子查询是数量级子查询的发展,可以用在任何适合数量级子查询的地方。
最后,如果一个子查询返回多个列和多行的话,它被称为表级子查询。表级子查询可以用作涉及到表的查询操作,包含在from子句当中。它也常常被用在where子句当中,后面使用in 或者 exist或者一个确定的比较操作(确定的比较操作是一个比较操作通过使用some,all,或者any限定)。
数量级子查询和表级子查询的区别非常小。经常会出现在一个数量级子查询被编写的情况下,但是子查询返回多个记录行。假设我们有两个表和一些记录数据。
INSERT INTO clients VALUES
  (10, ’sam’,’smith’,'auditor’,5525.75);
 
INSERT INTO firms VALUES
  (10,’abc co’,'leduc’),(30,’ghi inc’,'nisku’);
因为在这个查询中表firms有两行记录返回:
SELECT * FROM clients WHERE clno <
  (SELECT clno FROM firms);
错误原因:
"Subquery returns more than 1 row"
 
这种情况有两个解决方法。第一个是修改查询让其用any包含,使外部查询的比较任意的值 :
SELECT * FROM clients WHERE clno < ANY
  (SELECT clno FROM firms);
在这里,第一个比较是(10<10),返回为false,但是第二个比较(10<30),返回true,因此子查询返回true,使用的是 clno 10相比较的结果,使用any 的规则如下:
ANY返回true,如果子查询的比较操作至少有一个是是true。
ANY 返回 false,如果子查询返回为空行,或者比较任意一行都是false。
ANY的同义词是SOME,使用in 等同于使用 = ANY。
第二种方法是修改查询,使用all包含子查询,比较外部的查询结果使用每一个子查询的值。
SELECT * FROM clients WHERE clno < ALL
  (SELECT clno FROM firms);
在这里,第一次的比较还是返回false,而第二此返回true,最后,子查询的结果是false,所以查询返回空行。使用all的规则是:
返回true,如果子查询返回空行记录,或者子查询的每一个结果比较都为true的话。
返回false,如果子查询至少有一个比较结果返回false。
Does the Subquery Return at least One Row?
子查询至少要求返回一行么?
在有些时候,查询的结果是子查询是否有一个结果返回。使用[NOT] EXISTS来判断结果集是否为空。如果你的子查询至少有一行返回,使用EXISTS 返回 true;否则,返回为false。还有一种用法,NOT EXISTS,如果子查询结果集为空,它返回为true,否则的话,返回为true。一般情况下,子查询跟随在 [NOT] EXISTS后面,以select * 开头。在这里,星号(*)不是表示列出所有的列,而是表示为列出一些列。这里有一个小例子,返回所有client表的结果。
 
SELECT * FROM clients WHERE EXISTS
  (SELECT * FROM firms);
在本例当中,where子句返回true,因为表firms不为空。通常[NOT] EXISTS会使用在更加复杂的情况下面,假设你有一下数据表:
CREATE TABLE passengers (
   name VARCHAR(15),
   compartment INT);
 
INSERT INTO passengers VALUES (’smith’,20);
INSERT INTO passengers VALUES (‘jones’,25);
 
CREATE TABLE cars (
   compartment INT,
   class VARCHAR(10));
 
INSERT INTO cars VALUES (20,’first’);
下面是这中类型的查询:
SELECT * FROM cars c1 WHERE NOT EXISTS
  (SELECT * FROM passengers p1 WHERE NOT EXISTS
    (SELECT * FROM cars c2
       WHERE c2.compartment = p1.compartment
         AND c2.compartment = c1.compartment));
这个查询的作用是请求查找所有存在乘客的汽车。为了理解这个结果集的含义,我们假设Smith在20号汽车,Jones在25号汽车,但是在cars表中没有包含25号汽车。这样就会有一个乘客―Jones―乘坐一个不存在的汽车。(在标准的数据库中,不会存在这种情况,可以通过使用主键/外键来约束这两个表间的数据完整性)。这个查询中的第二个NOT EXISTS子查询,返回true对于乘客Jones。
另外,这里的一个乘客―Jones,没有乘坐20号汽车。因此第一个NOT EXISTS子查询在这里返回false。因为这里没有其他汽车被检查,这个查询的结果是空(返回零行)――这里没有汽车每一个乘客都乘坐。
子查询的其他用法
在sql标准1999中,Mysql提供了增强的子查询支持。在前面提到的行级子查询,现在支持一次比较多个列的值:
SELECT ROW (’smith’, ‘auditor’) =
   (SELECT lname, job FROM clients WHERE clno = 10);
在这个例子中,子查询包含值为’smith’ 和 ‘auditor’的数据。这些数据和ROW的值就行比较时,他们的内容一样,因此返回1(true)。
你也可以把一个子查询,作为一个表名,放在from子句后面(就像oracle里面的用法一样,作为内部视图):
SELECT * FROM
  (SELECT * FROM clients WHERE job LIKE ‘a%’) AS cl;
为了取得这个查询的结果,mysql服务器熟悉取得子查询的结果,然后把结果集赋予别名(cl,在本例中)。然后让外部的查询使用。实际上,上面的例子可以被分解如下:
SELECT * FROM cl;
这里cl作为一个子查询的临时结果集:
SELECT * FROM clients WHERE job LIKE ‘a%’;
当子查询被使用在from 子句当中,关键字as是强制使用的;中间的临时结果必须被命名,作为外部的查询被引用。
使用子查询修改数据
子查询还有这样的一个功能:用来修改数据库的数据。这就是说,你可以把子查询放在delete,insert,update或者replace语句里面,我们举例说明:
UPDATE clients SET account_balance =
  (SELECT SUM(amount) FROM accounts where clno=clients.clno);
这个update语句为每一个客户修改 account_balance 数据,通过计算account表中的客户帐号。
这里有一个提示:目前不允许使用同一个表的子查询来修改这个表中的数据。
 
总结:
子查询在mysql 4.1版中新添加,现在支持数量、行、表的子查询。
比较操作符号= <> < <= > >=可以使用在子查询中,并且可以使用[NOT] IN 和 [NOT] EXISTS子句。
表级子查询可以使用短句ANY/SOME 或者 ALL做比较。
子查询可以用来修改数据。
2005年10月02日

    看武侠的人谁没看过古龙?
    喜欢他的人,对他的书和人念念不忘。不喜欢他的人,只对他的私生活津津乐道。因为一直都有这样一种传说在世间流转:古龙的一生唯酒与女人是重。
    一直认为古龙是一位孤独而多情的剑客,就像他书中决战千里的侠客,左手葫芦右手剑,剑一出鞘高下立分,干净利落。所以古龙嗜酒,纵酒狂歌侠气冲天。藏酒是古龙的爱好,喝酒是古龙的乐趣,他的生活全在他用一腔热血写著的武侠世界中。细看古龙笔下的傅红雪,孟星魂,王动……不都是与他相似的外表平凡内心孤高的豪情人物。古龙的人和他作品中的人都是与他的藏酒相同的,只的开了盖才令人惊觉其内里的醇香。
    古龙说:“古龙之所以为古龙,这就是了,我不是圣贤豪杰,我只有一腔热血。”他在书中创造的也正是这种一腔热血的人和一腔热血的情感。朋友,要与有热血的人交;酒,要与有热血的人喝;恋爱,要与有热血的人谈;死要为有热血的人死(林清玄语)。热血让人傲骨铮铮,热血让人豪情万丈,热血让人顶天立地。
    古龙的传奇绝对不同于金庸的传奇。古龙的英雄就像是你生活中的某一个陌生或熟悉的真汉子,有着与你相同的情感相同的缺点,甚至也会像你一样为窘迫的生活而无奈,有时也会犯点傻。古龙用他的才情与独特的思维方式开创了一个崭新的武侠时代,这个时代紧随着他的离世而无奈地终结。好笑的是,总有些无聊的人标榜自己得了古龙的真传在武侠世界现眼。
    我爱武侠,所以我也爱古龙。因为我想做一个他书中的一生快乐的真性情的老实人。
    我爱古龙,是因为古龙就是古龙。 独一无二的古龙。
    能不忆古龙!
    
    古龙作品列表
    《苍穹神剑》 1960 处女作
    《月异星邪》 1960
    《剑气书香》 1960 后半部由墨余生代写
    《湘妃剑》 1960
    《剑毒梅香》 1960 大部分由上官鼎代写
    《孤星传》 1960
    《失魂引》 1961
    《游侠录》 1961
    《护花铃》 1962
    《彩环曲》 1962
    《残金缺玉》 1962
    《飘香剑雨》 1963
    《剑玄录》 1963
    《剑客行》 1963
    《浣花洗剑录》 1964
    《情人剑》 1964 1976年改为《怒剑》
    《大旗英雄传》 1965 1976年改为《铁血大旗》
    《武林外史》 1965
    《名剑风流》 1966 结尾由乔奇代写
    《绝代双骄》 1967
    《铁血传奇》 1967 又名《楚留香传奇》,分为《血海飘香》《大沙漠》《画眉鸟》
    《多情剑客无情剑》 1969 分为《风云第一刀》《铁胆大侠魂》
    《萧十一郎》 1970
    《流星 蝴蝶 剑》 1970
    《鬼恋侠情》 1970 又称《借尸还魂》 楚留香续一
    《蝙蝠传奇》 1971 楚留香续二
    《欢乐英雄》 1971
    《大人物》 1971
    《桃花传奇》 1972 楚留香续三
    《九月鹰飞》 1972 《风云第一刀》后传
    
    七种武器系列:(仅完成六部)
    1、《长生剑》 1971
    2、《碧玉刀》 1971
    3、《孔雀翎》 1972
    4、《多情环》 1972
    5、《霸王枪》 1973
    6、《离别钩》 1979
    
    《火并萧十一郎》 1973
    《天涯 明月 刀》 1973
    《决不低头》 1973 武侠色彩现代枪战小说
    《拳头》 1973 又名《愤怒的小马》
    《七杀手》 1973
    《剑 花 烟雨江南》 1974
    
    陆小凤系列
    1、《陆小凤传奇》 1972
    2、《绣花大盗》 1973
    3、《决战前后》 1973
    4、《银钩赌坊》 1974
    5、《幽灵山庄》 1975
    6、《凤舞九天》 1975
    
    《边城浪子》 1974 《天涯明月刀》后传
    《血鹦鹉》 1975 《惊魂六记之一》
    《三少爷的剑》 1975 《江湖人之一》
    《白玉老虎》 1976
    《飘泊英雄传》 1976 大部分由温玉代写
    《大地飞鹰》 1976
    《圆月弯刀》 1977 部分由司马紫烟代写
    《飞刀,又见飞刀》 1977
    《碧血洗银枪》 1977
    《新月传奇》 1978 楚留香传奇之四
    《英雄无泪》 1978
    《七星龙王》 1978
    《午夜兰花》 1979 楚留香传奇之五
    《风铃中的刀声》 1980 结尾由于东楼代写
    《剑神一笑》 1981
    《怒剑狂花》 1982
    《白玉雕龙》 1981 白玉老虎后传 大部分由申碎梅代写
    《那一剑的风情》 1982 大部分由丁情代写
    《边城刀声》 1983
    《猎鹰 赌局》 1984 最后遗作 短篇
    
    另查还有:《神州山庄》《长河落日剑》《长干行》《剑气满天花满楼》《快刀浪子》《迷光血影》《不是集》《墨宝》《江海英雄》等几部似是而非扑朔迷离的作品,尚待细查考证,以验明正身。