SQL语言的使用

来源:互联网 发布:淘宝出售假冒商品影响 编辑:程序博客网 时间:2024/04/29 07:19


sql中SELECT语句的使用方法

sql select case
select  (case Power when 'A' then '員工' when 'B' then '管理員' when 'C' then '系統管理員' end)as c0
FROM dbo.employee
case FieldName When 0 then 1 when Null then 1 else FieldName end) as FieldName

sql语法case用法
                                     

CASE 可能是 SQL 中被误用最多的关键字之一。虽然你可能以前用过这个关键字来创建字段,但是它还具有更多用法。例如,你可以在 WHERE

子句中使用 CASE。

首先让我们看一下 CASE 的语法。在一般的 SELECT 中,其语法如下:

SELECT =
CASE
WHEN THEN
WHEN THEN
ELSE
END

在上面的代码中需要用具体的参数代替尖括号中的内容。下面是一个简单的例子:

USE pubs
GO
SELECT
Title,
'Price Range' =
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END
FROM titles
ORDER BY price
GO

对于informix不能用以上形式,可以如下:
USE pubs
GO
SELECT
Title,
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END
Price Range
FROM titles
ORDER BY price
GO


这是 CASE 的典型用法,但是使用 CASE 其实可以做更多的事情。比方说下面的 GROUP BY 子句中的 CASE:

SELECT 'Number of Titles', Count(*)
FROM titles
GROUP BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END
GO

你甚至还可以组合这些选项,添加一个 ORDER BY 子句,如下所示:

USE pubs
GO
SELECT
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END AS Range,
Title
FROM titles
GROUP BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END,
Title
ORDER BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END,
Title
GO

对于informix中形式有所不同,例子
select
case when td_acc1_no[1,3]='610' then get_contrast(td_acc1_no)
                 else get_contrast(td_td_acct_no)
                 end sx_acct_no
,               sum(td_actu_amt) sx_bal
from dcc_tdacnacn where td_td_acct_no in ('6107111001014107111000050182',
'6107111001014107111000050168')
group by   1


注意,为了在 GROUP BY 块中使用 CASE,查询语句需要在 GROUP BY 块中重复 SELECT 块中的 CASE 块。

除了选择自定义字段之外,在很多情况下 CASE 都非常有用。再深入一步,你还可以得到你以前认为不可能得到的分组排序结果集。

 

 


数据表都已经创建起来了,假设我们已经插入了许多的数据,我们就可以用自己喜欢的方式对数据表里面的信息进行检索和显示了,比如说:可以象下面这样把整个数据表内的内容都显示出来
select * from president;
也可以只选取某一个数据行里的某一个数据列
select birth from president where last_name=’Eisenhower’;
select语句的通用形式如下:
select 你要的信息
from 数据表(一个或多个)
where 满足的条件
select语句有几个子句,他们的各种搭配能帮你查出最感兴趣的信息,这些子句可以很简单,也可以很复杂,看看作者是如何详细讲解的

1, 用各种操作符来设定检索条件
要想让select语句只把满足特定条件的记录检索出来,就必须给它加上where字句来设置数据行的检索条件。只有这样,才能有选择地把数据列的取值满足特定要求的那些数据行挑选出来。可以针对任何类型的值进行查找,比如说,对数值进行搜索
select * from score where score>95; //显示所有分数在95分以上的信息
也可以针对字符串值进行查找
select last_name,first_name from president where last_name=’Tom’; //找出所有姓tom的总统
还可以对不同类型的值进行组合查找
select last_name,first_name,birth,state from president
where birth<’1950-1-1’ and (state=’VA’ or state=’BA’);
//找出1950年前出生于VA州或BA州的总统
可见 where子句中可以使用的是算术操作符( -*/%),比较操作符(<>=)以及逻辑运算符,我们应该熟练理解这些操作符的含义(都很简单)

2, NULL 值的特别处理
这是一种不属于任何类型的值。它通常用来表示“没有数据”“数据未知”“数据缺失”“数据超出取值范围”“与本数据列无关”“与本数据列的其它值不同”等多种含义。在许多情况下,NULL 值是非常有用的。
我们的各种操作符是不能对NULL 值进行处理的,如果相对NULL 值进行查找,用的是 is null 或 is not null 来进行判断,举例如下:
select last_name,first_name,birth,state from president
where death is null; //找出所有没死的总统

 

 

 

 

 


////////////////////////////////////////////////////////////////////////

 

用于SELECT和WHERE子句的SQL函数来源:

一个 SQL 语句中的 select_expression 或 where_definition 可由任何使用了下面所描述函数的表达式组成。phpma

包含 NULL 的表达式总是得出一个 NULL 值结果,除非表达式中的操作和函数在文档中有另外的说明。

注意:在一个函数名和跟随它的括号之间必须不存在空格。这有助于 MySQL 语法分析程序区分函数调用和对恰巧与函数同名表或列的引用。然而,参数左右两边的空格却是允许的。

你可以强制 MySQL 接受函数名后存在空格的形式,这需要通过以 --ansi 选项启动 mysqld,或在 mysql_connect() 中使用 CLIENT_IGNORE_SPACE,但是,在这种情况下,所有的函数名均将成为保留字。查看章节 1.8.2 以 ANSI 模式运行 MySQL.

为了简洁,从 mysql 程序输出的例子以缩写的形式显示。因此:phpma

mysql> SELECT MOD(29,9);
1 rows in set (0.00 sec)

+-----------+
| mod(29,9) |
+-----------+
| 2 |
+-----------+

将被显示为这样:

mysql> SELECT MOD(29,9);
-> 2

6.3.1 无类型的特殊运算符和函数phpma
6.3.1.1 圆括号

( ... )

括号,使用它来强制一个表达式的计算顺序。phpma

mysql> SELECT 1+2*3;
-> 7
mysql> SELECT (1+2)*3;
-> 9

6.3.1.2 比较运算符

比较运算符的结果是 1 (TRUE)、0 (FALSE) 或 NULL。这些函数可工作于数字和字符串上。根据需要,字符串将会自动地被转换到数字,以及数字被转换成字符串(比如在 Perl 中)。

MySQL 使用下列规则进行比较:phpma

* 如果一个或两个参数是 NULL,比较的结果是 NULL,除了 <=> 运算符。phpma
* 如果在一个比较操作中两个参数均是字符串,他们将作为字符串被比较。
* 如果两个参数均是整数,他们作为整数被比较。
* 十六进制值如果不与一个数字进行比较,那么它将当作一个二进制字符串。
* 如果参数之一是一个 TIMESTAMP 或 DATETIME 列,而另一参数是一个常数,在比较执行之前,这个常数被转换为一个时间戳。这样做是为了对 ODBC 更友好。
* 在所有其它情况下,参数作为浮点(real)数字被比较。 phpma

缺省地,字符串使用当前字符集以忽略字母大小写的方式进行比较(缺省的字符集为 ISO-8859-1 Latin1,它对英语处理得很出色)。

下面的例子演示了对于比较操作字符串到数字的转换:phpma

mysql> SELECT 1 > '6x';
-> 0
mysql> SELECT 7 > '6x';
-> 1
mysql> SELECT 0 > 'x6';
-> 0
mysql> SELECT 0 = 'x6';
-> 1

=
等于:

mysql> SELECT 1 = 0;
-> 0
mysql> SELECT '0' = 0;
-> 1
mysql> SELECT '0.0' = 0;
-> 1
mysql> SELECT '0.01' = 0;
-> 0
mysql> SELECT '.01' = 0.01;
-> 1

<>
!=
不等于:

mysql> SELECT '.01' <> '0.01';
-> 1
mysql> SELECT .01 <> '0.01';
-> 0
mysql> SELECT 'zapp' <> 'zappp';
-> 1

<=
小于或等于:

mysql> SELECT 0.1 <= 2;
-> 1

<
小于:

mysql> SELECT 2 < 2;
-> 0

>=
大于或等于:

mysql> SELECT 2 >= 2;
-> 1

>
大于:

mysql> SELECT 2 > 2;
-> 0

<=>
NULL 值安全等于:

mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
-> 1 1 0

IS NULL
IS NOT NULL
测试一个值是或不是 NULL:

mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
-> 0 0 1
mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
-> 1 1 0

为了能够与其它程序更好的工作,在使用 IS NULL 是 MySQL 支持下列额外选择性:

* 通过它,你可以找到最后插入的记录行:

SELECT * FROM tbl_name WHERE auto_col IS NULL

这个操作可以通过设置 SQL_AUTO_IS_NULL=0 来禁止。查看章节 5.5.6 SET 句法.phpma
* 对于 NOT NULL 的 DATE 和 DATETIME 列,可以通过使用下列语句找到特殊的值 0000-00-00:

SELECT * FROM tbl_name WHERE date_column IS NULL

这需要通过某些 ODBC 应用程序才能工作(因为 ODBC 不支持一个 0000-00-00 日期)

expr BETWEEN min AND maxphpma
如果 expr 大于或等于 min ,并且 expr 小于或等于 max,BETWEEN 返回 1,否则返回 0。它等价于表达式 (min <= expr AND expr <= max) ,只要所有的参数均是相同的类型。 否则类型会依照上面的规则发生转换,但是应用于所有三个参数。注意,在 MySQL 4.0.5 之前,参数被转换到 expr 的类型。

mysql> SELECT 1 BETWEEN 2 AND 3;phpma
-> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
-> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
-> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
-> 0

expr NOT BETWEEN min AND max
等同于 NOT (expr BETWEEN min AND max)。

expr IN (value,...)
如果 expr 是 IN 列表中的作一值,它将返回 1,否则返回 0。如果所有的值均是常数,那么所有的值被依照 expr 的类型进行计算和排序。然后以一个二进制搜索方式完成项目的搜索。这就意味着,如果 IN 列表完全由常数组成,IN 将是非常快的。如果 expr 是一个字母大小写敏感的字符串表达式,字符串比较将以大小写敏感方式执行:phpma

mysql> SELECT 2 IN (0,3,5,'wefwf');
-> 0
mysql> SELECT 'wefwf' IN (0,3,5,'wefwf');
-> 1

从 MySQL 4.1 开始(符合 SQL-99 标准),如果左手边的表达式是 NULL,或者在列表中没有发现相匹配的值并且列表中的一个表达式是 NULL,IN 均返回 NULL。

expr NOT IN (value,...)
等同于 NOT (expr IN (value,...))。phpma

ISNULL(expr)
如果 expr 是 NULL,ISNULL() 返回 1,否则返回 0:

mysql> SELECT ISNULL(1+1);
-> 0
mysql> SELECT ISNULL(1/0);
-> 1

注意,对 NULL 值使用 = 进行比较总是为 false !
COALESCE(list)
返回列表中第一个非 NULL 的元素:


mysql> SELECT COALESCE(NULL,1);
-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL

INTERVAL(N,N1,N2,N3,...)
Returns 如果 N < N1 返回 0,如果 N < N2 返回 1,等等。所有的参数均被当作整数。为了函数能正确地工作,它要求 N1 < N2 < N3 < ... < Nn。这是因为它使用的是一个二进制的搜索(非常地快):phpma

mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
-> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
-> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
-> 0

如果以任何一个标准运算符(=, <>..., 但除了 LIKE)对一个忽略大小写的字符串进行比较,尾部的空白空间(空格、TAB 和换行)均被忽略。

mysql> SELECT "a" ="A /n";
-> 1

6.3.1.3 逻辑运算符phpma

在 SQL 中,所有的逻辑运算符返回的值均为 TRUE、FALSE 或 NULL (未知)。在 MySQL 中,它们由 1 (TRUE)、0 (FALSE) 和 NULL 实现。这些大部分在不同的 SQL 数据库间是相同的,然而某些可能会以一个非零值返回 TRUE。

NOT
!
逻辑非。如果操作数为 0,返回 1;如果操作数为非零,返回 0;如果操作数为 NOT NULL,返回 NULL。phpma

mysql> SELECT NOT 10;
-> 0
mysql> SELECT NOT 0;
-> 1
mysql> SELECT NOT NULL;
-> NULL
mysql> SELECT ! (1+1);
-> 0
mysql> SELECT ! 1+1;
-> 1

最后一个例子返回 1,因为表达式是与 (!1)+1 一样被计算的。

AND
&&
逻辑与。如果所有的操作数都是非零或非 NULL 的,返回 1;如果有一个或多个操作数为 0 ,则返回 0,只要操作数中有 NULL 返回值就为 NULL。

mysql> SELECT 1 && 1;
-> 1
mysql> SELECT 1 && 0;
-> 0
mysql> SELECT 1 && NULL;
-> NULL
mysql> SELECT 0 && NULL;
-> 0
mysql> SELECT NULL && 0;
-> 0

请注意,在 MySQL 4.0.5 以前版本中,当遇到一个 NULL 时就停止计算,而不是继续进程检查可能存在的0。这就意味着,在这些版本中,SELECT (NULL AND 0) 返回 NULL,而不是 0。在 4.0.5 中,代码已被重新设计了,已便于在任何仍然使用优化情况下,返回值总是能如 ANSI 所规定的那样。
OR
||
逻辑或。如果任何一个操作数是非零的,返回值为 1,如果任一操作数为 NULL,返回值为 NULL,否则返回 0。

mysql> SELECT 1 || 1;
-> 1
mysql> SELECT 1 || 0;
-> 1
mysql> SELECT 0 || 0;
-> 0
mysql> SELECT 0 || NULL;
-> NULL
mysql> SELECT 1 || NULL;
-> 1

XOR
逻辑异或。如果任一操作数为 NULL,返回值为 NULL。对于非 NULL 的操作数,如果有奇数个非零的操作数,结果返回为 1,否则返回 0。

mysql> SELECT 1 XOR 1;
-> 0
mysql> SELECT 1 XOR 0;
-> 1
mysql> SELECT 1 XOR NULL;
-> NULL
mysql> SELECT 1 XOR 1 XOR 1;
-> 1

a XOR b 算术相等于 (a AND (NOT b)) OR ((NOT a) and b)。 XOR 在 MySQL 4.0.2 中被添加。

6.3.1.4 控制流函数phpma

IFNULL(expr1,expr2)
如果 expr1 为非 NULL 的,IFNULL() 返回 expr1,否则返回 expr2。IFNULL() 返回一个数字或字符串值,这取决于它被使用的语境:

mysql> SELECT IFNULL(1,0);
-> 1
mysql> SELECT IFNULL(NULL,10);
-> 10
mysql> SELECT IFNULL(1/0,10);
-> 10
mysql> SELECT IFNULL(1/0,'yes');
-> 'yes'

在 MySQL 4.0.6 和更新版本中,IFNULL(expr1,expr2) 的默认返回值以 STRING、REAL 或 INTEGER 顺序更加'general'了两个表达式。当你基于一个表达式创建一个表或在一个临时表中 MySQL 不得不存储一个从 IFNULL() 返回的值时,这个与较早 MySQL 版本的不同将更加值得注意。

CREATE TABLE foo SELECT IFNULL(1,"test") as test;

在 MySQL 4.0.6 中,列 'test' 的类型为 CHAR(4),然而在较早的版本中,你得到的却是 BIGINT。

NULLIF(expr1,expr2)
如果 expr1 = expr2 为真,返回 NULL,否则返回 expr1。它等同于 CASE WHEN x = y THEN NULL ELSE x END:

mysql> SELECT NULLIF(1,1);
-> NULL
mysql> SELECT NULLIF(1,2);
-> 1

注意,如果参数不相等,在 MySQL 中,expr1 被求值两次。phpma

IF(expr1,expr2,expr3)
如果 expr1 为真(expr1 <> 0 以及 expr1 <> NULL),那么 IF() 返回 expr2,否则返回 expr3。IF() 返回一个数字或字符串,这取决于它被使用的语境:

mysql> SELECT IF(1>2,2,3);
-> 3
mysql> SELECT IF(1<2,'yes','no');
-> 'yes'
mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
-> 'no'

如果 expr2 或 expr3 明确地为 NULL,那么函数 IF() 的返回值类型为非 NULL 列的类型。(这在选择在 MySQL 4.0.3 中新加入)。 expr1 是作为一个整数值被计算的,这就意味着,如果测试的是一个浮点型或字符串值,就必须进行比较操作:

mysql> SELECT IF(0.1,1,0);
-> 0
mysql> SELECT IF(0.1<>0,1,0);
-> 1

在上面第一种情况下,IF(0.1) 返回 0,是因为 0.1 被转换为一个整数值,返回 IF(0) 的测试结果。这可能不是你所期望的。在第二种情况下,比较测试原浮点数是否为一个非零值。比较的结果被作为整数使用。 缺省的 IF() 返回值类型 (当结果存储在临时表中时,这是非常重要的) 在 MySQL 3.23 中按下列方式确定:
表达式 返回值
表达式(expr2)或表达式(expr3)返回值为字符串 字符串
表达式(expr2)或表达式(expr3)返回值为浮点型值 浮点型phpma
表达式(expr2)或表达式(expr3)返回值为整型 整型
如果表达式(expr2)和表达式(expr3)均是字符串,同时两个字符串均是忽略字母大小写的,那么返回值也是忽略字母大小写的(从 MySQL 3.23.51 开始)。

CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
第一个形式当 value=compare-value 时返回 result。第二个形式当第一个为真值的 condition 出现时,返回该条件的结果。如果没有匹配的结果值,那么 ELSE 后的结果将被返回。如果没有 ELSE 部分,那么 NULL 被返回:

mysql> SELECT CASE 1 WHEN 1 THEN "one"
WHEN 2 THEN "two" ELSE "more" END;
在某些情况下,NULL 值是很有用的类型,大家慢慢就会理解的。
用于SELECT和WHERE子句的SQL函数来源:网络 作者:本站整理 时间:2007-06-18 Tag: 点击: 1682
-> "one"
mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
-> "true"
mysql> SELECT CASE BINARY "B" WHEN "a" THEN 1 WHEN "b" THEN 2 END;
-> NULL

返回值的类型 (INTEGER、DOUBLE 或 STRING) 与第一个返回值(第一个 THEN 后的表达式)的类型相同。
6.3.2 字符串函数

如果返回结果的长度超过服务器参数 max_allowed_packet 的大小,字符串值函数将返回 NULL。查看章节 5.5.2 调节服务器参数。

对于操作字符串位置的函数,第一个位置被标记为 1。phpma

ASCII(str)
返回字符串 str 最左边的那个字符的 ASCII 码值。如果 str 是一个空字符串,那么返回值为 0。如果 str 是一个 NULL,返回值也是 NULL:

mysql> SELECT ASCII('2');
-> 50
mysql> SELECT ASCII(2);
-> 50
mysql> SELECT ASCII('dx');
-> 100

也可参看 ORD() 函数。

ORD(str)
如果字符串 str 的最左边的字符是一个多字节的字符,根据多字节字符的成分字符的 ASCII 码值通过下面的公式计算返回那个的编码:((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code...]。如果最左边的字符不是一个多字节字符,返回值与 ASCII() 函数相同:

mysql> SELECT ORD('2');
-> 50

CONV(N,from_base,to_base)
在不同的数字基数之间转换数字。将数字 N 从 from_base 转换到 to_base,并以字符串表示形式返回。如果任何一个参数为 NULL,那么返回值也为 NULL。参数 N 被解释为是一个整数,但是也可以被指定为一个整数或一个字符串。最小基为 2,最大基为 36。如果 to_base 是一个负值,N 将被看作为是一个有符号数字。否则,N 被视为是无符号的。CONV 以 64 位精度工作:phpma

mysql> SELECT CONV("a",16,2);
-> '1010'
mysql> SELECT CONV("6E",18,8);
-> '172'
mysql> SELECT CONV(-17,10,-18);
-> '-H'
mysql> SELECT CONV(10+"10"+'10'+0xa,10,10);
-> '40'

BIN(N)
返回 N 的字符串表示的二进制值形式,在这里,N 长长的(BIGINT)数字。这个函数等价于 CONV(N,10,2)。如果 N 是一个 NULL,返回值也是 NULL:

mysql> SELECT BIN(12);
-> '1100'

OCT(N)
返回 N 的字符串表示的八进制值形式,在这里,N 是一个长长的数字。这个函数等价于 CONV(N,10,8)。如果 N 是一个 NULL,返回值也是 NULL :

mysql> SELECT OCT(12);
-> '14'

HEX(N_or_S)
如果 N_OR_S 是一个数字,返回 N 的字符串表示的十六进制值形式,这里 N 是一个长长的(BIGINT)数字。这个函数等价于 CONV(N,10,16)。 如果 N_OR_S 是一个字符串,N_OR_S 中的每个字符均被转换为 2 位十六进制数字,并以十六进制的字符串形式返回。这是 0xff 形式的字符串反转操作。

mysql> SELECT HEX(255);
-> 'FF'
mysql> SELECT HEX("abc");
-> 616263
mysql> SELECT 0x616263;
-> "abc"

CHAR(N,...)
CHAR() 以整数类型解释参数,返回这个整数所代表的 ASCII 码值给出的字符组成的字符串。NULL 值将被忽略:

mysql> SELECT CHAR(77,121,83,81,'76');
-> 'MySQL'
mysql> SELECT CHAR(77,77.3,'77.3');
-> 'MMM'

CONCAT(str1,str2,...)
将参数连接成字符串返回。如果有任何一个参数为 NULL,返回值也为 NULL。可以有超过 2 个的参数。数字参数将被转换为相等价的字符串形式:

mysql> SELECT CONCAT('My', 'S', 'QL');
-> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
-> NULL
mysql> SELECT CONCAT(14.3);
-> '14.3'

CONCAT_WS(separator, str1, str2,...)
CONCAT_WS() 支持 CONCAT 加上一个分隔符,它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间:

mysql> SELECT CONCAT_WS(",","First name","Second name","Last Name");
-> 'First name,Second name,Last Name'
mysql> SELECT CONCAT_WS(",","First name",NULL,"Last Name");
-> 'First name,Last Name'

LENGTH(str)
OCTET_LENGTH(str)
CHAR_LENGTH(str)
CHARACTER_LENGTH(str)
返回字符串 str 的长度:

mysql> SELECT LENGTH('text');
-> 4
mysql> SELECT OCTET_LENGTH('text');
-> 4

注意,CHAR_LENGTH() 和 CHARACTER_LENGTH() 对于多字节字符只计数一次。phpma

BIT_LENGTH(str)
返回字符串 str 的比特长度:

mysql> SELECT BIT_LENGTH('text');
-> 32

LOCATE(substr,str)
POSITION(substr IN str)
返回子串 substr 在字符串 str 中第一次出现的位置。如果子串 substr 在 str 中不存在,返回值为 0:

mysql> SELECT LOCATE('bar', 'foobarbar');
-> 4
mysql> SELECT LOCATE('xbar', 'foobar');
-> 0

这个函数是多字节安全的。在 MySQL 3.23 中,这个函数是字母大小写敏感的,当在 MySQL 4.0 中时,如有任一参数是一个二进制字符串,它才是字母大小写敏感的。

LOCATE(substr,str,pos)
返回子串 substr 在字符串 str 中的第 pos 位置后第一次出现的位置。如果 substr 不在 str 中返回 0 :

mysql> SELECT LOCATE('bar', 'foobarbar',5);
-> 7

这个函数是多字节安全的。在 MySQL 3.23 中,这个函数是字母大小写敏感的,当在 MySQL 4.0 中时,如有任一参数是一个二进制字符串,它才是字母大小写敏感的。

INSTR(str,substr)
返回子串 substr 在字符串 str 中第一次出现的位置。这与有两个参数形式的 LOCATE() 相似,只是参数的位置被颠倒了:

mysql> SELECT INSTR('foobarbar', 'bar');
-> 4
mysql> SELECT INSTR('xbar', 'foobar');
-> 0

这个函数是多字节安全的。在 MySQL 3.23 中,这个函数是字母大小写敏感的,当在 MySQL 4.0 中时,如有任一参数是一个二进制字符串,它才是字母大小写敏感的。

LPAD(str,len,padstr)
用字符串 padstr 对 str 进行左边填补直至它的长度达到 len 个字符长度,然后返回 str。如果 str 的长度长于 len',那么它将被截除到 len 个字符。

mysql> SELECT LPAD('hi',4,'??');
-> '??hi'

RPAD(str,len,padstr)
用字符串 padstr 对 str 进行右边填补直至它的长度达到 len 个字符长度,然后返回 str。如果 str 的长度长于 len',那么它将被截除到 len 个字符。
mysql> SELECT RPAD('hi',5,'?');
-> 'hi???'

LEFT(str,len)
返回字符串 str 中最左边的 len 个字符:

mysql> SELECT LEFT('foobarbar', 5);
-> 'fooba'

这个函数是多字节安全的。

RIGHT(str,len)
返回字符串 str 中最右边的 len 个字符:

mysql> SELECT RIGHT('foobarbar', 4);
-> 'rbar'

这个函数是多字节安全的。phpma

SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
MID(str,pos,len)
从字符串 str 的 pos 位置起返回 len 个字符的子串。使用 FROM 的变体形式是 ANSI SQL92 的句法:

mysql> SELECT SUBSTRING('Quadratically',5,6);
-> 'ratica'

这个函数是多字节安全的。

SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
从字符串 str 的 pos 位置起返回子串:

mysql> SELECT SUBSTRING('Quadratically',5);
-> 'ratically'
mysql> SELECT SUBSTRING('foobarbar' FROM 4);
-> 'barbar'

这个函数是多字节安全的。

SUBSTRING_INDEX(str,delim,count)
返回字符串 str 中在第 count 个出现的分隔符 delim 之前的子串。如果 count 是一个正数,返回从最后的(从左边开始计数)分隔符到左边所有字符。如果 count 是负数,返回从最后的(从右边开始计数)分隔符到右边所有字符:

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
-> 'www.mysql'
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'

这个函数是多字节安全的。phpma

LTRIM(str)
返回移除了领头的空格字符后的 str:

mysql> SELECT LTRIM(' barbar');
-> 'barbar'

RTRIM(str)
返回移除了尾部的空格字符后的 str:

mysql> SELECT RTRIM('barbar ');
-> 'barbar'

这个函数是多字节安全的。

TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
移除字符串 str 中所有的 remstr 前缀或后缀,然后将其返回。如果没有任何 BOTH、LEADING 或 TRAILING 修饰符被给出,BOTH 被假定。如果 remstr 没有被指定,空格将被移除:

mysql> SELECT TRIM(' bar ');
-> 'bar'
mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
-> 'barxxx'
mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
-> 'bar'
mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
-> 'barx'

这个函数是多字节安全的。

SOUNDEX(str)
返回 str 的近音字。两个发音差不多的字符串应该有同样的近音字。一个标准的近音字为 4 个字符长,但是函数 SOUNDEX() 却返回一个任意长的字符串。你可以在结果上使用 SUBSTRING() 标准的近音字。提供的字符中所有的非数字字母的字符均被忽略。所有在 A-Z 范围之外的国际 alpha 字符被视为元音:

mysql> SELECT SOUNDEX('Hello');
-> 'H400'
mysql> SELECT SOUNDEX('Quadratically');
-> 'Q36324'

SPACE(N)
返回有 N 空格字符组成的字符串:phpma

mysql> SELECT SPACE(6);
-> ' '

REPLACE(str,from_str,to_str)
在字符串 str 中所有出现的字符串 from_str 均被 to_str替换,然后返回这个字符串:

mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
-> 'WwWwWw.mysql.com'

这个函数是多字节安全的。

REPEAT(str,count)
返回一个由重复了 count 次的字符串 str 组成的字符串。如果 count <= 0,返回一个空字符串。如果 str 或 count 是 NULL,返回值也为 NULL:

mysql> SELECT REPEAT('MySQL', 3);
-> 'MySQLMySQLMySQL'

REVERSE(str)
以颠倒的字符顺序返回字符串 str:

mysql> SELECT REVERSE('abc');
-> 'cba'

这个函数是多字节安全的。phpma

INSERT(str,pos,len,newstr)
在字符串 str 中,将从 pos 位置开始,len 个字符长的子串替换为字符串 newstr ,然后将结果返回:

mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
-> 'QuWhattic'

这个函数是多字节安全的。

ELT(N,str1,str2,str3,...)
如果 N = 1,返回 str1,如果N = 2,返回 str2,等等。如果 N 小于 1 或大于参数的数量,返回 NULL。ELT() FIELD() 反运算:

mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
-> 'ej'
mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
-> 'foo'

FIELD(str,str1,str2,str3,...)
返回 str 在列表 str1, str2, str3, ... 中的索引。如果 str 没有发现,返回 0。FIELD() 是 ELT() 的反运算:

mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
-> 2
mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
-> 0

FIND_IN_SET(str,strlist)
Returns a value 如果字符串 str 在由 N 个子串组成的列表 strlist 中,返回一个 1 到 N 的值。一个字符串列表是由通过字符 “,” 分隔的多个子串组成。如果第一个参数是一个常数字符串,并且第二个参数是一个 SET 列类型,FIND_IN_SET() 函数将被优化为使用位运算!如果 str 在不 strlist 中或者如果 strlist 是一个空串,返回值为 0。如果任何一个参数为 NULL,返回值也是 NULL。如果第一个参数包含一个 “,”,这个函数将完全不能工作:

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
-> 2

MAKE_SET(bits,str1,str2,...)
返回一个集合 (包含由字符 “,” 分隔的多个子串组成的一个字符串),它由在 bits 集合中有相应的比特位的字符串组成。str1 对应于比特位 0,str2 对应比特位 1,等等。在 str1, str2, ... 中的 NULL 串不允许被添加到结果中:

mysql> SELECT MAKE_SET(1,'a','b','c');
-> 'a'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
-> 'hello,world'
mysql> SELECT MAKE_SET(0,'a','b','c');
-> ''

EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
返回一个字符串,对于在 'bits' 中的每个比特字位,你将得到一个 'on' 字符,而如果比特字位是一个清零比特位(reset bit)你将得到一个 'off' 字符串。每个字符串均被“分隔符”(缺省为“,”)分隔,并且只有 'number_of_bits'(缺省为 64) 个 'bits' 被使用:

mysql> SELECT EXPORT_SET(5,'Y','N',',',4)
-> Y,N,Y,N

示例(译者注):

mysql> select EXPORT_SET(1,'1','0','',5);
-> 10000
# 最左边第一位为 2 的 0 次幂

mysql> select EXPORT_SET(2,'1','0','',5);
-> 01000
# 最左边第一位为 2 的 0 次幂,第二位为 2 的 1 次幂

mysql> select EXPORT_SET(4,'1','0','',5);
-> 00100
# 最左边第一位为 2 的 0 次幂,第二位为 2 的 1 次幂,第三位为 2 的 2 次幂

mysql> select EXPORT_SET(15,'1','0','',5);
-> 11110
# 最左边第一位为 2 的 1 次幂,第四位为 2 的 3 次幂

mysql> select EXPORT_SET(16,'1','0','',5);
-> 00001
# 最左边第一位为 2 的 1 次幂,第五位为 2 的 4 次幂


# 以上结果在 MySQL 4.0.12 中测试通过

示例结束(译者注)

LCASE(str)
LOWER(str)
依照当前字符集设置映射(缺省为 ISO-8859-1 Latin1),将字符串 str 中的所有字符改变为小写,然后返回该值:

mysql> SELECT LCASE('QUADRATICALLY');
-> 'quadratically'

这个函数是多字节安全的。

UCASE(str)
UPPER(str)
依照当前字符集设置映射(缺省为 ISO-8859-1 Latin1),将字符串 str 中的所有字符改变为大写,然后返回该值:

mysql> SELECT UCASE('Hej');
-> 'HEJ'

这个函数是多字节安全的。

LOAD_FILE(file_name)
读入文件,并将文件内容作为一个字符串返回。这个文件必须在服务器上,必须指定文件完整的路径名,并且你必须有 FILE 权限。文件必须完全可读,并且小于 max_allowed_packet。 如果该文件不存在,或因为上面的任一原因而不能被读出,函数返回 NULL:

mysql> UPDATE tbl_name
SET blob_column=LOAD_FILE("/tmp/picture")
WHERE id=1;

如果你没有使用 MySQL 3.23,你不得不在你的应用程序中读取文件,以文件的信息创建一个 INSERT 语句,来更新数据库。如果你使用 MySQL++ 库,下面有一个示例,详细请查看 http://www.mysql.com/documentation/mysql++/mysql++-examples.html。

QUOTE(str)
引用一个字符串,并返回一个结果,该结果可作为一个适当转义过的数据值在一个 SQL 语句中使用。字符串被单引号包围着返回,并且在该字符串中每个单引号(“'”)、反斜线符号(“/”)、ASCII NUL 和 Control-Z 出现的地方,在该字符之前均被加上了一个反斜线。如果参数是 NULL,那么结果值是一个没有单引号包围的单词 “NULL”。 QUOTE 函数在 MySQL 4.0.3 中被加入。

mysql> SELECT QUOTE("Don't");
-> 'Don't!'
mysql> SELECT QUOTE(NULL);
-> NULL

6.3.2.1 字符串比较函数

在必要的时候,MySQL 会自动地将数字转换到字符串,反之亦然:

mysql> SELECT 1+"1";
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'

如果你希望明确地将一个数字转换为字符串,将它参数传递到 CONCAT() 中。

如果将一个二进制字符串作为参数传递给一个字符串函数,结果返回也是一个二进制字符串。一个数字被转换到字符串,该字符串被视为是一个二进制字符串。这仅仅会影响结果。

通常,只要字符串比较中的任何一个表达式是区分大小写的,比较就会以字母大小写敏感方式执行。

expr LIKE pat [ESCAPE 'escape-char']
使用 SQL 的简单的正规表达式进行比较的模式匹配。返回 1 (TRUE) 或 0 (FALSE)。可以在模式中使用下面所示的两个通配符字符与 LIKE 配合:
字符 含义
% 匹配任意多个字符,甚至是零个字符
_ 严格地匹配一个字符

mysql> SELECT 'David!' LIKE 'David_';
-> 1
mysql> SELECT 'David!' LIKE '%D%v%';
-> 1

为了测试一个含有通配符的文字实例,可以用转义符加在能配符前。如果没有明确指定 ESCAPE 字符,假定为 “/”:
字符串 含义
/% 匹配一个 % 字符
/_ 匹配一个 _ 字符

mysql> SELECT 'David!' LIKE 'David/_';
-> 0
mysql> SELECT 'David_' LIKE 'David/_';
-> 1

为了指定一个不同的转义字符,可以使用 ESCAPE 子句:

mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
-> 1

下面两个语句表明,字符串比较是忽略大小写的,除非任一操作数是一个二进制字符串:

mysql> SELECT 'abc' LIKE 'ABC';
-> 1
mysql> SELECT 'abc' LIKE BINARY 'ABC';
-> 0

LIKE 允许用在一个数字表达式上。(这是 MySQL 对 ANSI SQL LIKE 的扩展。)

mysql> SELECT 10 LIKE '1%';
-> 1

注意:因为 MySQL 在字符串中使用的是 C 的转义句法(例如 “/n”),所以在 LIKE 字符串中使用的任何一个 “/” 必须被双写。例如,为了查找 “/n”,必须以 “//n” 形式指定它。为了查找 “/”,必须指定它为 “////” (反斜线被语法分析器剥离一次,另一次在模式匹配时完成,留下一条单独的反斜线被匹配)。

expr NOT LIKE pat [ESCAPE 'escape-char']
相同于 NOT (expr LIKE pat [ESCAPE 'escape-char'])。

expr SOUNDS LIKE expr
等同于 SOUNDEX(expr)=SOUNDEX(expr) (适用于 MySQL 4.1 或更新的版本)。

expr REGEXP pat
expr RLIKE pat
依照模式 pat 对字符串表达式 expr 执行一个模式比较。模式可以是一个扩展的正则表达式。查看章节 G MySQL 正则表达式。Returns 如果表达式 expr 匹配 pat,返回 1,否则返回 0。RLIKE 是 REGEXP 的同义词,它提供了与 mSQL 的兼容。注意:MySQL 在字符串中使用的是 C 的转义句法(例如 “/n”),所以在 REGEXP 字符串中使用的任何一个 “/” 必须被双写。在 MySQL 3.23.4 中,REGEXP 对于正常的(不是二进制)字符串是忽略大小写的:

mysql> SELECT 'Monty!' REGEXP 'm%y%%';
-> 0
mysql> SELECT 'Monty!' REGEXP '.*';
-> 1
mysql> SELECT 'new*/n*line' REGEXP 'new//*.//*line';
-> 1
mysql> SELECT "a" REGEXP "A", "a" REGEXP BINARY "A";
-> 1 0
mysql> SELECT "a" REGEXP "^[a-d]";
-> 1

当决定一个字符的类型时,REGEXP 和 RLIKE 使用当前使用的字符集(缺省为 ISO-8859-1 Latin1)。

expr NOT REGEXP pat
expr NOT RLIKE pat
等同于 NOT (expr REGEXP pat)。

STRCMP(expr1,expr2)
如果字符串是相同,STRCMP() 返回 0,如果第一个参数根据当前排序次序小于第二个参数,返回 -1,否则返回 1:

mysql> SELECT STRCMP('text', 'text2');
-> -1
mysql> SELECT STRCMP('text2', 'text');
-> 1
mysql> SELECT STRCMP('text', 'text');
-> 0

MATCH (col1,col2,...) AGAINST (expr)
MATCH (col1,col2,...) AGAINST (expr IN BOOLEAN MODE)
MATCH ... AGAINST() 用于全文搜索,返回在列 (col1,col2,...) 和查询 expr 之间文本的相关相似的尺度。相关性是一个正的浮点型数字。零相关性意味着不相似。MATCH ... AGAINST() 可用于 MySQL 3.23.23 或更新的版本中。IN BOOLEAN MODE 扩展在 MySQL 4.0.1 中被新加入。详细描述和使用范例,请查看 6.8 MySQL 全文搜索。
6.3.2.2 字母大小写敏感性

BINARY
BINARY 操作符将跟在它后面的字符串强制作为一个二进制字符串。这可以很容易地强制一个列的比较以字母大小写敏感方式进行,即使该列没有定义为 BINARY 或 BLOB?

mysql> SELECT "a" = "A";
-> 1
mysql> SELECT BINARY "a" = "A";
-> 0

BINARY string 是 CAST(string AS BINARY) 的缩写。查看章节 6.3.5 Cast 函数。BINARY 在 MySQL 3.23.0 中被加入。 注意,当将一个索引列强制为 BINARY 时,在某些语境中,MySQL 将不能有效地使用索引。

如果希望对一个 blob 进行忽略字母大小的比较时,你通常可以在比较前将它转换到大写:

SELECT 'A' LIKE UPPER(blob_col) FROM table_name;

我们计划不久推出在不同字符集间的转化,以使字符串比较有更好的伸缩性。
6.3.3 数字函数
6.3.3.1 算术运算

常用的算术操作符均是可用的。注意,如果两个参数均是整型,`-', `+' 和 `*' 以 BIGINT (64 位)精度运算并返回结果!如果一个参数是一个无符号的整数,另一个参数也是一个整数,结果也将是一个无符号整数。查看章节 6.3.5 Cast 函数。

+
加法:

mysql> SELECT 3+5;
-> 8

-
减法:

mysql> SELECT 3-5;
-> -2

*
乘法:

mysql> SELECT 3*5;
-> 15
mysql> SELECT 18014398509481984*18014398509481984.0;
-> 324518553658426726783156020576256.0
mysql> SELECT 18014398509481984*18014398509481984;
-> 0

最后一个表达式的结果是错误的,这是因为乘法结果超过了 64 位 BIGINT 计算范围。
/
除法:

mysql> SELECT 3/5;
-> 0.60

被 0 除将返回一个 NULL 结果:

mysql> SELECT 102/(1-1);
-> NULL

只有当在一个结果被转换到一个整数的语境中执行时,除法将会以 BIGINT 进行算术计算。

6.3.3.2 数学函数

所有的数学函数在发生错误的情况下,均返回 NULL。

-
一元减。 改变参数的符号:

mysql> SELECT - 2;
-> -2

注意,如果这个操作符被用于一个 BIGINT,返回值也是一个 BIGINT!这就意味着,应该避免在一个可能有值 -2^63 的整数上使用 - 操作符!

ABS(X)
返回 X 的绝对值:

mysql> SELECT ABS(2);
-> 2
mysql> SELECT ABS(-32);
-> 32

这个函数可安全地使用于 BIGINT 值。

SIGN(X)
以 -1、0 或 1 方式返回参数的符号,它取决于参数 X 是负数、0 或正数。

mysql> SELECT SIGN(-32);
-> -1
mysql> SELECT SIGN(0);
-> 0
mysql> SELECT SIGN(234);
-> 1

MOD(N,M)
%
取模 (就如 C 中的 % 操作符)。返回 N 被 M 除后的余数:

mysql> SELECT MOD(234, 10);
-> 4
mysql> SELECT 253 % 7;
-> 1
mysql> SELECT MOD(29,9);
-> 2
mysql> SELECT 29 MOD 9;
-> 2

这个函数可安全地使用于 BIGINT 值。最后一个示例可在 MySQL 4.1 中工作。

FLOOR(X)
返回不大于 X 的最大整数值:

mysql> SELECT FLOOR(1.23);
-> 1
mysql> SELECT FLOOR(-1.23);
-> -2

注意,返回值被转换为一个 BIGINT!

CEILING(X)
返回不小于 X 的最小整数:

mysql> SELECT CEILING(1.23);
-> 2
mysql> SELECT CEILING(-1.23);
-> -1

注意,返回值被转换为一个 BIGINT!

ROUND(X)
ROUND(X,D)
将参数 X 四舍五入到最近的整数,然后返回。两个参数的形式是将一个数字四舍五入到 D 个小数后返回。

mysql> SELECT ROUND(-1.23);
-> -1
mysql> SELECT ROUND(-1.58);
-> -2
mysql> SELECT ROUND(1.58);
-> 2
mysql> SELECT ROUND(1.298, 1);
-> 1.3
mysql> SELECT ROUND(1.298, 0);
-> 1

注意,当参数在两个整数之间时, ROUND() 的行为取决于 C 库的实现。某些取整到最近的偶数,总是向下取,总是向上取,也可能总是接近于零。如果你需要某种取整类型,应该使用一个明确定义的函数比如 TRUNCATE() 或 FLOOR() 代替。

DIV
整除。类似于 FLOOR(),但是它可安全地用于 BIGINT 值。

mysql> SELECT 5 DIV 2
-> 2

DIV 在 MySQL 4.1.0 中新加入。

EXP(X)
返回值 e (自然对数的底) 的 X 次方:

mysql> SELECT EXP(2);
-> 7.389056
mysql> SELECT EXP(-2);
-> 0.135335

LN(X)
返回 X 的自然对数:

mysql> SELECT LN(2);
-> 0.693147
mysql> SELECT LN(-2);
-> NULL

这个函数在 MySQL 4.0.3 被新加入。在 MySQL 中,它是 LOG(X) 的同义词。

LOG(X)
LOG(B,X)
如果以一个参数调用,它返回 X 的自然对数:

mysql> SELECT LOG(2);
-> 0.693147
mysql> SELECT LOG(-2);
-> NULL

如果以两个参数调用,这个函数返回 X 任意底 B 的对数:

mysql> SELECT LOG(2,65536);
-> 16.000000
mysql> SELECT LOG(1,100);
-> NULL

任意底选项在 MySQL 4.0.3 中被加入。LOG(B,X) 等价于 LOG(X)/LOG(B)。

LOG2(X)
返回 X 的以 2 为底的对数:

mysql> SELECT LOG2(65536);
-> 16.000000
mysql> SELECT LOG2(-100);
-> NULL

LOG2() 通常可以用于计数出一个数字需要多少个比特位用于存储它。这个函数在 MySQL 4.0.3 中被添加。在更早的版本中,可以使用 LOG(X)/LOG(2) 来代替它。

LOG10(X)
返回 X 以 10 为底的对数:

mysql> SELECT LOG10(2);
-> 0.301030
mysql> SELECT LOG10(100);
-> 2.000000
mysql> SELECT LOG10(-100);
-> NULL

POW(X,Y)
POWER(X,Y)
返回 X 的 Y 幂:

mysql> SELECT POW(2,2);
-> 4.000000
mysql> SELECT POW(2,-2);
-> 0.250000

SQRT(X)
返回 X 的非否平方根:

mysql> SELECT SQRT(4);
-> 2.000000
mysql> SELECT SQRT(20);
-> 4.472136

PI()
返回 PI 值(圆周率)。缺少显示 5 位小数,但是在 MySQL 内部,为 PI 使用全部的双精度。

mysql> SELECT PI();
-> 3.141593
mysql> SELECT PI()+0.000000000000000000;
-> 3.141592653589793116

COS(X)
返回 X 的余弦,在这里,X 以弧度给出:

mysql> SELECT COS(PI());
-> -1.000000

SIN(X)
返回 X 的正弦,在这里,X 以弧度给出:


mysql> SELECT SIN(PI());
-> 0.000000

TAN(X)
返回 X 的正切,在这里,X 以弧度给出:

mysql> SELECT TAN(PI()+1);
-> 1.557408

ACOS(X)
返回 X 的反余弦,更确切地说,返回余弦值为 X 的值。如果 X 不在 -1 到 1 之间的范围内,返回 NULL:

mysql> SELECT ACOS(1);
-> 0.000000
mysql> SELECT ACOS(1.0001);
-> NULL
mysql> SELECT ACOS(0);
-> 1.570796

ASIN(X)
返回 X 的反正弦,更确切地说,返回正弦值为 X 的值。如果 X 不在 -1 到 1 之间的范围内,返回 NULL:

mysql> SELECT ASIN(0.2);
-> 0.201358
mysql> SELECT ASIN('foo');
-> 0.000000

ATAN(X)
返回 X 的反正切, 更确切地说,返回正切值为 X 的值:

mysql> SELECT ATAN(2);
-> 1.107149
mysql> SELECT ATAN(-2);
-> -1.107149

ATAN(Y,X)
ATAN2(Y,X)
返回两个变量 X 和 Y 的反正切。它类似于计算 Y / X 的反正切,除了两个参数的符号用于决定结果的象限:

mysql> SELECT ATAN(-2,2);
-> -0.785398
mysql> SELECT ATAN2(PI(),0);
-> 1.570796

COT(X)
返回 X 的余切:

mysql> SELECT COT(12);
-> -1.57267341
mysql> SELECT COT(0);
-> NULL

RAND()
RAND(N)
返回一个范围在 0 到 1.0 之间的随机浮点值。如果一个整数参数 N 被指定,它被当做种子值使用(用于产生一个可重复的数值):

mysql> SELECT RAND();
-> 0.9233482386203
mysql> SELECT RAND(20);
-> 0.15888261251047
mysql> SELECT RAND(20);
-> 0.15888261251047
mysql> SELECT RAND();
-> 0.63553050033332
mysql> SELECT RAND();
-> 0.70100469486881

在一个 ORDER BY 子句中,不可以使用 RAND() 值使用一个列,因为 ORDER BY 将多次重复计算列。从 MySQL 3.23 开始,你可以使用:SELECT * FROM table_name ORDER BY RAND(),这有利于得到一个来自 SELECT * FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000 的集合中的随机样本。 注意,在一个 WHERE 子句中的 RAND() 将在每次 WHERE 执行时被重新计算。 RAND() 并不是预期完美的随机数发生器,但是可以代替做为产生特别的随机数一个快速的方法,这样便于在两个不同平台下的同一 MySQL 版本间移动。

LEAST(X,Y,...)
有两个或更多个参数,返回最小(最小值)的参数。参数使用下列规则进行比较:

* 如果返回值用于一个 INTEGER 语境,或所有的参数是整数值,它们作为整数比较。
* 如果返回值用于一个 REAL 语境,或所有的参数均是实数值,它们作为实数被比较。
* 如果任何一个参数是字母大小写敏感的,参数作为大小写敏感的字符串进行比较。
* 在其它情况下,参数做为忽略大小写的字符中进行比较:

mysql> SELECT LEAST(2,0);
-> 0
mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
-> 3.0
mysql> SELECT LEAST("B","A","C");
-> "A"

在早于 MySQL 3.22.5 的版本中,你可以使用 MIN() 代替 LEAST。

GREATEST(X,Y,...)
返回最大(最大值)参数。参数使用与 LEAST 一致的规则进行比较:

mysql> SELECT GREATEST(2,0);
-> 2
mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
-> 767.0
mysql> SELECT GREATEST("B","A","C");
-> "C"

在早于 MySQL 3.22.5 的版本中,可以使用 MAX() 代替 GREATEST。

DEGREES(X)
将参数 X 从弧度转换为角度,然后返回:

mysql> SELECT DEGREES(PI());
-> 180.000000

RADIANS(X)
将参数 X 从角度转换为弧度,然后返回:

mysql> SELECT RADIANS(90);
-> 1.570796

TRUNCATE(X,D)
将数值 X 截到 D 个小数,然后返回。如果 D 为 0,结果将不包含小数点和小数部分:

mysql> SELECT TRUNCATE(1.223,1);
-> 1.2
mysql> SELECT TRUNCATE(1.999,1);
-> 1.9
mysql> SELECT TRUNCATE(1.999,0);
-> 1
mysql> SELECT TRUNCATE(-1.999,1);
-> -1.9

从 MySQL 3.23.51 开始,所有数字被四舍五入到零。 如果 D 是负数,那么数字的整个部分被对准零位输出:

mysql> SELECT TRUNCATE(122,-2);
-> 100

注意, 十进值小数在计算机中通常不以精确数字存储,而是双精度型的值,你可能会被下列结果所愚弄:

mysql> SELECT TRUNCATE(10.28*100,0);
-> 1027

上面结果的发生是因为 10.28 实际上是以某些像 10.2799999999999999 的形式被存储的。

6.3.4 日期和时间函数

对于每个类型的值范围以及日期和时间值有效指定格式,请查看章节 6.2.2 Date 和 Time 类型。

这里是一个使用日期函数的例子。下面的查询选择所有 date_col 值在最后 30 天内的记录。

mysql> SELECT something FROM tbl_name
WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;

DAYOFWEEK(date)
返回 date 的星期索引(1 = Sunday, 2 = Monday, ... 7 = Saturday)。索引值符合 ODBC 的标准。

mysql> SELECT DAYOFWEEK('1998-02-03');
-> 3

WEEKDAY(date)
返回 date 的星期索引(0 = Monday, 1 = Tuesday, ... 6 = Sunday):

mysql> SELECT WEEKDAY('1998-02-03 22:23:00');
-> 1
mysql> SELECT WEEKDAY('1997-11-05');
-> 2

DAYOFMONTH(date)
返回 date 是一月中的第几天,范围为 1 到 31:

mysql> SELECT DAYOFMONTH('1998-02-03');
-> 3

DAYOFYEAR(date)
返回 date 是一年中的第几天,范围为 1 到 366:

mysql> SELECT DAYOFYEAR('1998-02-03');
-> 34

MONTH(date)
返回 date 中的月份,范围为 1 到 12:

mysql> SELECT MONTH('1998-02-03');
-> 2

DAYNAME(date)
返回 date 的星期名:

mysql> SELECT DAYNAME("1998-02-05");
-> 'Thursday'

MONTHNAME(date)
返回 date 的月份名:

mysql> SELECT MONTHNAME("1998-02-05");
-> 'February'

QUARTER(date)
返回 date 在一年中的季度,范围为 1 到 4:

mysql> SELECT QUARTER('98-04-01');
-> 2

WEEK(date)
WEEK(date,first)
对于星期日是一周中的第一天的场合,如果函数只有一个参数调用,返回 date 为一年的第几周,返回值范围为 0 到 53 (是的,可能有第 53 周的开始)。两个参数形式的 WEEK() 允许你指定一周是否以星期日或星期一开始,以及返回值为 0-53 还是 1-52。 这里的一个表显示第二个参数是如何工作的:

值 含义
0 一周以星期日开始,返回值范围为 0-53
1 一周以星期一开始,返回值范围为 0-53
2 一周以星期日开始,返回值范围为 1-53
3 一周以星期一开始,返回值范围为 1-53 (ISO 8601)

mysql> SELECT WEEK('1998-02-20');
-> 7
mysql> SELECT WEEK('1998-02-20',0);
-> 7
mysql> SELECT WEEK('1998-02-20',1);
-> 8
mysql> SELECT WEEK('1998-12-31',1);
-> 53

注意,在版本 4.0 中,WEEK(#,0) 被更改为匹配 USA 历法。 注意,如果一周是上一年的最后一周,当你没有使用 2 或 3 做为可选参数时,MySQL 将返回 0:

mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
-> 2000, 0
mysql> SELECT WEEK('2000-01-01',2);
-> 52

你可能会争辩说,当给定的日期值实际上是 1999 年的第 52 周的一部分时,MySQL 对 WEEK() 函数应该返回 52。我们决定返回 0 ,是因为我们希望该函数返回“在指定年份中是第几周”。当与其它的提取日期值中的月日值的函数结合使用时,这使得 WEEK() 函数的用法可靠。 如果你更希望能得到恰当的年-周值,那么你应该使用参数 2 或 3 做为可选参数,或者使用函数 YEARWEEK() :

mysql> SELECT YEARWEEK('2000-01-01');
-> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
-> 52

YEAR(date)
返回 date 的年份,范围为 1000 到 9999:

mysql> SELECT YEAR('98-02-03');
-> 1998

YEARWEEK(date)
YEARWEEK(date,first)
返回一个日期值是的哪一年的哪一周。第二个参数的形式与作用完全与 WEEK() 的第二个参数一致。注意,对于给定的日期参数是一年的第一周或最后一周的,返回的年份值可能与日期参数给出的年份不一致:

mysql> SELECT YEARWEEK('1987-01-01');
-> 198653

注意,对于可选参数 0 或 1,周值的返回值不同于 WEEK() 函数所返回值(0), WEEK() 根据给定的年语境返回周值。
HOUR(time)
返回 time 的小时值,范围为 0 到 23:

mysql> SELECT HOUR('10:05:03');
-> 10

MINUTE(time)
返回 time 的分钟值,范围为 0 到 59:

mysql> SELECT MINUTE('98-02-03 10:05:03');
-> 5

SECOND(time)
返回 time 的秒值,范围为 0 到 59:

mysql> SELECT SECOND('10:05:03');
-> 3

PERIOD_ADD(P,N)
增加 N 个月到时期 P(格式为 YYMM 或 YYYYMM)中。以 YYYYMM 格式返回值。 注意,期间参数 P 不是 一个日期值:

mysql> SELECT PERIOD_ADD(9801,2);
-> 199803

PERIOD_DIFF(P1,P2)
返回时期 P1 和 P2 之间的月数。P1 和 P2 应该以 YYMM 或 YYYYMM 指定。 注意,时期参数 P1 和 P2 不是 日期值:

mysql> SELECT PERIOD_DIFF(9802,199703);
-> 11

DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
这些函数执行日期的算术运算。ADDDATE() 和 SUBDATE() 分别是 DATE_ADD() 和 DATE_SUB() 的同义词。 在 MySQL 3.23 中,如果表达式的右边是一个日期值或一个日期时间型字段,你可以使用 + 和 - 代替 DATE_ADD() 和 DATE_SUB()(示例如下)。 参数 date 是一个 DATETIME 或 DATE 值,指定一个日期的开始。expr 是一个表达式,指定从开始日期上增加还是减去间隔值。expr 是一个字符串;它可以以一个 “-” 领头表示一个负的间隔值。type 是一个关键词,它标志着表达式以何格式被解释。 下表显示 type 和 expr 参数是如何关联的:
type 值 expr 期望的格式
SECOND SECONDS
MINUTE MINUTES
HOUR HOURS
DAY DAYS
MONTH MONTHS
YEAR YEARS
MINUTE_SECOND "MINUTES:SECONDS"
HOUR_MINUTE "HOURS:MINUTES"
DAY_HOUR "DAYS HOURS"
YEAR_MONTH "YEARS-MONTHS"
HOUR_SECOND "HOURS:MINUTES:SECONDS"
DAY_MINUTE "DAYS HOURS:MINUTES"
DAY_SECOND "DAYS HOURS:MINUTES:SECONDS"
在 expr 的格式中,MySQL 允许任何字符作为定界符。表中所显示的是建议的定界字符。如果 date 参数是一个 DATE 值,并且计算的间隔仅仅有 YEAR、MONTH 和 DAY 部分(没有时间部分),那么返回值也是一个 DATE 值。否则返回值是一个 DATETIME 值:

mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
-> 1998-01-01 00:00:00
mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
-> 1998-01-01
mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
-> 1997-12-31 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
-> INTERVAL 1 SECOND);
-> 1998-01-01 00:00:00
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
-> INTERVAL 1 DAY);
-> 1998-01-01 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
-> INTERVAL "1:1" MINUTE_SECOND);
-> 1998-01-01 00:01:00
mysql> SELECT DATE_SUB("1998-01-01 00:00:00",
-> INTERVAL "1 1:1:1" DAY_SECOND);
-> 1997-12-30 22:58:59
mysql> SELECT DATE_ADD("1998-01-01 00:00:00",
-> INTERVAL "-1 10" DAY_HOUR);
-> 1997-12-30 14:00:00
mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
-> 1997-12-02

如果你指定了一个太短的间隔值(没有包括 type 关键词所期望的所有间隔部分),MySQL 假设你遗漏了间隔值的最左边部分。例如,如果指定一个 type 为 DAY_SECOND,那么 expr 值被期望包含天、小时、分钟和秒部分。如果你象 "1:10" 样指定一个值,MySQL 假设天和小时部分被遗漏了,指定的值代表分钟和秒。换句话说,"1:10" DAY_SECOND 被解释为等价于 "1:10" MINUTE_SECOND。这类似于 MySQL 解释 TIME 值为经过的时间而不是一天的时刻。 注意,如果依着包含一个时间部分的间隔增加或减少一个日期值,该日期值将被自动地转换到一个日期时间值:

mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 DAY);
-> 1999-01-02
mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 HOUR);
-> 1999-01-01 01:00:00

如果你使用了确定不正确的日期,返回结果将是 NULL。如果你增加 MONTH、YEAR_MONTH 或 YEAR,并且结果日期的天比新月份的最大天数还大,那么它将被调整到新月份的最大天数:

mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH);
-> 1998-02-28

注意,上面的例子中,单词 INTERVAL 和关键词 type 是不区分字母大小写的。

EXTRACT(type FROM date)
EXTRACT() 函数使用与 DATE_ADD() 或 DATE_SUB() 一致的间隔类型,但是它用于指定从日期中提取的部分,而不是进行日期算术运算。

 

mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
-> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
-> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
-> 20102

TO_DAYS(date)
给出一个日期 date,返回一个天数(从 0 年开始的天数):

mysql> SELECT TO_DAYS(950501);
-> 728779
mysql> SELECT TO_DAYS('1997-10-07');
-> 729669

TO_DAYS() 无意于使用先于格里高里历法(即现行的阳历)(1582)出现的值,因为它不考虑当历法改变时所遗失的天数。

FROM_DAYS(N)
给出一个天数 N,返回一个 DATE 值:

mysql> SELECT FROM_DAYS(729669);
-> '1997-10-07'

FROM_DAYS() 无意于使用先于格里高里历法(1582)出现的值,因为它不考虑当历法改变时所遗失的天数。

DATE_FORMAT(date,format)
依照 format 字符串格式化 date 值。下面的修饰符可被用于 format 字符串中:
修饰符 含义
%M 月的名字 (January..December)
%W 星期的名字 (Sunday..Saturday)
%D 有英文后缀的某月的第几天 (0th, 1st, 2nd, 3rd, etc.)
%Y 年份,数字的,4 位
%y 年份,数字的,2 位
%X 周值的年份,星期日是一个星期的第一天,数字的,4 位,与 '%V' 一同使用
%x 周值的年份,星期一是一个星期的第一天,数字的,4 位,与 '%v' 一同使用
%a 缩写的星期名 (Sun..Sat)
%d 月份中的天数,数字的 (00..31)
%e 月份中的天数,数字的 (0..31)
%m 月,数字的 (00..12)
%c 月,数字的 (0..12)
%b 缩写的月份名 (Jan..Dec)
%j 一年中的天数 (001..366)
%H 小时 (00..23)
%k 小时 (0..23)
%h 小时 (01..12)
%I 小时 (01..12)
%l 小时 (1..12)
%i 分钟,数字的 (00..59)
%r 时间,12 小时 (hh:mm:ss [AP]M)
%T 时间,24 小时 (hh:mm:ss)
%S 秒 (00..59)
%s 秒 (00..59)
%p AM 或 PM
%w 一周中的天数 (0=Sunday..6=Saturday)
%U 星期 (00..53),星期日是一个星期的第一天
%u 星期 (00..53),星期一是一个星期的第一天
%V 星期 (01..53),星期日是一个星期的第一天。与 '%X' 一起使用
%v 星期 (01..53),星期一是一个星期的第一天。与 '%x' 一起使用
%% 一个字母 “%”
所有其它的字符不经过解释,直接复制到结果中:

mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
-> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
-> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
'%D %y %a %d %m %b %j');
-> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
'%H %k %I %r %T %S %w');
-> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
-> '1998 52'

在 MySQL 3.23 中,在格式修饰符前需要字符 `%'。在更早的 MySQL 版本中,`%' 是可选的。 月份与天修饰符的范围从零开始的原因是,在 MySQL 3.23 中,它允许存储不完善的日期值(例如 '2004-00-00')。

TIME_FORMAT(time,format)
它的使用方法与上面的 DATE_FORMAT() 函数相似,但是 format 字符串只包含处理小时、分和秒的那些格式修饰符。使用其它的修饰符会产生一个 NULL 值或 0。

CURDATE()
CURRENT_DATE
以 'YYYY-MM-DD' 或 YYYYMMDD 格式返回当前的日期值,返回的格式取决于该函数是用于字符串还是数字语境中:

mysql> SELECT CURDATE();
-> '1997-12-15'
mysql> SELECT CURDATE() + 0;
-> 19971215

CURTIME()
CURRENT_TIME
以 'HH:MM:SS' 或 HHMMSS 格式返回当前的时间值,返回的格式取决于该函数是用于字符串还是数字语境中:

mysql> SELECT CURTIME();
-> '23:50:26'
mysql> SELECT CURTIME() + 0;
-> 235026

NOW()
SYSDATE()
CURRENT_TIMESTAMP
以 'YYYY-MM-DD HH:MM:SS' 或 YYYYMMDDHHMMSS 格式返回当前的日期时间值,返回的格式取决于该函数是用于字符串还是数字语境中:

mysql> SELECT NOW();
-> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
-> 19971215235026

注意,函数 NOW() 在每个查询中只计算一次,也就是在查询开始执行时。这就是说,如果在一个单独的查询中多次引用了 NOW(),它只会给出值都是一个相同的时间。

UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
如果调用时没有参数,以无符号的整数形式返回一个 Unix 时间戳(从 '1970-01-01 00:00:00' GMT 开始的秒数)。如果以一个参数 date 调用 UNIX_TIMESTAMP(),它将返回该参数值从 '1970-01-01 00:00:00' GMT 开始经过的秒数值。date 可以是一个 DATE 字符串,一个 DATETIME 字符串,一个 TIMESTAMP,或者以一个 YYMMDD 或 YYYYMMDD 显示的本地时间:

mysql> SELECT UNIX_TIMESTAMP();
-> 882226357
mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
-> 875996580

当 UNIX_TIMESTAMP 被用于一个 TIMESTAMP 列时,函数直接返回一个内部的时间戳值,而不进行一个隐含地 “string-to-unix-timestamp” 转换。如果你传递一个超出范围的日期参数给 UNIX_TIMESTAMP() ,它将返回 0,但是请注意,MySQL 对其仅仅进行基本的检验(年范围 1970-2037,月份 01-12,日期 01-31)。 如果你希望减去 UNIX_TIMESTAMP() 列,你应该需要将结果强制转换为一有符号整数。查看章节 6.3.5 Cast 函数。

FROM_UNIXTIME(unix_timestamp [,format])
以 'YYYY-MM-DD HH:MM:SS' 或 YYYYMMDDHHMMSS 格式返回一个 unix_timestamp 参数值,返回值的形式取决于该函数使用于字符串还是数字语境。 如果 format 给出,返回值依 format 字符串被格式。format 可以包含与 DATE_FORMAT() 函数同样的修饰符。

mysql> SELECT FROM_UNIXTIME(875996580);
-> '1997-10-04 22:23:00'
mysql> SELECT FROM_UNIXTIME(875996580) + 0;
-> 19971004222300
mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),
'%Y %D %M %h:%i:%s %x');
-> '1997 23rd December 03:43:30 1997'

SEC_TO_TIME(seconds)
以 'HH:MM:SS' 或 HHMMSS 格式返回参数 seconds 被转换到时分秒后的值,返回值的形式取决于该函数使用于字符串还是数字语境:

mysql> SELECT SEC_TO_TIME(2378);
-> '00:39:38'
mysql> SELECT SEC_TO_TIME(2378) + 0;
-> 3938

TIME_TO_SEC(time)
将参数 time 转换为秒数后返回:

mysql> SELECT TIME_TO_SEC('22:23:00');
-> 80580
mysql> SELECT TIME_TO_SEC('00:39:38');
-> 2378

6.3.5 Cast 函数

CAST 函数的句法如下:

CAST(expression AS type)


CONVERT(expression,type)

type 可以是下面的任一个:

* BINARY
* CHAR (4.0.6 中新加入)
* DATE
* DATETIME
* SIGNED {INTEGER}
* TIME
* UNSIGNED {INTEGER}

CAST() 是 ANSI SQL99 的句法,CONVERT() 是 ODBC 的句法。

CAST 函数主要用于以特殊的 CREATE ... SELECT 形式建立一个列时:

CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);

CAST(string AS BINARY 与 BINARY string 是相同的。 CAST(expr AS CHAR 表示一个使用当前默认字符集的字符串。

为了将一个字符串转换成一个数字值,通常不需要做任何事情;只要将字符串值当做一个数字即可:

mysql> SELECT 1+'1';
-> 2

如果在一个字符串语境中使用一个数字,该数字会被自动地转换为一个 BINARY 字符串。

mysql> SELECT CONCAT("hello you ",2);
-> "hello you 2"

MySQL 支持两方是有符号的和无符号的 64 位值的算术运算。如果你使用一个数字操作符(比如 +),并且其中的一个操作数是 unsigned integer,那么结果将是无符号的。为了不考虑这些问题,你可以使用 SIGNED 和 UNSIGNED CAST 操作符来,它会分别地强制运算到一个有符号的或一个无符号的 64 位整数。

mysql> SELECT CAST(1-2 AS UNSIGNED)
-> 18446744073709551615
mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
-> -1

注意,如果任一个操作数是一个浮点值(在这种语境下,DECIMAL() 被当作是一个浮点数值),结果也将是一个浮点数值,并且结果不受上面的规则影响。

mysql> SELECT CAST(1 AS UNSIGNED) -2.0
-> -1.0

如果在一个算术运算中使用一个字符串,它将被转换为一个浮点数字。

函数 CAST() 和 CONVERT() 在 MySQL 4.0.2 中被加入。

为了完全支持 BIGINT,在 MySQL 4.0 中对无符号值的处理发生了改变。如果希望你的代码在 MySQL 4.0 和 3.23 中均能够正常运行(在这种情况下,你或许不能够使用 CAST 函数),当进行两个无符号整数列的减法时,你可以使用下面的技巧得到一个有符号的结果:

SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);

这个做法是在进行减法之前,先将无符号列转换为一个浮点数。

如果你将旧的 MySQL 应用程序移植到 MySQL 4.0 时,在 UNSIGNED 列上出现了问题,你可以在启动 mysqld 时使用 --sql-mode=NO_UNSIGNED_SUBTRACTION 选项。注意,只要你使用了这个选项,你将不能直接地使用 UNSIGNED BIGINT 列类型。
6.3.6 其它函数
6.3.6.1 位函数

MySQL 使用 BIGINT (64 位) 算法进行位运算,因而这些操作符有一个 64 位的最大范围。

|
位或

mysql> SELECT 29 | 15;
-> 31

返回值是一个 64 位的无符号整数。

&
位与

mysql> SELECT 29 & 15;
-> 13

返回值是一个 64 位的无符号整数。

^
位异或

mysql> SELECT 1 ^ 1;
-> 0
mysql> SELECT 1 ^ 0;
-> 1
mysql> SELECT 11 ^ 3;
-> 8

返回值是一个 64 位的无符号整数。 XOR 在 MySQL 4.0.2 中被加入。

<<
左移一个长长的数字(BIGINT):

mysql> SELECT 1 << 2;
-> 4

返回值是一个 64 位的无符号整数。

>>
右移一个长长的数字(BIGINT):

mysql> SELECT 4 >> 2;
-> 1

返回值是一个 64 位的无符号整数。

~
置反所有位:

mysql> SELECT 5 & ~1;
-> 4

返回值是一个 64 位的无符号整数。

BIT_COUNT(N)
返回在参数 N 中嵌入的比特位数量:

mysql> SELECT BIT_COUNT(29);
-> 4

6.3.6.2 辅助功能函数

DATABASE()
返回当前数据库名:

mysql> SELECT DATABASE();
-> 'test'

如果没有当前数据库,DATABASE() 返回一个空字符串。
USER()
SYSTEM_USER()
SESSION_USER()
返回当前 MySQL 用户名:

mysql> SELECT USER();
-> 'davida@localhost'

在 MySQL 3.22.11 或更新的版本中,返回值包含用户名和客户机的主机名。你可以象下面所示的仅取出用户名部分(无论值是否包含一个主机名部分,它均能正常工作):

mysql> SELECT SUBSTRING_INDEX(USER(),"@",1);
-> 'davida'

CURRENT_USER()
返回当前会话被验证匹配的用户名:

mysql> SELECT USER();
-> 'davida@localhost'
mysql> SELECT * FROM mysql.user;
-> ERROR 1044: Access denied for user: '@localhost' to database 'mysql'
mysql> SELECT CURRENT_USER();
-> '@localhost'

PASSWORD(str)
OLD_PASSWORD(str)
从纯文本口令 str 计算一个口令字符串。这个函数用于对存储到授权表 user 的Password 列中的 MySQL 口令进行加密。

mysql> SELECT PASSWORD('badpwd');
-> '7f84554057dd964b'

PASSWORD() 加密是不可逆的。 PASSWORD() 不以与 Unix 口令加密相同的方式进行口令加密。参见 ENCRYPT()。 注意, PASSWORD() 函数是用于在 MySQL 服务中验证系统的,你不应该 在你的应用程序中使用它。你可以使用 MD5() 或 SHA1() 代替使用它。同样查看 RFC-2195 可获得有关应用程序的口令处理与安全验证的更多信息。
ENCRYPT(str[,salt])
Encrypt使用 Unix crypt() 系统调用加密 str 。参数 salt 应该是一个有两个字符的字符串,(在 MySQL 3.22.16 中,salt 可以超过两个字符。):

mysql> SELECT ENCRYPT("hello");
-> 'VxuFAJXVARROc'

如果 crypt() 在你的系统上不可用,ENCRYPT() 总是返回 NULL。 ENCRYPT() 只保留 str 中前 8 个字符,而忽略其它所有的,至少在某些系统上是这样的。这取决于底层 crypt() 系统调用的行为。

ENCODE(str,pass_str)
使用 pass_str 做为密钥加密 str。使用 DECODE() 解密结果。结果是一个与 string 一样长的二进制字符。如果希望将它保存到一个列中,请使用 BLOB 列类型。

DECODE(crypt_str,pass_str)
使用 pass_str 作为密钥解密加密后的字符串 crypt_str。crypt_str 应该是一个由 ENCODE() 返回的字符串。

MD5(string)
计算一个字符串的 MD5 128 位校验和。值作为一个 32 位的十六进制数字返回,例如,被用于一个哈希(hash)键:

mysql> SELECT MD5("testing");
-> 'ae2b1fca515949e5d54fb22b8ed95575'

这是 "RSA 数据安全公司的 MD5 消息-摘要算法"。

SHA1(string)
SHA(string)
计算一个字符串的 SHA1 160 位校验和(在 RFC 3174 (Secure Hash Algorithm) 中被描述)。返回值是一个 40 位的十六进制数字,或在输入参数为 NULL 的情况下,返回值为 NULL。一个使用这个函数的可能就是用于一个哈希键。你也可以使用它作为存储密码时的密码安全函数。


mysql> SELECT SHA1("abc");
-> 'a9993e364706816aba3e25717850c26c9cd0d89d'

SHA1() 在MySQL 4.0.2 中被加入,并可被当做比 MD5() 加密更安全的等价物。SHA() 是 SHA1() 的同义词。

AES_ENCRYPT(string,key_string)
AES_DECRYPT(string,key_string)
这些函数允许使用官方的 AES(Advanced Encryption Standardadvanced 先进的密码技术标准) 算法加密/解密数据。加密时使用 128 位长的密钥,但是你可以通过修改源码将其扩展到 256 位。我们选择 128 位是因为它更快一点并且已足够安全了。输入的参数可以是任意长度的。如果任何一个参数是 NULL,这个函数返回值也将是 NULL。 因为 AES 是一个块级的算法,加密不同长度的字符串时会对其进行填充,因而结果字符串的长度也可以通过 16*(trunc(string_length/16)+1) 计算出。 如果 AES_DECRYPT() 发现数据无效或错误的填料,它将返回 NULL。可是,如果输入的数据或密钥是无效的,函数仍然可能返回一个非 NULL 值 (可能是无用的信息)。 通过修改你的 SQL 语句,你可以使用 AES 函数以一个加密的形式存储数据:

INSERT INTO t VALUES (1,AES_ENCRYPT("text","password"));

尽量避免在一个连接上的每个查询中传递密钥,这样可以得到更高的安全性,上述方式可以通过连接时在服务器端存储密钥来完成:

SELECT @password:="my password";
INSERT INTO t VALUES (1,AES_ENCRYPT("text",@password));

AES_ENCRYPT() 和 AES_DECRYPT() 在 MySQL 4.0.2 中被加入,可以被考虑为当前 MySQL 中可用的加解密函数中最密码安全的。

DES_ENCRYPT(string_to_encrypt [, (key_number | key_string) ] )
使用 Triple-DES 算法以给定的密钥对字符串加密。 注意,只有配置了 MySQL 对 SSL 的支持,这个函数才能正常工作。查看章节 4.3.9 使用安全地连接。 编码密钥以下列各项方法选择:
参数 含义
只有一个参数 des-key-file 中的第一个密钥被使用。
key number des-key-file 中给定的密钥 (0-9) 被使用。
string 给定的 key_string 将被用于加密 string_to_encrypt。
返回字符串是一个二进制字符串,并且第一个字符是 CHAR(128 | key_number)。 128 被加入是为了更加容易地识别一个加密密钥。如果你使用一个字符串密钥,key_number 将是 127。 当发生错误时,这个函数返回 NULL。 返回字符串的长度将为:new_length= org_length + (8-(org_length % 8))+1。 des-key-file 的格式如下:

key_number des_key_string
key_number des_key_string

每个 key_number 必须是一个在 0 到 9 范围之内的数字。文件中的行可以是任何次序的。des_key_string 是用于加密消息的字符串。在数字与密钥之间至少要有一个空格。如果你没在 DES_ENCRYPT() 指定任何密钥参数,那么文件中的第一个密钥将被缺省使用。 以 FLUSH DES_KEY_FILE 命令,你可以告诉 MySQL 从密钥文件中读取新的密钥值。这个操作需要你有 Reload_priv 权限。 有一套默认密钥的一个好处就是,它给应用程序一个检查存在的加密列值的方法,而不需要给最终用户解密这些值的权限。

mysql> SELECT customer_address FROM customer_table WHERE
crypted_credit_card = DES_ENCRYPT("credit_card_number");

DES_DECRYPT(string_to_decrypt [, key_string])
解密 DES_ENCRYPT() 加密后的字符串。 注意,只有配置了 MySQL 对 SSL 的支持,这个函数才能正常工作。查看章节 4.3.9 使用安全地连接。 如果 key_string 参数没有给出,DES_DECRYPT() 检查加密字符串的第一个字节,以确定用于加密原始字符串的 DES 密钥数字,然后从 des-key-file 读取密钥用于解密消息。为了能这样工作,该用户必须有 SUPER 权限。 如果将一个 key_string 参数传递给该函数,这个字符串将被作为解密消息的密钥。 如果 string_to_decrypt 看上去不像是一个加密字符串,MySQL 将返回给定的 string_to_decrypt。 当发生错误时,该函数返回 NULL。

LAST_INSERT_ID([expr])
返回被插入到一个 AUTO_INCREMENT 列中的最后一个自动产生的值。查看章节 8.1.3.130 mysql_insert_id()。

mysql> SELECT LAST_INSERT_ID();
-> 195

最后产生的 ID 是以每个连接为基础在服务器端被维护的。它不可能被其它的客户端连接改变。如果你以一个非特殊值(即一个非 NULL 和非 0 的值)更新其它的 AUTO_INCREMENT,它甚至也不会改变。 如果你在同一时间内以一个插入语句插入了许多记录行,LAST_INSERT_ID() 将返回第一个被插入行的值。这样做的原因是因为,这可能列容易地在其它服务器上再现同一条 INSERT 语句。 如果 expr 被作为一个参数传递给 LAST_INSERT_ID(),那么函数将返回这个参数的值,并且被设置为 LAST_INSERT_ID() 返回的下一个值。这可被用于模拟一个序列: 首先创建一个表:

mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);

然后这个表可以被用来以下面的方式产生序列值:

mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);

你也可以不调用 LAST_INSERT_ID() 产生序列,但是以这种方式使用这个函数的作用就是,ID 值是在服务器端叙谈最后的自动产生值被维护的(是多用户安全的)。你可以检索这的新的 ID 值,就好像读取 MySQL 中任何正常的 AUTO_INCREMENT 值一样。举例来说,LAST_INSERT_ID()(无任何参数) 将返回一个新的 ID。C API 函数 mysql_insert_id() 也可以用来得到这个值。 注意,由于 mysql_insert_id() 仅仅只能用于在 INSERT 和 UPDATE 语句的更新之后,所以在执行了其它的 SQL 语句(比如 SELECT 或 SET)之后,你不能够使用 C API 函数检索到 LAST_INSERT_ID(expr) 的值。

FORMAT(X,D)
将数字 X 格式化为一个 '#,###,###.##' 的形式,四舍五入到 D 位小数。如果 D 为 0,返回的结果将没有小数点和小数部分:

mysql> SELECT FORMAT(12332.123456, 4);
-> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4);
-> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0);
-> '12,332'

VERSION()
以一个字符串形式返回 MySQL 服务器的版本:

mysql> SELECT VERSION();
-> '3.23.13-log'

注意,如果你的版本以 -log 结果,那就意味着日志是被设为可用的。

CONNECTION_ID()
返回当前连接的连接 ID(thread_id)。每个连接均有一个自己唯一的 id:

mysql> SELECT CONNECTION_ID();
-> 1

GET_LOCK(str,timeout)
尝试获得一个由字符串 str 给定名字的锁定与一个 timeout 秒的超时。如果锁定被获得成功,返回 1,如果尝试超时,返回 0,或者一个错误发生(比如内存溢出或线程被 mysqladmin kill 杀死),返回NULL。当你执行 RELEASE_LOCK()、执行一个新的 GET_LOCK(),或线程终止时,一个锁定被释放。这个函数可以被用于执行应用程序锁定或模拟记录锁定。它会阻塞其它的客户端用同样的名字的锁定请求;遵从一个给定锁定字符串名的客户端可以使用这个字符串来执行子协作建议的锁定:

mysql> SELECT GET_LOCK("lock1",10);
-> 1

mysql> SELECT IS_FREE_LOCK("lock2");
-> 1
mysql> SELECT GET_LOCK("lock2",10);
-> 1
mysql> SELECT RELEASE_LOCK("lock2");
-> 1
mysql> SELECT RELEASE_LOCK("lock1");
-> NULL

注意,第二个 RELEASE_LOCK() 调用返回 NULL 是因为 "lock1" 锁定被第二个 GET_LOCK() 调用自动地释放了。

RELEASE_LOCK(str)
释放由字符串 str 命名的通过 GET_LOCK() 获得的锁定。如果锁定被释放,返回 1;如果锁定并没有被当前线程锁定(在这种情况下,锁定不会被释放),返回 0;如果命名的锁定不存在,返回 NULL。如果锁定从来就没有通过调用一个 GET_LOCK() 获得,或已被释放了,那么该锁定将不存在。 DO 语句通常与 RELEASE_LOCK() 一起使用。查看章节 6.4.10 DO 句法。

IS_FREE_LOCK(str)
检查以 str 命名的锁定是否可以自由使用(也就是说,还未锁定)。如果锁定被释放了(没有一个人使用这个锁定),返回 1;如果这个锁定处于使用中,返回 0;如果发生一个错(例如错误的参数),返回 NULL。

BENCHMARK(count,expr)
BENCHMARK() 函数用于将表达式 expr 重复运行 count 次。它可以被用于计时 MySQL 处理表达式有多快。结果通常为 0。在 mysql 客户端有意使用它时,它将返回查询执行所需的时间:

mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE("hello","goodbye")) |
+----------------------------------------------+
| 0 |
+----------------------------------------------+
1 row in set (4.74 sec)

报告的时间是客户端经过的时间,不是服务器端的 CPU 时间。执行 BENCHMARK() 多次可能是明智的,并注意服务器的负载来解释结果。

INET_NTOA(expr)
给定一个数字的网络地址 (4 或 8 字节),以一个字符串的形式返回点组表示的地址:

mysql> SELECT INET_NTOA(3520061480);
-> "209.207.224.40"

INET_ATON(expr)
以字符串的形式给定一个点组表示的网络地址,返回一个地址的数字值表示的整数。地址可以是 4 或 8 个字节的地址:

mysql> SELECT INET_ATON("209.207.224.40");
-> 3520061480

产生的数字通常是以网络地址字节的顺序;例如,上面的数字是以 209*256^3 + 207*256^2 + 224*256 +40 被计算出来的。

MASTER_POS_WAIT(log_name, log_pos)
阻塞,只到从服务器到达(也就是说,已读取并应用了所有更新,一直到)主服务器上的日志中指定的位置。如果主服务器上的信息没有初始化,或如果参数错误,返回 NULL。如果从服务器没有运行,将阻塞并造作,只到它启动并到达或超过指定的位置。如果从服务器已超过指定的位置,立即返回。 如果 timeout (在 4.0.10 中新加入) 被指定,当等待 timeout 秒经过后,将放弃。timeout 必须大于 0;一个零或一个负值 timeout 意味着超时。返回值是到达日志指定位置所必须等待的日志事件的数量,或者在出错的情况下为 NULL,或者超过超时时间返回 -1。 这个命令有益于控制主从服务器的同步,但是最初是为了复制测试的方便而写的。

FOUND_ROWS()
返回最后一个 SELECT SQL_CALC_FOUND_ROWS ... 命令如果没有以 LIMIT 进行限制结果时将返回记录行数。

mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();

第二个 SELECT 将返回一个数字,它指示前一个没有被 LIMIT 子句限制的 SELECT 将返回多少行记录。注意,如果你使用 SELECT SQL_CALC_FOUND_ROWS ...,MySQL 不得不计算所有的记录行到结果集中。然而,这与你不使用 LIMIT 相比是更快一点的,因为结果集不需要发送到客户端。 SQL_CALC_FOUND_ROWS 从 MySQL 4.0.0 开始可以被使用。

6.3.7 用于 GROUP BY 子句的函数

如果在一个没有包含 GROUP BY 子句的一个语句中使用聚合函数,它将等价于将所有的记录行分为一组。

COUNT(expr)
返回由一个 SELECT 语句检索出来的记录行中非 NULL 值的记录总数目:

mysql> SELECT student.student_name,COUNT(*)
-> FROM student,course
-> WHERE student.student_id=course.student_id
-> GROUP BY student_name;


COUNT(*) 在它返回检索出的记录行的数目上稍微有点不同,它不管记录行中是否包括 NULL 值。 如果 SELECT 语句从一个表中进行检索,没有检索其它的列,并且没有 WHERE 子句,那么 COUNT(*) 将被优化以便更快地返回值。示例如下:

mysql> SELECT COUNT(*) FROM student;

COUNT(DISTINCT expr,[expr...])
返回一个互不相同的非 NULL 的值的总数目:

mysql> SELECT COUNT(DISTINCT results) FROM student;

在 MySQL 中,通过给出一个表达式列表,可以得到不包含 NULL 的不同的表达式组合的数目。在 ANSI SQL 中,你可能不得不在 COUNT(DISTINCT ...) 中拼接所有的表达式。

AVG(expr)
返回 expr 的平均值:

mysql> SELECT student_name, AVG(test_score)
-> FROM student
-> GROUP BY student_name;

MIN(expr)
MAX(expr)
返回 expr 的最小或最大值。MIN

 

 


3, 查询结果进行排序
一般说来,如果创建了一个数据表并向里面插入了一些记录,当发出一条select * from name命令的时候,数据记录在查询结果中的先后顺序通常与它们被插入时的先后顺序一样.这当然符合我们的思维习惯.但这只是一种"想当然"的假设而已,事实上,但记录被删除时,数据库中会产生一些空的区域,MYSQL会用新的记录来填补这些区域,也就是说,这个时候本假设就不正确了.因此我们必须记住一点,从服务器返回的记录行的先后顺序是没有任何保证的!如果想要按照一定的顺序,就必须使用order by 子句来设置这个顺序.
select last_name,first_name,birth,state from president
order by last_name; //让总统们的名字按字母顺序排列
还可以设置排列的升序降序
select last_name,first_name from president
order by state DESC,last_name ASC;
//先按照出生地的降序排列,同出生地的按照姓氏的升序排列
注意:如果结果中含有NULL 值,默认情况下他们总是出现在查询结果的开头。

4, 限制查询结果中数据行个数
这个简单,只要用limit 子句就可以了,看两个例子:
select last_name,first_name,birth,state from president
order by birth limit 5; //只想看前5个
order by birth limit 10,5; //返回从第11个记录开始的5个记录(跳过了10个)
小技巧:从president表中随机找出一个总统来玩:
select last_name,first_name,birth,state from president
order by rand() limit 1; //这是用了表达式求值的方法,在哪里都管用

5, 对输出列进行求值和命名
为了提高效率,MYSQL还可以把表达式的计算结果当作输出列的值。表达式可以很简单,也可以很复杂。例如:下面这个查询有两个输出列,前一个输出列对应一个非常简单的表达式(一个常数),而后一个输出列则对应着一个使用了多个算术运算符和两个函数调用的复杂表达式。
Select 17,format(sqrt(3*3 4*4),0))
输出:17 5
再看这个命令:把两个输出列合并成一个
select concat(first_namem,’ ‘,last_name),concat(city,’,’,state) from president;
如果合并之后输出列的标题过长,则可以给其一个别名,如:
select concat(first_namem,’ ‘,last_name) as name,
concat(city,’,’,state) as birth place
from president;这样就比较美观了。

6, 和日期有关的问题
首先记住:在MYSQL中,年份是放到最前面的!我们通常对日期进行下列操作:
按日期进行排序
查找某个日期或日期范围
提取日期中的年,元,日各个部分
计算两个日期的间隔
用一个日期求出另外一个日期
看例子:
select * from event where date=’2002-10-01’ //看看这天有何考试信息?
select last_name,first_name,birth,state from president
where death>’1900-01-01’ and death<’2000-01-01’; //看看上个世纪死了几个?
三个函数year,month,dayofmonth可以分别分离出日期中的年月日来。
select last_name,first_name,birth from president
where month(birth)=3; //谁生在3月 ?
where month(birth)=7 and dayofmonth(birth) =6; //谁生在7月6日?(汤姆克鲁斯?)
函数to_days可以把日期转换为天数。
select last_name,first_name,birth to_days(death)-to_days(birth) as age from president
可以看看这帮家伙都活了多少天!你自己把它改为年吧。
日期值的减法运算还能帮我们计算出现在距离某个特定日期还有多长的时间,这正是我们用来找到需要在近期内缴纳会费的会员的办法:
select last_name,first_name,expiration from member
where (to_days(expiration)-to_days(curdate())<60; //有些人60天内需要花钱了!

7, 模式匹配
有些情况下,模糊查询是很必要的,我们使用like和not like加上一个带通配符的字符串就可以了。共有两个通配符”_”(单个字符)和”&”(多个字符)
select concat(first_namem,’ ‘,last_name) as name,
where last_name like ‘W%’; //找到以W或w开头的人
where last_name like ‘%W%’; //找到名字里面W或w开头的人

8, 设置和使用SQL变量
MYSQL 3.23.6以上的版本可以使用查询结果来设置变量,我们就能够方面的把一些结果保存起来以供他用。变量的命名规格是:@name, 赋值语法是 @name:=value ( pascal?) 使用起来也简单:
select @birth:=birth from president
where last_name =’adsltiger’; //执行完成后我们就就会有一个@birth变量可用
用一下试试:
select concat(first_namem,’ ‘,last_name) as name from president
where birth<@birth order by birth; //看看那些人比我大!

*9, 生成统计信息
单纯依靠手工来生成统计信息是一项既艰苦又耗时还容易出错的工作,如果我们能熟练掌握用数据库来生成各种统计信息的技巧,他就会成为很有威力的信息处理工具。作者在这里用了许多篇幅讲这个主题,为了便于大家理解,我分解开来论述:
9.1 找出一组数据中到底有多少种不同的值是一项比较常见的统计工作,而关键字distinct就可以把查询结果中的重复数据清除掉。如
select distinct state from president //看看美国总统们都来自那些州?(重复的不计)
9.2用count()函数来统计相关记录的个数,注意其使用方法:count(*)计算所有的,NULL也要;count(数据列名称) NULL值不计算在内。
select count(*) from president;
9.3如果我们想知道班级内的男女生数目?该如何查询呢?最简单的方法是
select count(*) from student where sex=’f’;
select count(*) from student where sex=’m
但是如果使用count函数结合group by关键字,一行命令就搞定了
select sex,count(*) f rom student group by sex;
我们可以看到,与反复使用彼此类似的查询来分别统计某数据列不同取值出现次数的做法相比, 把count(*)和group by字句相结合使用有许多优点,主要表现在:
在开始统计自前,不必知道被统计的数据列里面有多少种不同的取值
因为只用了一个查询命令,我们可以对输出做排序的处理
select state,count(*) as count from president
group by state order by count desc limt4; //看看出生总统最多的前四个州是哪几个?
9.4除了count(),我们还用其他一些统计函数,如求出最小值的min(),求最大值的max(),求和的sum(),求平均值的avg(),在实际工作中,这些函数时经常用到的!

*10, 从多个表提取信息
我们目前的例子都是从一个表里面提取信息,但数据库的真正威力还在于用“关系”来综合多个数据表里面的记录,这种操作称之为“关联”或“结合”我们可以看到,select需要给出多个数据表里面的信息(不可重复);from需要知道从哪几个表里面做事;where则对几个表之间的关联信息作出详细的描述。
首先我们要学习最可靠的数据列引用方式:数据表名.数据列名。这样在查询中就一定不会混淆这个数据列到底在哪一个表里。
例子1:查询某一天内的学生们的考试成绩,用学号列出。
select scroe.student_id,event_date,score.score.event.type
from event,score
where event.date=’2003-09-12’
and event.event_id=score.event_id
首先,利用event数据表把日期映射到一个考试事件编号,在利用这个编号把score表内相匹配的考试分数找出来。关联两个表,一个查询搞定。
例子2:查询某一天内的学生们的考试成绩,用姓名列出。
select student.name event.name,score.score,event.type
form event,score,student
where event.date=’2003-09-12’
and event.event_id= score.event_id
and scroe.student_id=student.student_id;
关联三个表,一个查询搞定。
例子3:查询一下缺席学生的名字,学号,缺席次数
select student.student_id,student_name
count(absence.date) as absences
from student,absence
where student.student_id=absence.student_id //关联条件
group by student.student_id;

简单的关联操作就介绍到这里。事实上,对于关联的知识我们需要学的很多很多,比如说,我们怀疑某一个数据表内不存在和我们相关的数据,把么在关联查询的时候如何处理这个表呢?这就涉及到内联接,外联接,左联接,右联接的许多新概念了。不知道大家还有没有信心向下看我的笔记?在本书第四章里面,对关联进行了十分详细的论述,看来“在SQL里面,干粗活的是select”的说法再对不过了。

我们了解了select命令的如此之多的用法,感到了它的灵活性,许多字句的组合能够形成一个非常“精妙”的SQL语句,在基础没有打好之前,我等初学者目前还没有必要去钻研那些技巧性很高的东西,“一定程度的创造性是必要的,但太专业或充满技巧的代码则是各种 bug的发源地,同时也是若干个不眠之夜的前奏”

 

////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

 

 

 

SQL查询语句,绝对精彩的文章
 SQL  查询语句  文章
一、 简单查询
简单的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
另外,可以根据表达式进行排序。

 

 

 

/////////////////////////////////////////////////////////////////////

 

 

MySQL优化全攻略--相关数据库命令

  执行下面这个命令可以了解服务器的运行状态:
  
  mysql >show status;
  
  该命令将显示出一长列状态变量及其对应的值,其中包括:被中止访问的用户数量,被中止的连接数量,尝试连接的次数,并发连接数量最大值,以及其他许多有用的信息。这些信息对于确定系统问题和效率低下的原因是十分有用的。
  
  SHOW命令除了能够显示出MySQL服务器整体状态信息之外,它还能够显示出有关日志文件、指定数据库、表、索引、进程和许可权限表的宝贵信息。请访问http://www.mysql.com/doc/S/H/SHOW.html了解更多信息。
  
  ▲ EXPLAIN
  
  EXPLAIN能够分析SELECT命令的处理过程。这不仅对于决定是否要为表加上索引很有用,而且对于了解MySQL处理复杂连接的过程也很有用。
  
  下面这个例子显示了如何用EXPLAIN提供的信息逐步地优化连接查询。(本例来自MySQL文档,见http://www.mysql.com/doc/E/X/EXPLAIN.html。原文写到这里似乎有点潦草了事,特加上此例。)
  
  假定用EXPLAIN分析的SELECT命令如下所示:
  
  EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
  tt.ProjectReference, tt.EstimatedShipDate,
  tt.ActualShipDate, tt.ClientID,
  tt.ServiceCodes, tt.RepetitiveID,
  tt.CurrentProcess, tt.CurrentDPPerson,
  tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
  et_1.COUNTRY, do.CUSTNAME
  FROM tt, et, et AS et_1, do
  WHERE tt.SubmitTime IS NULL
  AND tt.ActualPC = et.EMPLOYID
  AND tt.AssignedPC = et_1.EMPLOYID
  AND tt.ClientID = do.CUSTNMBR;
  
  SELECT命令中出现的表定义如下:
  
  ※表定义
  
  表 列 列类型
  tt ActualPC CHAR(10)
  tt AssignedPC CHAR(10)
  tt ClientID CHAR(10)
  et EMPLOYID CHAR(15)
  do CUSTNMBR CHAR(15)
  
  ※索引
  
  表 索引
  tt ActualPC
  tt AssignedPC
  tt ClientID
  et EMPLOYID (主键)
  do CUSTNMBR (主键)
  
  ※tt.ActualPC值分布不均匀
  
  在进行任何优化之前,EXPLAIN对SELECT执行分析的结果如下:
  
  table type possible_keys    key key_len ref rows Extra
  et ALL PRIMARY      NULL NULL NULL 74
  do ALL PRIMARY      NULL NULL NULL 2135
  et_1 ALL PRIMARY      NULL NULL NULL 74
  tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872
  range checked for each record (key map: 35)
  
  每一个表的type都是ALL,它表明MySQL为每一个表进行了完全连接!这个操作是相当耗时的,因为待处理行的数量达到每一个表行数的乘积!即,这里的总处理行数为74 * 2135 * 74 * 3872 = 45,268,558,720。
  
  这里的问题之一在于,如果数据库列的声明不同,MySQL(还)不能有效地运用列的索引。在这个问题上,VARCHAR和CHAR是一样的,除非它们声明的长度不同。由于tt.ActualPC声明为CHAR(10),而et.EMPLOYID声明为CHAR(15),因此这里存在列长度不匹配问题。
  
  为了解决这两个列的长度不匹配问题,用ALTER TABLE命令把ActualPC列从10个字符扩展到15字符,如下所示:
  
  mysql > ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
  
  现在tt.ActualPC和et.EMPLOYID都是VARCHAR(15)了,执行EXPLAIN进行分析得到的结果如下所示:
  
  table type possible_keys key  key_len ref   rows Extra
  tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
  do ALL PRIMARY   NULL NULL NULL  2135
  range checked for each record (key map: 1)
  et_1 ALL PRIMARY   NULL NULL NULL  74
  range checked for each record (key map: 1)
  
  et eq_ref PRIMARY   PRIMARY 15  tt.ActualPC 1
  
  这还算不上完美,但已经好多了(行数的乘积现在少了一个系数74)。现在这个SQL命令执行大概需要数秒钟时间。
  
  为了避免tt.AssignedPC = et_1.EMPLOYID以及tt.ClientID = do.CUSTNMBR比较中的列长度不匹配,我们可以进行如下改动:
  
  mysql > ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
  MODIFY ClientID VARCHAR(15);
  
  现在EXPLAIN显示的结果如下:
  
  table type possible_keys key  key_len ref   rows  Extra
  et ALL PRIMARY   NULL NULL NULL   74
  tt ref AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used
  et_1 eq_ref PRIMARY   PRIMARY 15  tt.AssignedPC 1
  do eq_ref PRIMARY   PRIMARY 15  tt.ClientID 1
  
  这个结果已经比较令人满意了。
  
  余下的问题在于,默认情况下,MySQL假定tt.ActualPC列的值均匀分布,而事实上tt表的情况并非如此。幸而,我们可以很容易地让MySQL知道这一点:
  
  shell > myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt
  shell > mysqladmin refresh
  
  现在这个连接操作已经非常理想,EXPLAIN分析的结果如下:
  
  table type possible_keys key  key_len ref   rows Extra
  tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
  et eq_ref PRIMARY   PRIMARY 15  tt.ActualPC 1
  et_1 eq_ref PRIMARY   PRIMARY 15  tt.AssignedPC 1
  do eq_ref PRIMARY   PRIMARY 15  tt.ClientID 1
  
  ▲ OPTIMIZE
  
  OPTIMIZE能够恢复和整理磁盘空间以及数据碎片,一旦对包含变长行的表进行了大量的更新或者删除,进行这个操作就非常有必要了。OPTIMIZE当前只能用于MyISAM和BDB表。
  
  结束语:
  
  从编译数据库服务器开始、贯穿整个管理过程,能够改善MySQL性能的因素实在非常多,本文只涉及了其中很小的一部分。


 //////////////////////////////////////////////////////////////////

 

 

SQL select 使用IN关键字

      同BETWEEN关键字一样,IN的引入也是为了更方便地限制检索数据的范围,灵活使用IN关键字,可以用简洁的语句实现结构复杂的查询。  语法格式为:

    表达式 [NOT]  IN  (表达式1 , 表达式2 [,…表达式n])

【例】查询所有居住在KS、CA、MI或IN州的作家。

use  pubs

go

select  au_id,au_lname,au_fname

from   authors

where  state  IN ('CA','KS','MI','IN')

go

     如果不使用IN关键字,这些语句可以使用下面的语句代替:

use  pubs

go  select  au_id,au_lname,au_fname

from   authors

where  state='CA 'or state='KS'or state='MI'or state='IN'

go

【例】查询所有不在上述4个州居住的作家。

use  pubs

go

select  au_id,au_lname,au_fname

from     authors

where    state not in ('CA','KS','MI','IN')

 go      

与下面的语句等价:

use  pubs

go

select  au_id,au_lname,au_fname

from     authors

where    state<>'CA '

and  state<>'KS'

and   state<>'MI'

and  state<>'IN'

go

  
   

原创粉丝点击