SQL

 SQL 是用于访问和处理数据库的标准的计算机语言。

 在本教程中,您将学到如何使用 SQL 访问和处理数据系统中的数据,这类数据库包括:MySQL、SQL Server、Access、Oracle、Sybase、DB2和其他数据库系统。


每一章实例


 每章节都提供了简单的 SQL 简单实例。

实例

SELECT * FROM Customers;

 开始学习SQL吧!

 SQL查询从用户表中选择所有记录:

SELECT * FROM users;

 SQL查询通过使用where子句从用户表中删除单个记录:

DELETE FROM users WHERE user_id=299;

适用人群


 本参考的目的在于帮助初学者深入浅出地学习 SQL 语言。


SQL测验测试


 在51coolma测试你的SQL技能!

 开始SQL测验!


SQL快速参考


 一个SQL快速参考。打印并放在口袋里。

 SQL快速参考


SQL数据类型


 Microsoft Access,MySQL和SQL Server的数据类型和范围。

 SQL数据类型


W3Cschool实战认证


 实践出真知,通过获得证书是编程实例最好的证明

 去闯关



学习前提


 本参考准备了各种各样的示例,在正式开始练习之前,我假定你对什么是数据库——尤其是关系型数据库管理系统(RDBMS)——已经有所了解,同时也知道什么是计算机编程语言。


SQL简介


    SQL(结构化查询语言)是用于访问和操作数据库中的数据的标准数据库编程语言。

    SQL是关系数据库系统的标准语言。所有关系数据库管理系统(RDMS),如MySQL、MS Access、Oracle、Sybase、Informix、Postgres和SQL Server都使用SQL作为它们的标准数据库语言。

    为了处理数据库和数据库相关的编程,程序员需要有一些介质,或者可以说接口来详细说明一组命令或代码来处理数据库或访问数据库的数据。在本章中,将简要介绍在学习SQL的过程中您将学习的术语。


你会从SQL中学到什么?


    SQL为结构化查询语言提供了独特的学习和数据库处理技术,并将帮助您更好地控制SQL查询并有效处理这些代码。由于SQL帮助您包括数据库创建,数据库或表删除,获取行数据和修改这些数据等,并行SQL使得事情自动和平滑,最终用户可以轻松访问和处理该应用程序的数据。


SQL 是什么?


  • SQL 发音为“sequel”。
  • SQL 指结构化查询语言,全称是 Structured Query Language(是最初由IBM开发)。
  • SQL 是关系数据库系统的标准语言。
  • SQL 是一种 ANSI(American National Standards Institute 美国国家标准化组织)标准的计算机语言。


SQL 能做什么?


  • SQL可以创建新的数据库及其对象(表,索引,视图,存储过程,函数和触发器)。
  • SQL可以修改现有数据库的结构。
  • SQL可以从数据库中删除(删除)对象。
  • SQL可以TRUNCATE(删除)表中的所有记录。
  • SQL可以对数据字典进行COMMENT。
  • SQL可以RENAME一个对象。
  • SQL可以从数据库中选择(检索)数据。
  • SQL可以将数据插入到表中。
  • SQL可以更新表中的现有数据。
  • SQL可以从数据库表中删除记录。
  • SQL可以在数据库中设置用户的GRANT和REVOKE权限。


SQL 的历史


  • 1970年,SQL由IBM的Donald D. Chamberlin和Raymond F. Boyce开发。
  • 1974年,开发版本最初被称为SEQUEL(结构化英语查询语言)。
  • 1979年,关系软件发布了第一个叫做System / R的商业产品。
  • 由于商标冲突问题,SEQUEL首字母缩略词后来更改为SQL。
  • 后来IBM基于System / R的原型开始在SQL上开发商业产品。
  • 第一个关系数据库由RelationalSoftware发布,后来被称为Oracle。


SQL 是一种标准 - 但是...


    虽然 SQL 是一门 ANSI(American National Standards Institute 美国国家标准化组织)标准的计算机语言,但是仍然存在着多种不同版本的 SQL 语言。

然而,为了与 ANSI 标准相兼容,它们必须以相似的方式共同地来支持一些主要的命令(比如 SELECT、UPDATE、DELETE、INSERT、WHERE 等等)。

lamp注释:除SQL标准之外,大多数SQL数据库程序还具有自己的专有扩展名!

在您的网站中使用 SQL


    要创建一个显示数据库中数据的网站,您需要:

  • 一个RDBMS数据库程序(即MS Access,SQL Server,MySQL)。
  • 使用服务器端脚本语言,如PHP或ASP。
  • 使用SQL来获取所需的数据。
  • 使用HTML / CSS来设置页面的样式


RDBMS


    RDBMS 指关系型数据库管理系统,全称 Relational Database Management System。

    RDBMS 是 SQL 的基础,同样也是所有现代数据库系统的基础,比如 MS SQL Server、IBM DB2、Oracle、MySQL 以及 Microsoft Access。

    RDBMS 中的数据存储在被称为表的数据库对象中。

    表是相关的数据项的集合,它由列和行组成。

    代码示例:

SELECT * FROM Customers;

    每个表都被分解成称为字段的更小的实体。Customers表中的字段由CustomerID,CustomerName,ContactName,Address,City,PostalCode和Country组成。字段是表中的一列,用于维护表中每条记录的特定信息。

    记录(也称为行)是表中存在的每个单独条目。例如,在上面的Customers表中有91条记录。记录是表中的横向实体。

    列是表中的垂直实体,其包含与表中的特定字段相关联的所有信息。


SQL进程


    当您对任何RDBMS执行SQL命令时,系统将确定执行请求的最佳方式,并由SQL引擎确定如何解释该任务。

    在此过程中包含了各种组件。

    查询调度器优化引擎经典查询引擎SQL查询引擎

典型的查询引擎处理所有非SQL查询,但SQL查询引擎不会处理逻辑文件。


SQL标准命令


    与关系数据库交互的标准SQL命令是创建、选择、插入、更新、删除和删除,简单分为以下几组:

DDL(数据定义语言)

    数据定义语言用于改变数据库结构,包括创建、更改和删除数据库对象。用于操纵表结构的数据定义语言命令有:

  • CREATE TABLE-- 创建(在数据库中创建新表、表视图或其他对象)
  • ALTER TABLE-- 更改 (修改现有的数据库对象,如表)
  • DROP TABLE-- 删除  (删除数据库中的整个表、表或其他对象的视图)

DML(数据操纵语言)

    数据操纵语言用于检索、插入和修改数据,数据操纵语言是最常见的SQL命令。

    数据操纵语言命令包括:

  • INSERT-- 插入 (创建记录)
  • DELETE-- 删除 (删除记录)
  • UPDATE-- 修改(修改记录)
  • SELECT -- 检索 (从一个或多个表检索某些记录)

DCL(数据控制语言)

    数据控制语言为用户提供权限控制命令。

    用于权限控制的命令有:

  • GRANT-- 授予权限
  • REVOKE-- 撤销已授予的权限


SQL格式化


    使用SQL格式化工具可以比较直观的看到您想要的操作



章节小测


 现在,相信您已经了解了SQL的基础知识,那么,测验一下吧!

 SQL微课 - 数据库介绍:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL RDBMS 概念


 RDBMS是关系数据库管理系统(Relational Database Management System)的缩写。

 RDBMS是SQL的基础,也是所有现代数据库系统(如MS SQL Server、IBMDB2、Oracle、MySQL和MicrosoftAccess)的基础。

 关系数据库管理系统(Relational Database Management System,RDBMS)是一种基于E.F.Codd提出的关系模型的数据库管理系统。


什么是表?


 RDBMS中的数据存储在称为表的数据库对象中。这个表基本上是一个相关数据条目的集合,它由许多列和行组成。请记住,表是关系数据库中最常见和最简单的数据存储形式。

 下面的程序是Customers表的一个示例

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

什么是字段?


 每个表都被分解成更小的实体,称为字段。Customers表中的字段由ID、姓名、年龄、地址和薪资组成。

 字段是表中的列,用于维护有关表中每条记录的特定信息。


什么是记录或者行数据?


 记录也称为数据行,即表中存在的每个单独的条目。例如,上面的Customers表中有7条记录。下面是Customers表中的单行数据或记录。

+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |+----+----------+-----+-----------+----------+

 记录是表中的水平实体。


什么是列?


 列是表中的垂直实体,其中包含与表中特定字段关联的所有信息。

 例如,Customers表中的一列是Address,它表示位置描述,如下所示:

+-----------+| ADDRESS   |+-----------+| Ahmedabad || Delhi     || Kota      || Mumbai    || Bhopal    || MP        || Indore    |+----+------+

什么是空值?


 表中的空值是显示为空的字段中的值,这意味着具有空值的字段是没有值的字段。

 非常重要的一点是空值不同于零值或包含空格的字段。具有空值的字段是在创建记录时留空的字段。


SQL约束


 约束是在表上的数据列上强制执行的规则。它们用于限制可以进入表中的数据类型。

 这确保了数据库中数据的准确性和可靠性。

 约束可以是列级别,也可以是表级别。列级约束仅应用于一列,而表级约束则应用于整个表。

 以下是sql−中可用的一些最常用的约束

 约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。


数据完整性


 每个关系数据库管理系统都存在以下类型的数据完整性:

实体完整性−表中没有重复行。
域完整性−通过限制值的类型、格式或范围来强制执行给定列的有效条目。
引用完整性−不能删除其他记录使用的行。
用户定义的完整性−强制执行一些不属于实体、域或引用完整性的特定业务规则。

数据库规范化


 数据库规范化是在数据库中有效地组织数据的过程。这个规范化过程有两个原因:

  • 消除冗余数据,例如,将相同的数据存储在多个表中。 
  • 确保数据依赖关系是有意义的。

 这两个原因都是值得追求的目标,因为它们减少了数据库消耗的空间量,并确保了数据的逻辑存储。

 规范化由一系列指导原则组成,有助于指导您创建良好的数据库结构。

 规范化指导原则称为范式,范式的目的是组织数据库结构,使其符合第一范式、第二范式和第三范式的规则。

 你可以更长远的去选择第四范式,第五范式,等等,但一般来说,第三范式已经足够了。

第一范式(1NF)
第二范式(2NF)
第三范式(3NF)


SQL 语法规则


  • SQL语句总是以关键字开始,如SELECT、INSERT、UPDATE、DELETE、DROP、CREATE。
  • SQL语句以分号结尾。
  • SQL不区分大小写,意味着update与UPDATE相同。

数据库表


 数据库通常包含一个或多个表。每个表都用一个名称标识(例如,"Customers"或"Orders")。该表包含带有数据(行)的记录。
 在本教程中,我们将使用著名的Northwind示例数据库(包括MSAccess和MSSQLServer)。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

 上面的表包含五条记录(每一条对应一个客户)和七个列(CustomerID、CustomerName、ContactName、Address、City、PostalCode 和 Country)。


SQL 语句


 您需要在数据库上执行的大部分操作都是使用SQL语句完成的。

 以下SQL语句选择“Customers”表中的所有记录:

实例

SELECT * FROM Customers;

 在本教程中,我们将向您解释各种不同的SQL语句。


请记住...


  • SQL 对大小写不敏感:SELECT 与 select 是相同的。
  • 在本教程中,我们将以大写形式编写所有SQL关键字。

SQL 语句后面的分号?


  • 一些数据库系统需要在每个SQL语句的末尾使用分号。
  • 分号是分离数据库系统中每个SQL语句的标准方法,这样您就可以在对服务器的同一请求中执行多个SQL语句。
  • 在本教程中,我们将在每个SQL语句的末尾使用分号。

一些最重要的 SQL 命令


  • SELECT - 从数据库中提取数据
  • UPDATE - 更新数据库中的数据
  • DELETE - 从数据库中删除数据
  • INSERT INTO - 向数据库中插入新数据
  • CREATE DATABASE - 创建新数据库
  • ALTER DATABASE - 修改数据库
  • CREATE TABLE - 创建新表
  • ALTER TABLE - 变更(改变)数据库表
  • DROP TABLE - 删除表
  • CREATE INDEX - 创建索引(搜索键)
  • DROP INDEX - 删除索引


SELECT语句

 句法:

SELECT column_name(s) FROM table_name

SELECT语句和WHERE子句

 句法:

SELECT [*] FROM [TableName] WHERE [condition1]

SELECT语句与WHERE和/或子句

 句法:

SELECT [*] FROM [TableName] WHERE [condition1] [AND [OR]] [condition2]...

SELECT语句与ORDER BY

 句法:

SELECT column_name()FROM table_nameORDER BY column_name() ASC or DESC

SELECT  DISTINCT(区分)子句

 句法:

SELECT DISTINCT column1, column2....columnNFROM   table_name;

SELECT  IN子句

 句法:

SELECT column1, column2....columnNFROM   table_nameWHERE  column_name IN (val-1, val-2,...val-N);

SELECT LIKE (类)子句

 句法:

SELECT column1, column2....columnNFROM   table_nameWHERE  column_name LIKE { PATTERN };

SELECT  COUNT(计数)子句

 句法:

SELECT COUNT(column_name)FROM   table_nameWHERE  CONDITION;

SELECT与HAVING子句

 句法:

SELECT SUM(column_name)FROM   table_nameWHERE  CONDITIONGROUP BY column_nameHAVING (arithematic function condition);

INSERT INTO语句

 句法:

INSERT INTO table_name (column, column1, column2, column3, ...)VALUES (value, value1, value2, value3 ...)

UPDATE语句

 句法:

UPDATE table_nameSET column=value, column1=value1,...WHERE someColumn=someValue

DELETE语句

 句法:

DELETE FROM tableNameWHERE someColumn = someValue

CREATE 语句

 句法:

CREATE TABLE table_name(column1 datatype,column2 datatype,column3 datatype,.....columnN datatype,PRIMARY KEY( one or more columns ));

DROP 语句

 句法:

DROP TABLE table_name;

CREATE INDEX语句

 句法:

CREATE UNIQUE INDEX index_nameON table_name ( column1, column2,...columnN);

DROP INDEX语句

 句法:

ALTER TABLE table_nameDROP INDEX index_name;

DESC语句

 句法:

DESC table_name;

TRUNCATE 截断表语句

 句法:

TRUNCATE TABLE table_name;

ALTER TABLE语句

 句法:

ALTER TABLE table_name {ADD|DROP|MODIFY} column_name {data_ype};

ALTER TABLE语句(对表名重命名)

 句法:

ALTER TABLE table_name RENAME TO new_table_name;

Use语句 

 句法:

USE database_name;

COMMIT语句

 句法:

COMMIT;

ROLLBACK语句

 句法:

ROLLBACK;


章节小测


 现在,通过以下题目测测看您对“SQL 语法”的掌握程度吧!

 SQL语法规则:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL SELECT 语法


 SELECT 语法用于从数据库中选择数据。 

 返回的数据存储在结果表中,称为结果集。

基本语法:SELECT和FROM

 在任何SQL查询语句中都:SELECT和FROM他们必须按顺序排列。SELECT指示要查看哪些列,FROM标识它们所在的表。

 SQL SELECT 语法如下所示:

SELECT column1, column2, ...FROM table_name;

 这里,column1,column2,...是要从中选择数据的表的字段名称。如果要选择表中可用的所有字段,请使用以下语法:

SELECT * FROM table_name;

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是罗斯文示例数据库中“Customers”表的一个选择:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SELECT Column 实例


 我们将为以下三种用例提供实例

1、检索一列  
2、检索多列 
3、检索所有列

 我们将用上述的“Customers”表来说明三种用例的使用。

SELECT  检索一列

 下面的 SQL 语句从 "Customers" 表中选取 "City" 列:

实例

SELECT City FROM Customers; 

SELECT  检索多列

 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "City" 列:

实例

SELECT CustomerName, City FROM Customers;

注意:这两个列名在查询中用逗号分隔。每当您选择多个列时,它们必须用逗号分隔,但最后一列名称之后不能添加逗号。

SELECT * 实例 - 检索所有列

 下面的 SQL 语句从 "Customers" 表中选取所有列:

实例

SELECT * FROM Customers;

 如果要选择表中的所有列,则可以使用 * 而不需要把所有列名罗列查询。


结果集中的导航


 大多数数据库软件系统都允许使用编程函数在结果集中进行导航,例如:Move-To-First-Record、Get-Record-Content、Move-To-Next-Record 等等。

 本教程中不包括与这些编程函数类似的功能。要了解如何通过函数调用访问数据,请访问我们的 ADO 教程 或者 PHP 教程


章节小测


 现在,通过以下题目测测看您对“SQL Select(选择)语法”的掌握程度吧!

 SQL选择多列:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL SELECT DISTINCT 语法


 SELECT DISTINCT语法用于仅返回不同的(different)值。

 在一张表内,一列通常包含许多重复的值; 有时你只想列出不同的(different)值。

 SELECT DISTINCT语句用于仅返回不同的(different)值。

 SQL SELECT DISTINCT语法如下所示:

SELECT DISTINCT column1, column2, ...FROM table_name;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是罗斯文示例数据库中 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SELECT实例


 以下SQL语句从“Customers”表中的“Country”列中选择所有(包括重复)值:

 代码示例:

 SELECT Country FROM Customers;

SELECT Country FROM Customers;

 以上查询的结果:

CountryGermanyMexicoMexicoUK

Sweden

 现在,让我们在上面的SELECT语法中使用DISTINCT关键字并查看结果。


SELECT DISTINCT 实例


 以下SQL语句仅从"Customers" 表中的 "Country" 列中选择DISTINCT值:

实例1

SELECT DISTINCT Country FROM Customers;

 查询结果:

CountryGermanyMexicoUKSweden


 以下SQL语句列出了不同(distinct)客户国家的数量: 

实例2

SELECT COUNT(DISTINCT Country) FROM Customers; 

注意:上述示例在Firefox和Microsoft Edge中不起作用!

 由于在Microsoft Access数据库中不支持COUNT(DISTINCT column_name)。在我们的示例中Firefox和Microsoft Edge使用Microsoft Access。


章节小测


 现在,通过以下题目测测看您对“SQL SELECT DISTINCT(选择不同) 语法”的掌握程度吧!

 SQL DISTINCT关键字:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL WHERE 子句


 WHERE 子句用于过滤记录。

 WHERE 子句用于提取满足指定标准的记录。 

SQL WHERE 语法

SELECT column1, column2, ...FROM table_nameWHERE condition;
注意: WHERE子句不仅用于SELECT语法,还用于UPDATE,DELETE语法等!

 WHERE子句可以与以下类型的SQL语句一起使用:

  • UPDATE
  • DELETE

 UPDATE语句:

UPDATE "table_name"SET "column_1" = [new value]WHERE "condition";

 DELETE语句:

DELETE FROM "table_name"WHERE "condition";

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。
 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

WHERE 子句实例


 以下SQL语句从"Customers"表中选择其国家为"Mexico"的所有客户:

实例

SELECT * FROM Customers
WHERE Country='Mexico';

 你也可以使用OR运算符的查询子句:

实例

SELECT * FROM Customers
WHERE Country='Mexico' OR PostalCode='05021';

文本字段与数值字段


 SQL在文本值周围使用单引号(大多数数据库系统也接受双引号)。

 如果是数值字段,则不要使用引号。

实例

SELECT * FROM Customers
WHERE CustomerID=1;

WHERE 子句中的运算符


 WHERE子句中可以使用以下运算符:

运算符描述
=等于
<>不等于。 注意:在某些版本的SQL中,这个操作符可能写成!=
>大于
<小于
>=大于等于
<=小于等于
BETWEEN在某个范围内
LIKE搜索某种模式
IN为列指定多个可能的值


章节小测


 现在,通过以下题目测测看您对“SQL WHERE Clause(查询子句)”的掌握程度吧!

 SQL WHERE语句:在本部分测验中,您将练习使用 WHERE 语句的基础语法,以及如何在 WHERE 子句中使用 SQL 运算符。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL AND & OR 运算符


 AND&OR运算符用于根据一个以上的条件过滤记录,即用于组合多个条件以缩小SQL语句中的数据。

 WHERE子句可以与AND,OR和NOT运算符结合使用。

 AND和OR运算符用于根据多个条件筛选记录:

  • 如果由AND分隔的所有条件为TRUE,则AND运算符显示记录。
  • 如果使用AND运算符组合N个条件。对于SQL语句执行的操作(无论是事务还是查询),所有由AND分隔的条件都必须为TRUE。
  • 如果由OR分隔的任何条件为真,则OR运算符显示记录。
  • 如果使用OR运算符组合N个条件。对于SQL语句执行的操作(无论是事务还是查询),OR分隔的任何一个条件都必须为TRUE。

 如果条件不为TRUE,则NOT运算符显示记录。 

AND语法

SELECT column1, column2, ...FROM table_nameWHERE condition1 AND condition2 AND condition3 ...;

OR语法

SELECT column1, column2, ...FROM table_nameWHERE condition1 OR condition2 OR condition3 ...;

NOT语法

SELECT column1, column2, ...FROM table_nameWHERE NOT condition;


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers"表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

AND 运算符实例


 以下SQL语句从 "Customers" 表中选择其国家为 "Germany" 、其城市为"Berlin" 的所有客户:

实例

SELECT * FROM Customers
WHERE Country='Germany'
AND City='Berlin';

OR 运算符实例


 以下SQL语句选择城市为“Berlin”或“München”的“Customers”的所有字段:

实例

SELECT * FROM Customers
WHERE City='Berlin' OR City='München';

NOT 运算符实例


 以下SQL语句选择国家不是 "Germany"的"Customers"的所有字段:

SELECT * FROM CustomersWHERE NOT Country='Germany';

结合 AND & OR


 您还可以组合AND和OR(使用括号来组成成复杂的表达式)。

 以下SQL语句从国家 "Germany" 且城市为"Berlin" 或"München"的"Customers" 表中选择所有客户:

实例

SELECT * FROM Customers
WHERE Country='Germany'
AND (City='Berlin' OR City='München');


结合AND,OR和NOT


 你也可以结合AND,OR和NOT运算符。

 以下SQL语句选择国家是“德国”的“客户”的所有字段,城市必须是“柏林”或“慕尼黑”(用括号形成复杂表达式):

 代码示例:

SELECT * FROM CustomersWHERE Country='Germany' AND (City='Berlin' OR City='München');

 以下SQL语句选择来自"Customers" 的国家不是 "Germany" 且不是 "USA"的所有字段:

 代码示例:

SELECT * FROM CustomersWHERE NOT Country='Germany' AND NOT Country='USA';

章节小测


 现在,通过以下题目测测看您对“SQL AND, OR and NOT(与,或不是运算符)”的掌握程度吧!

 SQL AND, OR运算符:在本部分测验中,您将练习使用 SQL 的 AND, OR 运算符。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL ORDER BY 关键字


 ORDER BY 关键字用于按升序或降序对结果集进行排序。

 ORDER BY 关键字默认情况下按升序排序记录。

 如果需要按降序对记录进行排序,可以使用DESC关键字。

SQL ORDER BY 语法

SELECT column1, column2, ...FROM table_nameORDER BY column1, column2, ... ASC|DESC;

 您可以在ORDER BY子句中使用多个列,但要确保用于对该列进行排序的列应该在列表中。


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

ORDER BY 实例


 下面的 SQL 语句从 "Customers" 表中选取所有客户,并按照 "Country" 列排序:

实例

SELECT * FROM Customers
ORDER BY Country;

ORDER BY DESC 实例


 下面的 SQL 语句从 "Customers" 表中选取所有客户,并按照 "Country" 列降序排序:

实例

SELECT * FROM Customers
ORDER BY Country DESC;

ORDER BY 多列 实例1


 下面的 SQL 语句从 "Customers" 表中选取所有客户,并按照 "Country" 和 "CustomerName" 列排序:

实例

SELECT * FROM Customers
ORDER BY Country, CustomerName;

ORDER BY 多列 实例2


 以下SQL语句从"Customers" 表中选择所有客户,按 "Country" 升序排列,并按 "CustomerName" 列降序排列:

SELECT * FROM CustomersORDER BY Country ASC, CustomerName DESC;


章节小测


 更多测试题请参考:《SQL测验》题库>>


SQL INSERT INTO 语句


 INSERT INTO 语句用于向表中插入新的数据行。

SQL INSERT INTO 语法

 INSERT INTO 语句可以用两种形式编写。
 第一个表单没有指定要插入数据的列的名称,只提供要插入的值,即可添加一行新的数据:

INSERT INTO table_name (column1, column2, column3, ...)VALUES (value1, value2, value3, ...);

 第二种,如果要为表中的所有列添加值,则不需要在SQL查询中指定列名称。但是,请确保值的顺序与表中的列顺序相同。INSERT INTO语法如下所示:

INSERT INTO table_nameVALUES (value1, value2, value3, ...);

演示数据库


 在本教程中,我们将使用著名的 Northwind 示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
87Wartian HerkkuPirkko KoskitaloTorikatu 38Oulu90110Finland
88Wellington ImportadoraPaula ParenteRua do Mercado, 12Resende08737-363Brazil
89White Clover MarketsKarl Jablonski305 - 14th Ave. S. Suite 3BSeattle98128USA
90
Wilman KalaMatti KarttunenKeskuskatu 45Helsinki21240Finland
91
WolskiZbyszekul. Filtrowa 68Walla01-012Poland

INSERT INTO 实例


 假设我们想在"Customers"表中插入一个新行。

 我们可以使用以下SQL语句:

实例

INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
VALUES ('Cardinal','Tom B. Erichsen','Skagen 21','Stavanger','4006','Norway');

 现在,选自 "Customers" 表的数据如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
87Wartian HerkkuPirkko KoskitaloTorikatu 38Oulu90110Finland
88Wellington ImportadoraPaula ParenteRua do Mercado, 12Resende08737-363Brazil
89White Clover MarketsKarl Jablonski305 - 14th Ave. S. Suite 3BSeattle98128USA
90
Wilman KalaMatti KarttunenKeskuskatu 45Helsinki21240Finland
91
WolskiZbyszekul. Filtrowa 68Walla01-012Poland
92CardinalTom B. ErichsenSkagen 21Stavanger4006Norway

lamp注意到了吗?我们没有将任何号码插入 CustomerID 字段。
CustomerID列是一个自动递增字段,在将新记录插入到表中时自动生成。

仅在指定的列中插入数据


 我们还可以只在指定的列中插入数据。

 以下SQL语句插入一个新行,但只在“CustomerName”、“City”和“Country”列中插入数据(CustomerID字段将自动更新):

实例

INSERT INTO Customers (CustomerName, City, Country)
VALUES ('Cardinal', 'Stavanger', 'Norway');

 现在,选自 "Customers" 表的数据如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
87Wartian HerkkuPirkko KoskitaloTorikatu 38Oulu90110Finland
88Wellington ImportadoraPaula ParenteRua do Mercado, 12Resende08737-363Brazil
89White Clover MarketsKarl Jablonski305 - 14th Ave. S. Suite 3BSeattle98128USA
90
Wilman KalaMatti KarttunenKeskuskatu 45Helsinki21240Finland
91
WolskiZbyszekul. Filtrowa 68Walla01-012Poland
92CardinalnullnullStavangernullNorway

使用另一个表填充一个表


 您可以通过另一个表上的SELECT语句查询出来的字段值,然后将数据填充到本表中,条件是另一个表所查询的字段与本表要插入数据的字段是一一对应的。

INSERT INTO first_table_name [(column1, column2, ... columnN)] SELECT column1, column2, ...columnN FROM second_table_name[WHERE condition];


章节小测


 现在,通过以下题目测测看您对“SQL INSERT INTO 语句(在表中插入)”的掌握程度吧!

 SQL INSERT语句:在本部分测验中,您将通过选择填空、排序、判断的题型来练习在 SQL 中插入数据。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


什么是SQL NULL值?


 SQL 中,NULL 用于表示缺失的值。数据表中的 NULL 值表示该值所处的字段为空。

 具有NULL值的字段是没有值的字段。

 如果表中的字段是可选的,则可以插入新记录或更新记录而不向该字段添加值。然后,该字段将被保存为NULL值。

 值为 NULL 的字段没有值。尤其要明白的是,NULL 值与 0 或者包含空白(spaces)的字段是不同的。

注意:理解NULL值与零值或包含空格的字段不同是非常重要的。具有NULL值的字段是在记录创建期间留空的字段!


如何测试NULL值?


 使用比较运算符(例如=,<或<>)来测试NULL值是不可行的。

 我们将不得不使用IS NULL和IS NOT NULL运算符。

IS NULL语法

SELECT column_namesFROM table_nameWHERE column_name IS NULL;

IS NOT NULL语法

SELECT column_namesFROM table_nameWHERE column_name IS NOT NULL;

演示数据库


 假设我们有以下的“人员”表:

IDLastNameFirstNameAddressCity
1DoeJohn542 W. 27th StreetNew York
2BloggsJoe London
3RoeJane New York
4SmithJohn110 BishopsgateLondon

 假设“人员”表中的“Address”列是可选的。如果插入的记录没有“Address”值,则“Address”列将以空值保存。


IS NULL运算符


 以下SQL语句使用IS NULL运算符来列出所有没有地址的人员:

SELECT LastName, FirstName, Address FROM PersonsWHERE Address IS NULL;

 结果集将如下所示:

LastNameFirstNameAddress
BloggsJoe 
RoeJane 

提示:始终使用IS NULL来查找空值。


IS NOT NULL运算符


 以下SQL语句使用IS NOT NULL运算符来列出所有具有地址的人员:

SELECT LastName, FirstName, Address FROM PersonsWHERE Address IS NOT NULL;

 结果集将如下所示:

LastNameFirstNameAddress
DoeJohn542 W. 27th Street
SmithJohn110 Bishopsgate


语法:


 创建表的时候,NULL 的基本语法如下:

SQL> CREATE TABLE CUSTOMERS(   ID   INT              NOT NULL,   NAME VARCHAR (20)     NOT NULL,   AGE  INT              NOT NULL,   ADDRESS  CHAR (25) ,   SALARY   DECIMAL (18, 2),          PRIMARY KEY (ID));

 这里,NOT NULL表示对于给定列,必须按照其数据类型明确赋值。有两列并没有使用 NOT NULL 来限定,也就是说这些列可以为 NULL。

 值为 NULL 的字段是在记录创建的过程中留空的字段。


示例:


 NULL 值会给选取数据带来麻烦。不过,因为 NULL 和其他任何值作比较,其结果总是未知的,所以含有 NULL 的记录不会包含在最终结果里面。

 必须使用 IS NULL 或者 IS NOT NULL 来检测某个字段是否为 NULL。

 考虑下面的 CUSTOMERS 数据表,里面包含的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |          ||  7 | Muffy    |  24 | Indore    |          |+----+----------+-----+-----------+----------+

 下面是 IS NOT NULL 运算符的用法:

SQL> SELECT  ID, NAME, AGE, ADDRESS, SALARY     FROM CUSTOMERS     WHERE SALARY IS NOT NULL;

 上面语句的运行结果如下:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 |+----+----------+-----+-----------+----------+

 下面是 IS NULL 运算符的用法:

SQL> SELECT  ID, NAME, AGE, ADDRESS, SALARY     FROM CUSTOMERS     WHERE SALARY IS NULL;

 其运行结果如下:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  6 | Komal    |  22 | MP        |          ||  7 | Muffy    |  24 | Indore    |          |+----+----------+-----+-----------+----------+



SQL UPDATE 语句


 UPDATE 语句用于更新表中已存在的记录。

 还可以使用AND或OR运算符组合多个条件。               

SQL UPDATE 语法

 具有WHERE子句的UPDATE查询的基本语法如下所示:

UPDATE table_nameSET column1 = value1, column2 = value2, ...WHERE condition;

lamp请注意
更新表中的记录时要小心!
要注意SQL UPDATE 语句中的 WHERE 子句!

WHERE子句指定哪些记录需要更新。如果省略WHERE子句,所有记录都将更新!

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL UPDATE 实例


 以下SQL语句为第一个客户(CustomerID = 1)更新了“ContactName”和“City”:

实例

UPDATE Customers
SET ContactName = 'Alfred Schmidt', City= 'Frankfurt'
WHERE CustomerID = 1;

 现在,选自 "Customers" 表的数据如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteAlfred SchmidtObere Str. 57Frankfurt12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

更新多个记录


 WHERE子句决定了将要更新的记录数量。

 以下SQL语句将把国家/地区为"Mexico"的所有记录的联系人姓名更新为“Juan”:

UPDATE CustomersSET ContactName='Juan'WHERE Country='Mexico';

 “Customers”表中的选择现在看起来像这样:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteAlfred SchmidtObere Str. 57Frankfurt12209Germany
2Ana Trujillo Emparedados y heladosJuanAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaJuanMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden


Update 警告!


 更新记录时要小心。如果您省略WHERE子句,所有记录将被更新!

UPDATE CustomersSET ContactName='Juan';


 "Customers" 表将如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteJuanObere Str. 57Frankfurt12209Germany
2Ana Trujillo Emparedados y heladosJuanAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaJuanMataderos 2312México D.F.05023Mexico
4

Around the HornJuan120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpJuanBerguvsvägen 8LuleåS-958 22Sweden


章节小测


 现在,通过以下题目测测看您对“SQL UPDATE 语句(更新表中的记录)”的掌握程度吧!

 SQL UPDATE语句:在本部分测验中,您将练习使用 SQL 的 UPDATE 语句来更新数据。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL DELETE 语句


 DELETE语句用于删除表中现有记录。

SQL DELETE 语法

DELETE FROM table_nameWHERE condition;

lamp请注意
删除表格中的记录时要小心!
注意SQL DELETE 语句中的 WHERE 子句!

WHERE子句指定需要删除哪些记录。如果省略了WHERE子句,表中所有记录都将被删除!

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL DELETE 实例


 假设我们想从"Customers" 表中删除客户“Alfreds Futterkiste”。

 我们使用以下SQL语句:

实例

DELETE FROM Customers
WHERE CustomerName='Alfreds Futterkiste';

 现在,"Customers" 表如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

删除所有数据


 您可以删除表中的所有行,而不需要删除该表。这意味着表的结构、属性和索引将保持不变:

DELETE FROM table_name;

 或者

DELETE * FROM table_name;
注意:在没有备份的情况下,删除记录要格外小心!因为你删除了不能重复!


章节小测


 现在,通过以下题目测测看您对“SQL Delete 语句(删除表中的记录)”的掌握程度吧!

 SQL Delete语句:在本部分测验中,您将通过一道选择填空来练习使用 SQL 的 Delete 语句。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL 运算符


运算符是保留字或主要用于 SQL 语句的 WHERE 子句中的字符,用于执行操作,例如:比较和算术运算。 这些运算符用于指定 SQL 语句中的条件,并用作语句中多个条件的连词。

常见运算符有以下几种:

  • 算术运算符
  • 比较运算符
  • 逻辑运算符
  • 否定条件运算符

SQL 算术运算符


假设变量 a 的值是:10,变量 b 的值是:20,以下为各运算符执行结果:

运算符描述例子

+

加法,执行加法运算。

a + b 得到 30

-

减法,执行减法运算。

a - b 得到  -10

*

乘法,执行乘法运算。

a * b 得到  200

/

用左操作数除以右操作数。

b / a 得到  2

%

用左操作数除以右操作数并返回余数。

b % a 得到  0


SQL 比较运算符


假设变量 a 的值是:10,变量 b 的值是:20,以下为各运算符执行结果:

运算符描述例子
=检查两个操作数的值是否相等,如果是,则条件为真(true)。
(a = b) is false.
!=检查两个操作数的值是否相等,如果值不相等则条件为真(true)。
(a != b)  is  true.
<>检查两个操作数的值是否相等,如果值不相等则条件为真(true)。(a <> b) is true.
>检查左操作数的值是否大于右操作数的值,如果是,则条件为真(true)。
(a > b) is false.
<检查左操作数的值是否小于右操作数的值,如果是,则条件为真(true)。(a < b) is true.
>=检查左操作数的值是否大于或等于右操作数的值,如果是,则条件为真(true)。(a >= b) is false
<=检查左操作数的值是否小于或等于右操作数的值,如果是,则条件为真(true)。(a <= b) is true.
!<检查左操作数的值是否不小于右操作数的值,如果是,则条件变为真(true)。(a !< b) is false.
!>检查左操作数的值是否不大于右操作数的值,如果是,则条件变为真(true)。(a !> b) is true.

SQL 逻辑运算符:


这是在 SQL 所有的逻辑运算符的列表。

运算符描述
ALLALL运算符用于将值与另一个值集中的所有值进行比较。
ANDAND运算符允许在SQL语句的WHERE子句中指定多个条件。
ANYANY运算符用于根据条件将值与列表中的任何适用值进行比较。
BETWEENBETWEEN运算符用于搜索在给定最小值和最大值内的值。
EXISTSEXISTS运算符用于搜索指定表中是否存在满足特定条件的行。
ININ运算符用于将值与已指定的文字值列表进行比较。
LIKELIKE运算符用于使用通配符运算符将值与类似值进行比较。
NOTNOT运算符反转使用它的逻辑运算符的含义。 例如:NOT EXISTS, NOT BETWEEN, NOT IN等等,这是一个否定运算符。
OROR运算符用于组合SQL语句的WHERE子句中的多个条件。
IS NULLIS NULL运算符用于将值与NULL值进行比较。
UNIQUEUNIQUE运算符搜索指定表的每一行的唯一性(无重复项)。


章节小测


 现在,通过以下题目测测看您对“SQL 运算符”的掌握程度吧!

 SQL  IN,NOT IN 运算符:在本部分测验中,您将练习使用 SQL 的 IN 运算符以及 NOT IN 运算符

 点击此处进行测试>>

 SQL  LIKE 运算符:在本部分测验中,您将练习使用 SQL 的 LIKE 运算符

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL 表达式


 表达式是计算值的一个或多个值、运算符和SQL函数的组合。这些SQL表达式类似于公式,它们是用查询语言编写的。

 您还可以使用它们查询数据库中的特定数据集。

句法

 考虑SELECT语句的基本语法,如下所示:

SELECT column1, column2, columnN FROM table_name WHERE [CONDITION|EXPRESSION];

 有不同类型的sql表达式,如下所示:

  • 布尔型
  • 数值型
  • 日期

 现在让我们详细讨论每一个问题。


布尔表达式


 SQL布尔表达式基于匹配单个值获取数据。

 句法:

SELECT column1, column2, columnN FROM table_name WHERE SINGLE VALUE MATCHING EXPRESSION;

 使用具有以下记录的Customers表:

SQL> SELECT * FROM CUSTOMERS;+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+7 rows in set (0.00 sec)

 下表是一个简单的示例,展示了各种sql布尔表达式的用法。

SQL> SELECT * FROM CUSTOMERS WHERE SALARY = 10000;+----+-------+-----+---------+----------+| ID | NAME  | AGE | ADDRESS | SALARY   |+----+-------+-----+---------+----------+|  7 | Muffy |  24 | Indore  | 10000.00 |+----+-------+-----+---------+----------+1 row in set (0.00 sec)

数值表达式


 数值表达式用于在任何查询中执行任何数学运算。

 句法:

SELECT numerical_expression as  OPERATION_NAME[FROM table_nameWHERE CONDITION] ;

 这里,数值表达式用于数学表达式或任何公式。下面是一个简单的示例,展示了SQLNDigitic表达式的用法:

SQL> SELECT (15 + 6) AS ADDITION+----------+| ADDITION |+----------+|       21 |+----------+1 row in set (0.00 sec)

 有几个内置函数,如avg()、sum()、count()等,用于对表或特定表列执行所谓的聚合数据计算。

SQL> SELECT COUNT(*) AS "RECORDS" FROM CUSTOMERS; +---------+| RECORDS |+---------+|       7 |+---------+1 row in set (0.00 sec)

日期表达式


 日期表达式返回当前系统日期和时间值:

SQL>  SELECT CURRENT_TIMESTAMP;+---------------------+| Current_Timestamp   |+---------------------+| 2009-11-12 06:40:23 |+---------------------+1 row in set (0.00 sec)

 另一个日期表达式如下所示:

SQL>  SELECT  GETDATE();;+-------------------------+| GETDATE                 |+-------------------------+| 2009-10-22 12:07:18.140 |+-------------------------+1 row in set (0.00 sec)


SQL 选择数据库 USE语句


 当SQL Schema中有多个数据库时,在开始操作之前,需要选择一个执行所有操作的数据库。

 SQL USE语句用于选择SQL架构中的任何现有数据库。

句法

 USE语句的基本语法如下所示 :

USE DatabaseName;

 数据库名称在RDBMS中必须是唯一的。


实例


 您可以查看可用的数据库,如下所示:

SQL> SHOW DATABASES;+--------------------+| Database           |+--------------------+| information_schema || AMROOD             || TUTORIALSPOINT     || mysql              || orig               || test               |+--------------------+6 rows in set (0.00 sec)

 现在,如果您想使用AMROOD数据库,那么您可以执行以下SQL命令并开始使用AMROOD数据库。

SQL> USE AMROOD;


SQL SELECT TOP 子句


  • SELECT TOP 子句用于指定要返回的记录数量。
  • SELECT TOP子句在包含数千条记录的大型表上很有用。返回大量记录会影响性能。

注:并不是所有的数据库系统都支持SELECT TOP子句。MySQL支持LIMIT子句来选择有限数量的记录,而Oracle使用ROWNUM。

SQL Server / MS Access 语法

SELECT TOP number|percent column_name(s)FROM table_nameWHERE condition;

MySQL 和 Oracle 中的 SQL SELECT TOP 是等价的


MySQL语法:

SELECT column_name(s)FROM table_nameWHERE conditionLIMIT number;

实例

SELECT *FROM PersonsLIMIT 5;

Oracle 语法

SELECT column_name(s)FROM table_nameWHERE ROWNUM <= number;

实例

SELECT *FROM PersonsWHERE ROWNUM <=5;

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL SELECT TOP 实例


 以下SQL语句从"Customers" 表中选择前两条记录:

实例

SELECT TOP 2 * FROM Customers;

SQL SELECT TOP PERCENT 实例


 以下SQL语句从 "Customers" 表中选择前50%的记录:

实例

SELECT TOP 50 PERCENT * FROM Customers;

SQL TOP,LIMIT和ROWNUM示例


 以下SQL语句从"Customers"表中选择前三个记录:

SELECT TOP 3 * FROM Customers;

 以下SQL语句显示了使用LIMIT子句的等效示例:

SELECT * FROM CustomersLIMIT 3;

 以下SQL语句显示了使用ROWNUM的等效示例:

SELECT * FROM CustomersWHERE ROWNUM <= 3;

SQL TOP PERCENT示例


 以下SQL语句从"Customers"表中选择记录的前50%:

SELECT TOP 50 PERCENT * FROM Customers;

添加一个条件


 以下SQL语句从"Customers"表中选择国家为"Germany"的前三条记录:

SELECT TOP 3 * FROM CustomersWHERE Country='Germany';

 以下SQL语句显示了使用LIMIT子句的等效示例:

SELECT * FROM CustomersWHERE Country='Germany'LIMIT 3;

 以下SQL语句显示了使用ROWNUM的等效示例:

SELECT * FROM CustomersWHERE Country='Germany' AND ROWNUM <= 3;

为什么要LIMIT你的查询结果


 LIMIT作为一种简单的分页方法,主要是为了减少数据返回的时间,如果您查询一个非常大的表(例如一个有数十万或数百万行的表)而不使用限制,那么您可能会等待很长时间才能显示所有的结果,所以使用LIMIT可以减少查询数据返回的时间,提高效率。


章节小测


 现在,通过以下题目测测看您对本章节内容的掌握程度吧!

 SQL LIMIT关键字:在本部分测验中,您将练习使用 SQL LIMIT 关键字返回所有符合 SQL 语句中指定条件的结果。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL LIKE 运算符


 在WHERE子句中使用LIKE运算符来搜索列中的指定模式。 

 有两个通配符与LIKE运算符一起使用:

  • - 百分号表示零个,一个或多个字符
  • _ - 下划线表示单个字符

 注意: MS Access使用问号(?)而不是下划线(_)。

 百分号和下划线也可以组合使用! 

SQL LIKE 语法

SELECT column1, column2, ...FROM table_nameWHERE columnN LIKE pattern;
 提示:您还可以使用AND或OR运算符组合任意数量的条件。

 下面是一些使用'%'和'_'通配符显示不同LIKE运算符的例子:

LIKE 运算符描述
WHERE CustomerName LIKE 'a%'查找以“a”开头的任何值
WHERE CustomerName LIKE '%a'查找以“a”结尾的任何值
WHERE CustomerName LIKE '%or%'在任何位置查找任何具有“or”的值
WHERE CustomerName LIKE '_r%'在第二个位置查找任何具有“r”的值
WHERE CustomerName LIKE 'a_%_%'查找以“a”开头且长度至少为3个字符的值
WHERE ContactName LIKE 'a%o'找到以"a"开头,以"o"结尾的值

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers"表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LIKE 运算符实例


 以下SQL语句选择以“a”开头的CustomerName的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE 'a%';

 以下SQL语句选择客户名称以“a”结尾的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE '%a';

 以下SQL语句选择客户名称在任何位置都具有“或”的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE '%or%';

 以下SQL语句选择客户名称在第二位具有“r”的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE '_r%';

 以下SQL语句选择客户名称以“a”开头且长度至少为3个字符的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE 'a_%_%';

 以下SQL语句选择联系人名称以“a”开头并以“o”结尾的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE ContactName LIKE 'a%o';

 以下SQL语句选择客户名称不以“a”开头的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName NOT LIKE 'a%';

 以下SQL语句选择客户名称以“a”开头,以“s”结尾的5位字符的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE 'a___s';


SQL Wildcards 通配符


 通配符用于替换字符串中的任何其他字符。

 通配符与 SQL LIKE 运算符一起使用。在 WHERE 子句中使用LIKE运算符来搜索列中的指定模式。 

 有两个通配符与 LIKE 运算符一起使用:

  • - 百分号表示零个,一个或多个字符
  • _ - 下划线表示单个字符

 注意: 

  • MS Access 使用星号(*)通配符而不是百分比符号(%)通配符。 
  • MS Access 使用问号(?)而不是下划线(_)。

 在MS Access和SQL Server中,你也可以使用:

  • [ charlist ] - 定义要匹配的字符的集合和范围
  • [^ charlist ]或[!charlist ] - 定义不匹配字符的集合和范围

 通配符也可以组合使用!

 下面是一些使用''和'_'通配符显示不同LIKE运算符的例子:

LIKE运算符描述
WHERE CustomerName LIKE 'a%'查找以“a”开头的任何值
WHERE CustomerName LIKE '%a'查找以"a"结尾的任何值
WHERE CustomerName LIKE '%or%'在任何位置查找任何具有“or”的值
WHERE CustomerName LIKE '_r%'在第二个位置查找任何具有“r”的值
WHERE CustomerName LIKE 'a_%_%'查找以“a”开头并且长度至少为3个字符的值
WHERE ContactName LIKE 'a%o'查找以“a”开始并以“o”结尾的任何值

演示数据库


 在本教程中,我们将使用著名的 Northwind 示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

使用 SQL % 通配符


 以下 SQL 语句选择所有客户 City 以字母“ber”开头:

实例

SELECT * FROM Customers
WHERE City LIKE 'ber%';

 以下 SQL 语句选择 City 中包含“es”模式的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE '%es%';

使用 SQL _ 通配符


 以下 SQL 语句选择 City 以任意字符开头,然后是“erlin”的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE '_erlin';

 以下 SQL 语句选择 City 开头为“L”,后面是任意字符,后面是“n”,后面是任意字符,后面是“on”的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE 'L_n_on';

使用 SQL [charlist] 通配符


以下 SQL 语句选择所有客户 City 以"b"、"s"或"p"开头:

实例

SELECT * FROM Customers
WHERE City LIKE '[bsp]%';

以下 SQL 语句选择“City”以“a”、“b”或“c”开头的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE '[a-c]%';

以下 SQL 语句选择所有客户 City 不以"b"、"s"或"p"开头:

实例

SELECT * FROM Customers
WHERE City LIKE '[!bsp]%';

使用[!charlist]通配符


以下两个 SQL 语句选择所有客户的城市不以“b”,“s”或“p”开头:

代码示例:

SELECT * FROM CustomersWHERE City LIKE '[!bsp]%';

要么:

代码示例:

SELECT * FROM CustomersWHERE City NOT LIKE '[bsp]%';


SQL IN 运算符


 IN 运算符允许您在 WHERE 子句中指定多个值。

 IN 运算符是多个 OR 条件的简写。

SQL IN 语法

SELECT column_name(s)FROM table_nameWHERE column_name IN (value1, value2, ...);

或者

SELECT column_name(s)FROM table_nameWHERE column_name IN (SELECT STATEMENT);

演示数据库


 在本教程中,我们将使用著名的 Northwind 示例数据库。

 以下数据选取自"Customers" 表:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

IN 操作符实例


 以下 SQL 语句选取位于“Germany”,“France”和“UK”的所有客户:

代码示例:

SELECT * FROM CustomersWHERE Country IN ('Germany', 'France', 'UK');

 以下 SQL 语句选取不在“Germany”,“France”或“UK”中的所有客户:

代码示例:

SELECT * FROM CustomersWHERE Country NOT IN ('Germany', 'France', 'UK');

 以下 SQL 语句选取来自同一国家的所有客户作为供应商:

代码示例:

SELECT * FROM CustomersWHERE Country IN (SELECT Country FROM Suppliers);


SQL BETWEEN 运算符


 BETWEEN运算符用于选取介于两个值之间的数据范围内的值。

 BETWEEN运算符选择给定范围内的值。值可以是数字,文本或日期。

 BETWEEN运算符是包含性的:包括开始和结束值,且开始值需小于结束值。 

SQL BETWEEN 语法

SELECT column_name(s)FROM table_nameWHERE column_name BETWEEN value1 AND value2;

 要否定BETWEEN运算符的结果,可以添加NOT运算符:

SELECT column_name(s)FROM table_nameWHERE column_name NOT BETWEEN value1 AND value2;

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Products"表中的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning1248 - 6 oz jars22
5Chef Anton's Gumbo Mix1236 boxes21.35

BETWEEN 运算符实例


 以下SQL语句选择价格在10到20之间的所有产品:

实例

SELECT * FROM Products
WHERE Price BETWEEN 10 AND 20;


NOT BETWEEN 操作符实例

 要显示前面示例范围之外的产品,请使用NOT BETWEEN:

实例

SELECT * FROM Products
WHERE Price NOT BETWEEN 10 AND 20;

带有 IN 的 BETWEEN 操作符实例


 以下SQL语句选择价格在10到20之间但CategoryID不是1、2或3的所有产品:

实例

SELECT * FROM Products
WHERE (Price BETWEEN 10 AND 20)
AND NOT CategoryID IN (1,2,3);

带有文本值的 BETWEEN 操作符实例


 以下SQL语句选择所有带有ProductName BETWEEN'Carnarvon Tigers'和'Mozzarella di Giovanni'的产品:

实例

SELECT * FROM Products
WHERE ProductName BETWEEN 'Carnarvon Tigers' AND 'Mozzarella di Giovanni'
ORDER BY ProductName;

带有文本值的 NOT BETWEEN 操作符实例


 以下SQL语句选择ProductName不是BETWEEN'Carnarvon Tigers'和'Mozzarella di Giovanni'的所有产品:

实例

SELECT * FROM Products
WHERE ProductName NOT BETWEEN 'Carnarvon Tigers' AND 'Mozzarella di Giovanni'
ORDER BY ProductName;

示例表


 下面是选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
102489057/4/19963
102498167/5/19961
102503447/8/19962
102518437/9/19961
102527647/10/19962

带有日期值的 BETWEEN 操作符实例


 以下 SQL 语句选取 OrderDate 介于 '04-July-1996' 和 '09-July-1996' 之间的所有订单:

实例

SELECT * FROM Orders
WHERE OrderDate BETWEEN #07/04/1996# AND #07/09/1996#;

lamp

请注意,在不同的数据库中,BETWEEN 操作符会产生不同的结果!
在一些数据库中,BETWEEN 选取介于两个值之间但不包括两个测试值的字段。
在一些数据库中,BETWEEN 选取介于两个值之间且包括两个测试值的字段。
在一些数据库中,BETWEEN 选取介于两个值之间且包括第一个测试值但不包括最后一个测试值的字段。

因此,请检查您的数据库是如何处理 BETWEEN 操作符!


章节小测


 现在,通过以下题目测测看您对“SQL BETWEEN运算符”内容的掌握程度吧!

 SQL BETWEEN运算符:在本部分测验中,您将练习使用 SQL BETWEEN 运算符返回介于两个值之间的数据范围内的值。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>

SQL 通用数据类型


 数据类型定义了存储在列中的值的类型。


SQL 通用数据类型


 数据库表中的每一列都需要有一个名称和数据类型。

 SQL 开发人员必须在创建 SQL 表时决定表中的每个列将要存储的数据的类型。数据类型是一个标签,是便于 SQL 了解每个列期望存储什么类型的数据的指南,它也标识了 SQL 如何与存储的数据进行交互。

 下面的表格列出了 SQL 中通用的数据类型:

数据类型描述
CHARACTER(n)字符/字符串。固定长度 n。
VARCHAR(n) 或
CHARACTER VARYING(n)
字符/字符串。可变长度。最大长度 n。
BINARY(n)二进制串。固定长度 n。
BOOLEAN存储 TRUE 或 FALSE 值
VARBINARY(n) 或
BINARY VARYING(n)
二进制串。可变长度。最大长度 n。
INTEGER(p)整数值(没有小数点)。精度 p。
SMALLINT整数值(没有小数点)。精度 5。
INTEGER整数值(没有小数点)。精度 10。
BIGINT整数值(没有小数点)。精度 19。
DECIMAL(p,s)精确数值,精度 p,小数点后位数 s。例如:decimal(5,2) 是一个小数点前有 3 位数小数点后有 2 位数的数字。
NUMERIC(p,s)精确数值,精度 p,小数点后位数 s。(与 DECIMAL 相同)
FLOAT(p)近似数值,尾数精度 p。一个采用以 10 为基数的指数计数法的浮点数。该类型的 size 参数由一个指定最小精度的单一数字组成。
REAL近似数值,尾数精度 7。
FLOAT近似数值,尾数精度 16。
DOUBLE PRECISION近似数值,尾数精度 16。
DATE存储年、月、日的值。
TIME存储小时、分、秒的值。
TIMESTAMP存储年、月、日、小时、分、秒的值。
INTERVAL由一些整数字段组成,代表一段时间,取决于区间的类型。
ARRAY元素的固定长度的有序集合
MULTISET元素的可变长度的无序集合
XML存储 XML 数据

SQL 数据类型快速参考手册


 然而,不同的数据库为数据类型定义提供了不同的选择。
 下表显示了不同数据库平台上某些数据类型的通用名称:

数据类型AccessSQLServerOracleMySQLPostgreSQL
booleanYes/NoBitByteN/ABoolean
integerNumber (integer)IntNumberInt
Integer
Int
Integer
floatNumber (single)Float
Real
NumberFloatNumeric
currencyCurrencyMoneyN/AN/AMoney
string (fixed)N/ACharCharCharChar
string (variable)Text (<256)
Memo (65k+)
VarcharVarchar
Varchar2
VarcharVarchar
binary objectOLE Object MemoBinary (fixed up to 8K)
Varbinary (<8K)
Image (<2GB)
Long
Raw
Blob
Text
Binary
Varbinary

lamp

注释:在不同的数据库中,相同的数据类型可能有不同的名称。即使名字相同,大小和其他细节也可能不同!请随时检查文件!

来自 W3CSchool 的 SQL 快速参考


SQL 语句 语法
AND / OR SELECT column_name(s)
FROM table_name
WHERE condition
AND|OR condition
ALTER TABLE ALTER TABLE table_name
ADD column_name datatype

or

ALTER TABLE table_name
DROP COLUMN column_name

AS (alias) SELECT column_name AS column_alias
FROM table_name

or

SELECT column_name
FROM table_name AS table_alias

BETWEEN SELECT column_name(s)
FROM table_name
WHERE column_name
BETWEEN value1 AND value2
CREATE DATABASE CREATE DATABASE database_name
CREATE TABLE CREATE TABLE table_name
(
column_name1 data_type,
column_name2 data_type,
column_name2 data_type,
...
)
CREATE INDEX CREATE INDEX index_name
ON table_name (column_name)

or

CREATE UNIQUE INDEX index_name
ON table_name (column_name)

CREATE VIEW CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
DELETE DELETE FROM table_name
WHERE some_column=some_value

or

DELETE FROM table_name
(Note: Deletes the entire table!!)

DELETE * FROM table_name
(Note: Deletes the entire table!!)

DROP DATABASE DROP DATABASE database_name
DROP INDEX DROP INDEX table_name.index_name (SQL Server)
DROP INDEX index_name ON table_name (MS Access)
DROP INDEX index_name (DB2/Oracle)
ALTER TABLE table_name
DROP INDEX index_name (MySQL)
DROP TABLE DROP TABLE table_name
GROUP BY SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value
IN SELECT column_name(s)
FROM table_name
WHERE column_name
IN (value1,value2,..)
INSERT INTO INSERT INTO table_name
VALUES (value1, value2, value3,....)

or

INSERT INTO table_name
(column1, column2, column3,...)
VALUES (value1, value2, value3,....)

INNER JOIN SELECT column_name(s)
FROM table_name1
INNER JOIN table_name2
ON table_name1.column_name=table_name2.column_name
LEFT JOIN SELECT column_name(s)
FROM table_name1
LEFT JOIN table_name2
ON table_name1.column_name=table_name2.column_name
RIGHT JOIN SELECT column_name(s)
FROM table_name1
RIGHT JOIN table_name2
ON table_name1.column_name=table_name2.column_name
FULL JOIN SELECT column_name(s)
FROM table_name1
FULL JOIN table_name2
ON table_name1.column_name=table_name2.column_name
LIKE SELECT column_name(s)
FROM table_name
WHERE column_nameLIKE pattern
ORDER BY SELECT column_name(s)
FROM table_name
ORDER BY column_name [ASC|DESC]
SELECT SELECT column_name(s)
FROM table_name
SELECT * SELECT *
FROM table_name
SELECT DISTINCT SELECT DISTINCT column_name(s)
FROM table_name
SELECT INTO SELECT *
INTO new_table_name [IN externaldatabase]
FROM old_table_name

or

SELECT column_name(s)
INTO new_table_name [IN externaldatabase]
FROM old_table_name

SELECT TOP SELECT TOP number|percent column_name(s)
FROM table_name
TRUNCATE TABLE TRUNCATE TABLE table_name
UNION SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
UNION ALL SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2
UPDATE UPDATE table_name
SET column1=value, column2=value,...
WHERE some_column=some_value
WHERE SELECT column_name(s)
FROM table_name
WHERE column_name operator value


SQL 连接(Joins)


 SQL join 用于把来自两个或多个表的行结合起来。


SQL JOIN


 SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。

 简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上。

 最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN)。 SQL INNER JOIN 从多个表中返回满足 JOIN 条件的所有行。

 让我们看看选自 "Orders" 表的数据:

OrderIDCustomerIDOrderDate
1030821996-09-18
10309371996-09-19
10310771996-09-20

 然后,看看选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameCountry
1Alfreds FutterkisteMaria AndersGermany
2Ana Trujillo Emparedados y heladosAna TrujilloMexico
3Antonio Moreno TaqueríaAntonio MorenoMexico

 请注意,"Orders" 表中的 "CustomerID" 列指向 "Customers" 表中的客户。上面这两个表是通过 "CustomerID" 列联系起来的。

 然后,如果我们运行下面的 SQL 语句(包含 INNER JOIN):

实例

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;

 运行结果如下所示:

OrderIDCustomerNameOrderDate
10308Ana Trujillo Emparedados y helados1996-09-18

不同的 SQL JOIN


 在我们继续讲解实例之前,我们先列出您可以使用的不同的 SQL JOIN 类型:

  • INNER JOIN:如果表中有至少一个匹配,则返回行
  • LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN:只要其中一个表中存在匹配,则返回行
  • SELF JOIN:用于将表连接到自己,就好像该表是两个表一样,临时重命名了SQL语句中的至少一个表
  • CARTESIAN JOIN:从两个或多个连接表返回记录集的笛卡儿积 


SQL INNER JOIN 关键字(内部连接)


 内部链接INNER JOIN关键字选择两个表中具有匹配值的记录。

SQL INNER JOIN 语法

SELECT column_name(s)FROM table1INNER JOIN table2 ON table1.column_name = table2.column_name;

 注释:INNER JOIN 与 JOIN 是相同的。

SQL INNER JOIN


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
103093731996-09-191
103107781996-09-202

SQL INNER JOIN 实例


 以下SQL语句将返回所有下订单的客户:

实例

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
ORDER BY Customers.CustomerName;

注释:如果表中至少有一个匹配项,INNER JOIN 关键字将返回一行。如果 "Customers" 表中的行与"Orders" 不匹配,则不会列出行。


加入三张表


 以下SQL语句选择包含客户和货运单信息的所有订单:

 代码示例:

SELECT Orders.OrderID, Customers.CustomerName, Shippers.ShipperNameFROM ((OrdersINNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID)INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID);


SQL 左连接 LEFT JOIN 关键字


 SQL左链接LEFT JOIN关键字返回左表(表1)中的所有行,即使在右表(表2)中没有匹配。如果在正确的表中没有匹配,结果是NULL。

SQL LEFT JOIN 语法

SELECT column_name(s)                FROM table1                LEFT JOIN table2                ON table1.column_name=table2.column_name;       

 或:

SELECT column_name(s)                FROM table1                LEFT OUTER JOIN table2                ON table1.column_name=table2.column_name;      

注释:在一些数据库中,LEFT JOIN称为LEFT OUT ER JOIN。

SQL LEFT JOIN


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
103093731996-09-191
103107781996-09-202

SQL LEFT JOIN 实例


 以下SQL语句将选择所有客户以及他们可能拥有的任何订单:

实例

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
ORDER BY Customers.CustomerName;

注释:LEFT JOIN 关键字返回左表(Customers)中的所有行,即使在右边表(Orders)中没有匹配。


SQL右连接 RIGHT JOIN 关键字


 SQL右链接 RIGHT JOIN 关键字返回右表(table2)的所有行,即使在左表(table1)上没有匹配。如果左表没有匹配,则结果为NULL。

SQL RIGHT JOIN 语法

SELECT column_name(s)FROM table1RIGHT JOIN table2 ON table1.column_name = table2.column_name;

注释:在一些数据库中,RIGHT JOIN 称为 RIGHT OUTER JOIN。

SQL RIGHT JOIN



演示数据库

 在本教程中,我们将使用着名的Northwind示例数据库。

 以下是"Orders"表中的一个选项:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
103093731996-09-191
103107781996-09-202

 并从"Employees" t表中选择:

EmployeeIDLastNameFirstNameBirthDatePhoto
1DavolioNancy12/8/1968EmpID1.pic
2FullerAndrew2/19/1952EmpID2.pic
3LeverlingJanet8/30/1963EmpID3.pic

SQL RIGHT JOIN 实例


 以下SQL语句将返回所有雇员以及他们可能已经放置的任何订单:

实例

SELECT Orders.OrderID, Employees.LastName, Employees.FirstName
FROM Orders
RIGHT JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID
ORDER BY Orders.OrderID;

注释:RIGHT JOIN 关键字返回右表(Employees)的所有行,即使在左表(Orders)中没有匹配。


SQL FULL OUTER JOIN 关键字


 当左(表1)或右(表2)表记录匹配时,FULL OUTER JOIN关键字将返回所有记录。

 注意: FULL OUTER JOIN可能会返回非常大的结果集!

SQL FULL OUTER JOIN 语法

SELECT column_name(s)FROM table1FULL OUTER JOIN table2 ON table1.column_name = table2.column_name;

SQL FULL OUTER JOIN


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
10309331996-09-191
103107781996-09-202

SQL FULL OUTER JOIN 实例


 以下SQL语句选择所有客户和所有订单:

SELECT Customers.CustomerName, Orders.OrderIDFROM CustomersFULL OUTER JOIN Orders ON Customers.CustomerID=Orders.CustomerIDORDER BY Customers.CustomerName;

 从这套结果中选择的数据如下:

CustomerNameOrderID
Alfreds Futterkiste 
Ana Trujillo Emparedados y helados10308
Antonio Moreno Taquería10309
 10310

注意: FULL OUTER JOIN关键字返回左表(Customers)中的所有行,以及右表(Orders)中的所有行。如果 "Customers"中的行中没有"Orders"中的匹配项,或者"Orders"中的行中没有 "Customers"中的匹配项,那么这些行也会列出。


SQL自连接


 自联接是一种常规联接,但表本身是连接的。

Self JOIN语法

SELECT column_name(s)FROM table1 T1, table1 T2WHERE condition;

演示数据库


 在本教程中,我们将使用着名的Northwind示例数据库。

 以下是"Customers"表中的选择:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

SQL Self JOIN示例


 以下SQL语句匹配来自同一城市的客户:

代码示例

SELECT A.CustomerName AS CustomerName1, B.CustomerName AS CustomerName2, A.CityFROM Customers A, Customers BWHERE A.CustomerID <> B.CustomerIDAND A.City = B.City ORDER BY A.City;


SQL UNION 运算符


  UNION运算符用于组合两个或更多SELECT语句的结果集,而不返回任何重复的行。

  • UNION中的每个SELECT语句必须具有相同的列数
  • 这些列也必须具有相似的数据类型
  • 每个SELECT语句中的列也必须以相同的顺序排列
  • 每个SELECT语句必须有相同数目的列表达式
  • 但是每个SELECT语句的长度不必相同

SQL UNION 语法1

SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2;

注释:默认情况下,UNION 运算符选择一个不同的值。如果允许重复值,请使用 UNION ALL。

SQL UNION 语法2

SELECT column_name(s) FROM table1[WHERE condition]UNIONSELECT column_name(s) FROM table2[WHERE condition];

 给定的条件可以是基于您的需求的任何给定表达式。

SQL UNION ALL 语法1

 UNION All运算符用于组合两个SELECT语句(包括重复行)的结果。

 适用于UNION子句的相同规则将适用于UNION All操作符。

SELECT column_name(s) FROM table1UNION ALLSELECT column_name(s) FROM table2;

注释:UNION结果集中的列名总是等于UNION中第一个SELECT语句中的列名。

SQL UNION ALL 语法2

SELECT column_name(s) FROM table1[WHERE condition]UNION ALLSELECT column_name(s) FROM table2[WHERE condition];


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Suppliers" 表的数据:

SupplierIDSupplierNameContactNameAddressCityPostalCodeCountry
1Exotic LiquidCharlotte Cooper49 Gilbert St.LondonaEC1 4SDUK
2New Orleans Cajun DelightsShelley BurkeP.O. Box 78934New Orleans70117USA
3Grandma Kelly's HomesteadRegina Murphy707 Oxford Rd.Ann Arbor48104USA


SQL UNION 实例

 下面的 SQL 语句从 "Customers" 和 "Suppliers" 表中选取所有不同的城市(只有不同的值):

实例

SELECT City FROM Customers
UNION
SELECT City FROM Suppliers
ORDER BY City;

注释:不能用 UNION 来列出两个表中的所有城市。如果一些客户和供应商来自同一个城市,每个城市将只被列入一个列表。UNION将只选择不同的值。请使用UNION ALL选择重复值!


SQL UNION ALL 实例


 以下SQL语句使用 UNION ALL 从 "Customers"和"Suppliers" 表中选择所有城市(也是重复的值):

实例

SELECT City FROM Customers
UNION ALL
SELECT City FROM Suppliers
ORDER BY City;

带有 WHERE 的 SQL UNION ALL


 以下SQL语句使用UNIONALL从"Customers"和 "Suppliers" 表中选择所有德国城市(也是重复数值):

实例

SELECT City, Country FROM Customers
WHERE Country='Germany'
UNION ALL
SELECT City, Country FROM Suppliers
WHERE Country='Germany'
ORDER BY City;

SQL UNION与WHERE


 以下SQL语句从“客户”和“供应商”中选择所有不同的德国城市(只有不同​​的值):

SELECT City, Country FROM CustomersWHERE Country='Germany'UNIONSELECT City, Country FROM SuppliersWHERE Country='Germany'ORDER BY City;

另一个UNION示例


 以下SQL语句列出了所有客户和供应商:

SELECT 'Customer' As Type, ContactName, City, CountryFROM CustomersUNIONSELECT 'Supplier', ContactName, City, CountryFROM Suppliers;

 还有另外两个子句(即运算符),它们类似于UNION子句:

  • SQL INTERSECT子句
    用于组合两个SELECT语句,但只返回与第二个SELECT语句中的一行相同的第一个SELECT语句中的行。
  • SQL EXCEPT子句
    用于组合两个SELECT语句,并返回第一个SELECT语句中没有由第二个SELECT语句返回的行。


章节小测


 现在,通过以下题目测测看您对“SQL UNION 运算符”内容的掌握程度吧!

 SQL UNION 操作符:在本部分测验中,您将练习使用 SQL UNION 操作符将多个表的数据合并为一个综合数据集。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL SELECT INTO 语句


 使用 SQL,您可以将信息从一个表中复制到另一个表中。

 SELECT INTO 语句从一个表中复制数据,然后将数据插入到另一个新表中。

SQL SELECT INTO 语法

 我们可以把所有的列都复制到新表中:

SELECT *INTO newtable [IN externaldb]FROM table1;

 或者只复制希望的列插入到新表中:

SELECT column_name(s)INTO newtable [IN externaldb]FROM table1;

lamp

提示:将使用SELECT语句中定义的列名和类型创建新表。您可以使用AS子句来应用一个新名称。


SQL SELECT INTO 实例


 创建 Customers 的备份复件:

SELECT *INTO CustomersBackup2013FROM Customers;

 请使用 IN 子句来复制表到另一个数据库中:

SELECT *INTO CustomersBackup2013 IN 'Backup.mdb'FROM Customers;

 只复制一些列插入到新表中:

SELECT CustomerName,ContactNameINTO CustomersBackup2013FROM Customers;

 只复制德国的客户插入到新表中:

SELECT *INTO CustomersBackup2013FROM CustomersWHERE Country='Germany';

 复制多个表中的数据插入到新表中:

SELECT Customers.CustomerName, Orders.OrderIDINTO CustomersOrderBackup2013FROM CustomersLEFT JOIN OrdersON Customers.CustomerID=Orders.CustomerID;

 提示:SELECT INTO 语句可以用于在另一种模式下创建一个新的空表。只需添加WHERE子句,使查询返回时没有数据:

SELECT *INTO newtableFROM table1WHERE 1=0;


SQL INSERT INTO SELECT 语句


 使用SQL,您可以将信息从一个表中复制到另一个表中。

 INSERT INTO SELECT 语句从表中复制数据,并将数据插入现有的表中。目标表中的任何现有行都不会受到影响。

SQL INSERT INTO SELECT 语法

 我们可以将所有列从一个表中复制到另一个已经存在的表中:

INSERT INTO table2              SELECT * FROM table1;    

 或者我们可以把想要的列复制到另一个现有的表中:

INSERT INTO table2               (column_name(s))              SELECT column_name(s)             FROM table1;   

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers"表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Suppliers" 表的数据:

SupplierIDSupplierNameContactNameAddressCityPostal CodeCountryPhone
1Exotic LiquidCharlotte Cooper49 Gilbert St.LondonaEC1 4SDUK(171) 555-2222
2New Orleans Cajun DelightsShelley BurkeP.O. Box 78934New Orleans70117USA(100) 555-4822
3Grandma Kelly's HomesteadRegina Murphy707 Oxford Rd.Ann Arbor48104USA(313) 555-5735

SQL INSERT INTO SELECT 实例


 把 "Suppliers" 一栏复制到 "Customers" 一栏:

实例

INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country FROM Suppliers;

 只将德国供应商的副本插入 "Customers" :

实例

INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country FROM Suppliers
WHERE Country='Germany';


SQL 撤销索引、撤销表以及撤销数据库


 通过使用 DROP 语句,可以轻松地删除索引、表和数据库。


DROP INDEX 语句


 DROP INDEX 语句用于删除表中的索引。

用于 MS Access 的 DROP INDEX 语法:

DROP INDEX index_name ON table_name      

用于 MS SQL Server 的 DROP INDEX 语法:

DROP INDEX table_name.index_name     

用于 DB2/Oracle 的 DROP INDEX 语法:

DROP INDEX index_name   

用于 MySQL 的 DROP INDEX 语法:

ALTER TABLE table_name DROP INDEX index_name       

DROP TABLE 语句


 DROP TABLE 语句用于删除表。

DROP TABLE table_name      

DROP DATABASE 语句


 DROP DATABASE 语句用于删除数据库。

DROP DATABASE database_name    

TRUNCATE TABLE 语句


 如果我们只需要删除表中的数据,而不删除表本身,那么我们该怎么做?

 使用TRUNCATE TABLE语句:

TRUNCATE TABLE table_name   


章节小测


 现在,通过以下题目测测看您对本章节内容的掌握程度吧!

 SQL DROP TABLE:在本部分测验中,您将练习使用 SQL 语句来删除表中的数据。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL CREATE DATABASE 语句


 CREATE DATABASE 语句用于创建数据库。

 在RDBMS中,数据库名称始终应该是唯一的。

SQL CREATE DATABASE 语法

CREATE DATABASE dbname;

 在创建任何数据库之前,请确保您拥有管理权限。


SQL CREATE DATABASE 实例


 下面的 SQL 语句创建一个名为 "my_db" 的数据库:

CREATE DATABASE my_db;

 数据库表可以通过 CREATE TABLE 语句来添加。

 创建数据库后,您可以在数据库列表中检查它。

 语句:

SHOW DATABASES;

SQL CREATE TABLE 语句


SQL CREATE TABLE 语句

 CREATE TABLE 语句用于创建数据库中的表。

 表由行和列组成,每个表都必须有个表名。

SQL CREATE TABLE 语法

CREATE TABLE table_name                (                column_name1 data_type(size),                column_name2 data_type(size),                column_name3 data_type(size),                ....                );       

 column_name 参数规定表中列的名称。

 data_type 参数规定列的数据类型(例如 varchar、integer、decimal、date 等等)。

 size 参数规定表中列的最大长度。

 提示:如需了解 MS Access、MySQL 和 SQL Server 中可用的数据类型,请访问我们完整的 数据类型参考手册


SQL CREATE TABLE 实例

 现在我们想要创建一个名为 "Persons" 的表,包含五列:PersonID、LastName、FirstName、Address 和 City。

 我们使用下面的 CREATE TABLE 语句:

实例

CREATE TABLE Persons
(
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);

 PersonID列数据类型为int,包含一个整数。

 LastName、FirstName、Address和City列具有包含字符的varchar数据类型,这些字段的最大长度为255个字符。

 空 "Persons" 表是这样的:

PersonIDLastNameFirstNameAddressCity
     

 提示:使用 INSERT INTO 语句将数据写入空表。


章节小测


 现在,通过以下题目测测看您对“SQL CREATE TABLE 语句”内容的掌握程度吧!

 SQL CREATE TABLE:在本部分测验中,您将练习使用 SQL CREATE TABLE 语句创建数据库中的表,创建时请注意语法。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费



SQL ALTER TABLE 语句


ALTER TABLE 语句

 ALTER TABLE 语句用于在现有表中添加、删除或修改列。

SQL ALTER TABLE 语法

 若要向表中添加列,请使用以下语法:

ALTER TABLE table_name                ADD column_name datatype      

 若要删除表中的列,请使用以下语法(请注意,一些数据库系统不允许这样删除数据库表中的列):

ALTER TABLE table_name                DROP COLUMN column_name      

 若要更改表中列的数据类型,请使用以下语法:

SQL Server / MS Access:

ALTER TABLE table_name                ALTER COLUMN column_name datatype       

My SQL / Oracle:

ALTER TABLE table_name                MODIFY COLUMN column_name datatype        


SQL ALTER TABLE 实例

 请看 "Persons" 表:

P_IdLastNameFirstNameAddressCity
1HansenOlaTimoteivn 10Sandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStorgt 20Stavanger

 现在,我们想在 "Persons" 表中添加一个名为 "DateOfBirth" 的列。

 我们使用下面的 SQL 语句:

ALTER TABLE Persons                ADD DateOfBirth date       

 请注意,新列 "DateOfBirth" 的类型是 date,可以存放日期。数据类型规定列中可以存放的数据的类型。如需了解 MS Access、MySQL 和 SQL Server 中可用的数据类型,请访问我们完整的 数据类型参考手册

 现在,"Persons" 表将如下所示:

P_IdLastNameFirstNameAddressCityDateOfBirth
1HansenOlaTimoteivn 10Sandnes 
2SvendsonToveBorgvn 23Sandnes 
3PettersenKariStorgt 20Stavanger 


改变数据类型实例

 现在,我们想要改变 "Persons" 表中 "DateOfBirth" 列的数据类型。

 我们使用下面的 SQL 语句:

ALTER TABLE Persons                ALTER COLUMN DateOfBirth year      

 请注意,现在 "DateOfBirth" 列的类型是 year,可以存放 2 位或 4 位格式的年份。


DROP COLUMN 实例

 接下来,我们想要删除 "Person" 表中的 "DateOfBirth" 列。

 我们使用下面的 SQL 语句:

ALTER TABLE Persons                DROP COLUMN DateOfBirth        

 现在,"Persons" 表将如下所示:

P_IdLastNameFirstNameAddressCity
1HansenOlaTimoteivn 10Sandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStorgt 20Stavanger

章节小测


 现在,通过以下题目测测看您对本章节内容的掌握程度吧!

 SQL ALTER TABLE:在本部分测验中,您将练习使用 SQL ALTER TABLE 语句在已有的表中添加、删除或修改列。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

SQL AUTO INCREMENT 字段


 Auto-increment 会在新记录插入表中时生成一个唯一的数字。


AUTO INCREMENT 字段


 我们通常希望在每次插入新记录时自动创建主键字段的值。

 我们可以在表中创建一个自动增量(auto-increment)字段。


用于 MySQL 的语法


 以下SQL语句将 "Persons" 表中的“ID”列定义为自动递增(auto-increment)主键字段:

CREATE TABLE Persons                (                ID int NOT NULL AUTO_INCREMENT,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                PRIMARY KEY (ID)                )

 MySQL使用AUTO_INCREMENT关键字来执行自动增量( auto-increment )任务。 

 默认情况下,AUTO_INCREMENT的起始值为1,每个新记录增加1。

 若要以其他值开始AUTO_INCREMENT序列,请使用以下SQL语法:

ALTER TABLE Persons AUTO_INCREMENT=100       

 要在 "Persons" 表中插入新记录,我们不需要为"ID"栏指定值(自动添加唯一值):

INSERT INTO Persons (FirstName,LastName)                VALUES ('Lars','Monsen')        

 上面的SQL语句在 "Persons" 表中插入一个新记录。“ID”栏将得到唯一值。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


用于 SQL Server 的语法


 以下SQL语句将 "Persons" 表中的“ID”列定义为自动递增( auto-increment )主键字段:

CREATE TABLE Persons                (                ID int IDENTITY(1,1) PRIMARY KEY,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )       

 MS SQL Server使用IDENTITY关键字执行自动增量( auto-increment )任务。

 在上面的示例中,IDENTITY的起始值为1,每个新记录增量为1。

 提示:指定“ID”列以10开头,并递增5,将标识( identity )更改为IDENTITY(10,5)。

 要在 "Persons" 表中插入新记录,我们不需要为"ID"栏指定值(自动添加唯一值):

INSERT INTO Persons (FirstName,LastName)                VALUES ('Lars','Monsen')        

 上面的 SQL 语句在 "Persons" 表中插入一个新记录。“ID”栏将得到唯一值。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


用于 Access 的语法


 以下 SQL 语句将 "Persons" 表中的“ID”列定义为自动递增( auto-increment )主键字段:

CREATE TABLE Persons                (                ID Integer PRIMARY KEY AUTOINCREMENT,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )       

 MS Access使用 AUTOINCREMENT 关键字执行自动增量( auto-increment )任务。

 默认情况下,AUTOINCREMENT的起始值为1,每个新记录递增 1。

 提示:指定“ID”栏以10开头,并递增5,将自动递增( autoincrement )更改为自动递增(105)( AUTOINCREMENT(10,5))。

 要在 "Persons" 表中插入新记录,我们不需要为"ID"栏指定值(自动添加唯一值):

INSERT INTO Persons (FirstName,LastName)                VALUES ('Lars','Monsen')        

 上面的 SQL 语句在 "Persons" 表中插入一个新记录。“ID”栏将得到唯一值。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


语法 for Oracle


 在 Oracle 中,代码有点复杂。

 您必须使用序列( sequence )对象(该对象生成数字序列)创建自动增量( auto-increment )字段。

 使用以下CREATSEQUENT语法:

CREATE SEQUENCE seq_person                MINVALUE 1                START WITH 1                INCREMENT BY 1                CACHE 10        

 上面的代码创建了一个名为seq_pean的序列( sequence) 对象,它以1开头,以1递增。此对象缓存10个值以提高性能。缓存选项指定要存储多少序列值以提高访问速度。

 要在"Persons" 表中插入新记录,我们必须使用nextval函数,该函数从seq_hor序列检索下一个值:

INSERT INTO Persons (ID,FirstName,LastName)                VALUES (seq_person.nextval,'Lars','Monsen')       

 上面的SQL语句在 "Persons" 表中插入一个新记录。"ID" 列从 seq_person 序列中分配下一个数字。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


章节小测


 现在,通过以下题目测测看您对“SQL AUTO INCREMENT 字段”内容的掌握程度吧!

 SQL 自动递增(AUTO INCREMENT):在本部分测验中,您将练习使用 SQL 语句来在新记录插入表中时生成一个唯一的数字。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

SQL 视图(Views)


 视图是可视化的表。

 本章讲解如何创建、更新和删除视图。


SQL CREATE VIEW 语句


 在 SQL 中,视图是基于 SQL 语句的结果集的可视化表。

 视图包含行和列,就像真正的表一样。视图中的字段是一个或多个数据库中真实表中的字段。

 您可以添加 SQL 函数,在哪里添加,并将语句连接到视图,或者您可以呈现数据,就像数据来自单个表一样。


SQL CREATE VIEW 语法

CREATE VIEW view_name AS                SELECT column_name(s)                FROM table_name                WHERE condition      

 注释:视图总是显示最新数据!每当用户查询视图时,数据库引擎就使用视图的 SQL 语句重新构建数据。


SQL CREATE VIEW 实例


 示例数据库 Northwind 默认安装了一些视图。

 "Current Product List"(当前产品列表)视图从"Products"表中列出了所有正在使用的产品(未停产的产品)。这个视图使用下面的 SQL 创建:

CREATE VIEW [Current Product List] AS                SELECT ProductID,ProductName                FROM Products                WHERE Discontinued=No      

 我们可以像这样查询上面这个视图:

SELECT * FROM [Current Product List]        

 Northwind 样本数据库的另一个视图会选取 "Products" 表中所有单位价格高于平均单位价格的产品:

CREATE VIEW [Products Above Average Price] AS                SELECT ProductName,UnitPrice                FROM Products                WHERE UnitPrice>(SELECT AVG(UnitPrice) FROM Products)     

 我们可以像这样查询上面这个视图:

SELECT * FROM [Products Above Average Price]        

 Northwind 样本数据库的另一个视图会计算在 1997 年每个种类的销售总数。请注意,这个视图会从另一个名为 "Product Sales for 1997" 的视图那里选取数据:

CREATE VIEW [Category Sales For 1997] AS                SELECT DISTINCT CategoryName,Sum(ProductSales) AS CategorySales                FROM [Product Sales for 1997]                GROUP BY CategoryName       

 我们可以像这样查询上面这个视图:

SELECT * FROM [Category Sales For 1997]       

 我们也可以向查询添加条件。现在,我们仅仅需要查看 "Beverages" 类的销售总数:

SELECT * FROM [Category Sales For 1997]                WHERE CategoryName='Beverages'        

SQL 更新视图


 您可以使用下面的语法来更新视图:

SQL CREATE OR REPLACE VIEW 语法

CREATE OR REPLACE VIEW view_name AS                SELECT column_name(s)                FROM table_name                WHERE condition        

 现在,我们希望向 "Current Product List" 视图添加 "Category" 列。我们将通过下列 SQL 更新视图:

CREATE OR REPLACE VIEW [Current Product List] AS                SELECT ProductID,ProductName,Category                FROM Products                WHERE Discontinued=No        

SQL 撤销视图


 您可以通过 DROP VIEW 命令来删除视图。

SQL DROP VIEW 语法

DROP VIEW view_name     


SQL Date 函数


注意:当我们处理日期时,最困难的任务可能是确保插入日期的格式与数据库中日期列中的格式相匹配。

 只要您的数据仅包含日期的一部分,运行查询就不会成为问题。然而,当涉及到时间时,情况会稍微复杂一些。

 在讨论日期查询的复杂性之前,让我们看看最重要的内置日期处理程序。


MySQL Date 函数


 下表列出了 MySQL 中最重要的内置日期函数:

函数描述
NOW()返回当前的日期和时间
CURDATE()返回当前的日期
CURTIME()返回当前的时间
DATE()提取日期或日期/时间表达式的日期部分
EXTRACT()返回日期/时间的单独部分
DATE_ADD()向日期添加指定的时间间隔
DATE_SUB()从日期减去指定的时间间隔
DATEDIFF()返回两个日期之间的天数
DATE_FORMAT()用不同的格式显示日期/时间

SQL Server Date 函数


 下表列出了SQL 服务器中最重要的内置日期函数:

函数描述
GETDATE()返回当前的日期和时间
DATEPART()返回日期/时间的单独部分
DATEADD()在日期中添加或减去指定的时间间隔
DATEDIFF()返回两个日期之间的时间
CONVERT()用不同的格式显示日期/时间

SQL Date 数据类型


 MySQL 使用下列数据类型在数据库中存储日期或时间值:

  • DATE - 格式:YYYY-MM-DD
  • DATETIME - 格式:YYYY-MM-DD HH:MM:SS
  • TIMESTAMP - 格式:YYYY-MM-DD HH:MM:SS
  • YEAR - 格式:YYYY 或 YY

 SQL Server 使用下列数据类型在数据库中存储日期或时间值:

  • DATE - 格式:YYYY-MM-DD
  • DATETIME - 格式:YYYY-MM-DD HH:MM:SS
  • SMALLDATETIME - 格式:YYYY-MM-DD HH:MM:SS
  • TIMESTAMP - 格式:唯一的数字

 注释:在数据库中创建新表时,需要为该列选择数据类型!

 如需了解所有可用的数据类型,请访问我们完整的 数据类型参考手册


SQL 日期处理


 Note注意:如果您不涉及时间部分,那么我们可以轻松比较两个日期!

 假设我们有以下“订单”表:

OrderIdProductNameOrderDate
1Geitost2008-11-11
2Camembert Pierrot2008-11-09
3Mozzarella di Giovanni2008-11-11
4Mascarpone Fabioli2008-10-29

 现在,我们希望从上表中选取 OrderDate 为 "2008-11-11" 的记录。

 我们使用下面的 SELECT 语句:

SELECT * FROM Orders WHERE OrderDate='2008-11-11'   

 结果集如下所示:

OrderIdProductNameOrderDate
1Geitost2008-11-11
3Mozzarella di Giovanni2008-11-11

 现在,假设 "Orders" 表如下所示(请注意 "OrderDate" 列中的时间部分):

OrderIdProductNameOrderDate
1Geitost2008-11-11 13:23:44
2Camembert Pierrot2008-11-09 15:45:21
3Mozzarella di Giovanni2008-11-11 11:12:01
4Mascarpone Fabioli2008-10-29 14:56:59

 如果我们使用和上面一样的 SELECT 语句:

SELECT * FROM Orders WHERE OrderDate='2008-11-11'   

 这样我们就不会有结果了!这是因为查询的日期不包含时间部分。

提示:如果您想使查询更加简单和易于维护,请不要使用日期中的时间部分!

SQL NULL 值


 NULL 空值代表丢失的未知数据。

 默认情况下,表列可以保存 NULL 值。

 本章解释 IS NULL 和 IS NOT NULL 操作符。


SQL NULL 值


 如果表中的列是可选的,那么我们可以插入一个新记录或更新一个现有记录,而无需向列添加一个值。这意味着该字段将存储为 NULL 。

 NULL 值的处理与其他值不同。

 NULL 为未知或不适当值的占位符。

 Note注释:无法比较 NULL 和 0;它们是不等价的。


SQL 的 NULL 值处理


 请看下面的 "Persons" 表:

P_IdLastNameFirstNameAddressCity
1HansenOlaSandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStavanger

 如果 "Persons" 表 "Address" 一栏是可选的。这意味着,如果在 "Address" 列中插入一个没有值的记录,则 "Address" 列将用 NULL 值保存。

 那么如何测试null的值呢?

 您不能使用比较操作符测试 NULL 值,例如=、<或<>。

 我们必须使用 IS NULL 和 IS NOT NULL 操作符。


SQL IS NULL


 我们如何才能选择 "Address" 列中有 NULL 值的记录?

 我们必须使用 IS NULL 操作符:

SELECT LastName,FirstName,Address FROM PersonsWHERE Address IS NULL

 结果集如下所示:

LastNameFirstNameAddress
HansenOla
PettersenKari

 Note提示:总是使用 IS NULL 来查找 NULL 值。


SQL IS NOT NULL


 我们如何才能选择 "Address" 列中没有 NULL 值的记录?

 我们必须使用 IS NOT NULL 操作符:

SELECT LastName,FirstName,Address FROM PersonsWHERE Address IS NOT NULL

 结果集如下所示:

LastNameFirstNameAddress
SvendsonToveBorgvn 23

 在下一节中,我们将了解 ISNULL()、NVL()、IFNULL() 和 COALESCE() 函数。


SQL 别名(Aliases)


 通过使用 SQL,可以为表名称或列名称指定别名(Alias)。

  • SQL 别名用于为表或表中的列提供临时名称,数据库中的实际表名不会更改。
  • SQL 别名通常用于使列名更具可读性。
  • SQL 一个别名只存在于查询期间。
  • 表别名的使用是在特定SQL语句中重命名表。
  • 列别名用于为特定SQL查询重命名表的列。

列的 SQL Alias 语法

SELECT column_name AS alias_name
FROM table_name;
WHERE [condition];

表的 SQL Alias 语法

SELECT column_name(s)FROM table_name AS alias_name;WHERE [condition];

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK

 下面是选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
103545881996-11-143
10355461996-11-151
103568661996-11-182

列的 Alias 实例


 以下SQL语句创建两个别名,一个用于CustomerID列,另一个用于CustomerName列:

实例

SELECT CustomerID as ID, CustomerName AS Customer
FROM Customers;

 以下SQL语句创建两个别名,一个用于CustomerName列,一个用于ContactName列。注:如果别名包含空格,则需要双引号或方括号:

实例

SELECT CustomerName AS Customer, ContactName AS [Contact Person]
FROM Customers;

 以下SQL语句创建一个名为“Address”的别名,它包含四列(Address,PostalCode,City and Country):

SELECT CustomerName, Address + ', ' + PostalCode + ', ' + City + ', ' + Country AS AddressFROM Customers;

 注意:要使上面的SQL语句在MySQL中工作,请使用以下命令:

SELECT CustomerName, CONCAT(Address,', ',PostalCode,', ',City,', ',Country) AS AddressFROM Customers;

表的 Alias 实例


 以下SQL语句选择CustomerID = 4(“围绕角”)的所有订单。我们使用“Customers”和“Orders”表,给它们分别为“c”和“o”的表别名(这里我们使用别名来使SQL更短):

实例

SELECT o.OrderID, o.OrderDate, c.CustomerName
FROM Customers AS c, Orders AS o
WHERE c.CustomerName="Around the Horn" AND c.CustomerID=o.CustomerID;

 以下SQL语句与上述相同,但没有别名:

实例

SELECT Orders.OrderID, Orders.OrderDate, Customers.CustomerName
FROM Customers, Orders
WHERE Customers.CustomerName="Around the Horn" AND Customers.CustomerID=Orders.CustomerID;

 在下列情况下使用别名是有用的:

  • 查询涉及多个表

  • 用于查询函数

  • 需要把两个或更多的列放在一起

  • 列名长或可读性差


示例


 考虑下面两个数据表:

 (a)CUSTOMERS 表,如下:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)另一个是 ORDERS 表,如下所示:

+-----+---------------------+-------------+--------+|OID  | DATE                | CUSTOMER_ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 下面是表别名的用法:

SQL> SELECT C.ID, C.NAME, C.AGE, O.AMOUNT         FROM CUSTOMERS AS C, ORDERS AS O        WHERE  C.ID = O.CUSTOMER_ID;

 上面语句的运行结果如下所示:

+----+----------+-----+--------+| ID | NAME     | AGE | AMOUNT |+----+----------+-----+--------+|  3 | kaushik  |  23 |   3000 ||  3 | kaushik  |  23 |   1500 ||  2 | Khilan   |  25 |   1560 ||  4 | Chaitali |  25 |   2060 |+----+----------+-----+--------+

 下面是列别名的用法:

SQL> SELECT  ID AS CUSTOMER_ID, NAME AS CUSTOMER_NAME     FROM CUSTOMERS     WHERE SALARY IS NOT NULL;

 其运行结果如下所示:

+-------------+---------------+| CUSTOMER_ID | CUSTOMER_NAME |+-------------+---------------+|           1 | Ramesh        ||           2 | Khilan        ||           3 | kaushik       ||           4 | Chaitali      ||           5 | Hardik        ||           6 | Komal         ||           7 | Muffy         |+-------------+---------------+


 SQL约束用于指定表中数据的规则。

SQL 约束


 约束是作用于数据表中列上的规则,用于限制表中数据的类型。约束的存在保证了数据库中数据的精确性和可靠性。

 约束有列级和表级之分,列级约束作用于单一的列,而表级约束作用于整张数据表。

 下面是 SQL 中常用的约束,这些约束虽然已经在关系型数据库管理系统一章中讨论过了,但是仍然值得在这里回顾一遍。

 约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。


SQL创建约束


 当使用CREATE TABLE语句创建表时,或者在使用ALTER TABLE语句创建表之后,可以指定约束。

 语法

CREATE TABLE table_name (    column1 datatype constraint,    column2 datatype constraint,    column3 datatype constraint,    ....);

SQL CREATE TABLE + CONSTRAINT 语法

CREATE TABLE table_name                (                column_name1 data_type(size) constraint_name,                column_name2 data_type(size) constraint_name,                column_name3 data_type(size) constraint_name,                ....                );      

删除约束


 任何现有约束都可以通过在 ALTER TABLE 命令中指定 DROP CONSTRAINT 选项的方法删除掉。

 例如,要去除 EMPLOYEES 表中的主键约束,可以使用下述命令:

ALTER TABLE EMPLOYEES DROP CONSTRAINT EMPLOYEES_PK;

 一些数据库实现可能提供了删除特定约束的快捷方法。例如,要在 Oracle 中删除一张表的主键约束,可以使用如下命令:

ALTER TABLE EMPLOYEES DROP PRIMARY KEY;

 某些数据库实现允许禁用约束。这样与其从数据库中永久删除约束,你可以只是临时禁用掉它,过一段时间后再重新启用。


完整性约束


 完整性约束用于保证关系型数据库中数据的精确性和一致性。对于关系型数据库来说,数据完整性由参照完整性(referential integrity,RI)来保证。

 有很多种约束可以起到参照完整性的作用,这些约束包括主键约束(Primary Key)、外键约束(Foreign Key)、唯一性约束(Unique Constraint)以及上面提到的其他约束。


SQL NOT NULL 约束


 在默认的情况下,表的列接受 NULL 值。

 NOT NULL 约束强制列不接受 NULL 值。

 NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。

 下面的 SQL 强制 "P_Id" 列和 "LastName" 列不接受 NULL 值:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255))


SQL UNIQUE 约束


 UNIQUE 约束唯一标识数据库表中的每条记录。

 UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。

 PRIMARY KEY 约束拥有自动定义的 UNIQUE 约束。

 请注意,每个表可以有多个 UNIQUE 约束,但是每个表只能有一个 PRIMARY KEY 约束。


CREATE TABLE 时的 SQL UNIQUE 约束


 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 UNIQUE 约束:

 MySQL:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                UNIQUE (P_Id)                )        

 SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL UNIQUE,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )        

 如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)                )       

ALTER TABLE 时的 SQL UNIQUE 约束


 当表已被创建时,如需在 "P_Id" 列创建 UNIQUE 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD UNIQUE (P_Id)      

 如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)       

撤销 UNIQUE 约束


 如需撤销 UNIQUE 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE Persons                DROP INDEX uc_PersonID        

 SQL Server / Oracle / MS Access:

ALTER TABLE Persons                DROP CONSTRAINT uc_PersonID       


SQL PRIMARY KEY 约束


 PRIMARY KEY 约束唯一标识数据库表中的每条记录。

 主键必须包含唯一的值。

 主键列不能包含 NULL 值。

 每个表都应该有一个主键,并且每个表只能有一个主键。


CREATE TABLE 时的 SQL PRIMARY KEY 约束


 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 PRIMARY KEY 约束:

 MySQL:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                PRIMARY KEY (P_Id)                )        

 SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL PRIMARY KEY,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )        

 如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)                )     

 注释:在上面的实例中,只有一个主键 PRIMARY KEY(pk_PersonID)。然而,pk_PersonID 的值是由两个列(P_Id 和 LastName)组成的。


ALTER TABLE 时的 SQL PRIMARY KEY 约束


 当表已被创建时,如需在 "P_Id" 列创建 PRIMARY KEY 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD PRIMARY KEY (P_Id)        

 如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)       

 注释:如果您使用 ALTER TABLE 语句添加主键,必须把主键列声明为不包含 NULL 值(在表首次创建时)。


撤销 PRIMARY KEY 约束


 如需撤销 PRIMARY KEY 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE Persons                DROP PRIMARY KEY      

 SQL Server / Oracle / MS Access:

ALTER TABLE Persons               DROP CONSTRAINT pk_PersonID


SQL FOREIGN KEY 约束


 一个表中的 FOREIGN KEY 指向另一个表中的 PRIMARY KEY。

 让我们通过一个实例来解释外键。请看下面两个表:

 "Persons" 表:

P_IdLastNameFirstNameAddressCity
1HansenOlaTimoteivn 10Sandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStorgt 20Stavanger

 "Orders" 表:

O_IdOrderNoP_Id
1778953
2446783
3224562
4245621

 请注意,"Orders" 表中的 "P_Id" 列指向 "Persons" 表中的 "P_Id" 列。

 "Persons" 表中的 "P_Id" 列是 "Persons" 表中的 PRIMARY KEY。

 "Orders" 表中的 "P_Id" 列是 "Orders" 表中的 FOREIGN KEY。

 FOREIGN KEY 约束用于预防破坏表之间连接的行为。

 FOREIGN KEY 约束也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。


CREATE TABLE 时的 SQL FOREIGN KEY 约束


 下面的 SQL 在 "Orders" 表创建时在 "P_Id" 列上创建 FOREIGN KEY 约束:

 MySQL:

CREATE TABLE Orders                (                O_Id int NOT NULL,                OrderNo int NOT NULL,                P_Id int,               PRIMARY KEY (O_Id),                FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)                )     

 SQL Server / Oracle / MS Access:

CREATE TABLE Orders                (                O_Id int NOT NULL PRIMARY KEY,                OrderNo int NOT NULL,                P_Id int FOREIGN KEY REFERENCES Persons(P_Id)                )      

 如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Orders                (                O_Id int NOT NULL,                OrderNo int NOT NULL,                P_Id int,                PRIMARY KEY (O_Id),                CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)                REFERENCES Persons(P_Id)                )      

ALTER TABLE 时的 SQL FOREIGN KEY 约束


 当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders                ADD FOREIGN KEY (P_Id)                REFERENCES Persons(P_Id)   

 如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders                ADD CONSTRAINT fk_PerOrders                FOREIGN KEY (P_Id)                REFERENCES Persons(P_Id)       

撤销 FOREIGN KEY 约束


 如需撤销 FOREIGN KEY 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE Orders                DROP FOREIGN KEY fk_PerOrders        

 SQL Server / Oracle / MS Access:

ALTER TABLE Orders                DROP CONSTRAINT fk_PerOrders     


SQL DEFAULT 约束


 DEFAULT 约束用于向列中插入默认值。

 如果没有规定其他的值,那么会将默认值添加到所有的新记录。


CREATE TABLE 时的 SQL DEFAULT 约束


 下面的 SQL 在 "Persons" 表创建时在 "City" 列上创建 DEFAULT 约束:

 My SQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255) DEFAULT 'Sandnes')

 通过使用类似 GETDATE() 这样的函数,DEFAULT 约束也可以用于插入系统值:

CREATE TABLE Orders(O_Id int NOT NULL,OrderNo int NOT NULL,P_Id int,OrderDate date DEFAULT GETDATE())

ALTER TABLE 时的 SQL DEFAULT 约束


 当表已被创建时,如需在 "City" 列创建 DEFAULT 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE PersonsALTER City SET DEFAULT 'SANDNES'

 SQL Server / MS Access:

ALTER TABLE Persons ADD CONSTRAINT DF_Persons_City DEFAULT('SANDNES') FOR City--注释--Persons 为表名--City 为列名--DF_Persons_City 为我们创建的默认约束的名称 约束名称一般为:约束类型简称_表名_列名

 Oracle:

ALTER TABLE PersonsMODIFY City DEFAULT 'SANDNES'

撤销 DEFAULT 约束


 如需撤销 DEFAULT 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE PersonsALTER City DROP DEFAULT

 SQL Server / Oracle / MS Access:

ALTER TABLE PersonsALTER COLUMN City DROP DEFAULT

SQL CHECK 约束


 CHECK 约束用于限制列中的值的范围。

 如果对单个列定义 CHECK 约束,那么该列只允许特定的值。

 如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制。


CREATE TABLE 时的 SQL CHECK 约束


 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 CHECK 约束。CHECK 约束规定 "P_Id" 列必须只包含大于 0 的整数。

 MySQL:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255),CHECK (P_Id>0))

 SQL Server / Oracle / MS Access:

CREATE TABLE Persons(P_Id int NOT NULL CHECK (P_Id>0),LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255))

 如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255),CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes'))

ALTER TABLE 时的 SQL CHECK 约束


 当表已被创建时,如需在 "P_Id" 列创建 CHECK 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE PersonsADD CHECK (P_Id>0)

 如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE PersonsADD CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')

撤销 CHECK 约束


 如需撤销 CHECK 约束,请使用下面的 SQL:

 SQL Server / Oracle / MS Access:

ALTER TABLE PersonsDROP CONSTRAINT chk_Person

 MySQL:

ALTER TABLE PersonsDROP CHECK chk_Person

SQL JOIN 连接


 SQL 连接(JOIN) 子句用于将数据库中两个或者两个以上表中的记录组合起来。连接通过共有值将不同表中的字段组合在一起。

 我们来看看"Orders"表中的选择:

OrderIDCustomerIDOrderDate
1030821996-09-18
10309371996-09-19
10310771996-09-20

 然后,查看"Customers"表中的选择:

CustomerIDCustomerNameContactNameCountry
1Alfreds FutterkisteMaria AndersGermany
2Ana Trujillo Emparedados y heladosAna TrujilloMexico
3Antonio Moreno TaqueríaAntonio MorenoMexico

 请注意,"Orders"表中的“客户ID”列是指"CustomerID"表中的“客户ID”。上面两个表格之间的关系是“CustomerID”列。

 然后,我们可以创建下面的SQL语句(包含一个INNER JOIN),它选择两个表中具有匹配值的记录:

 代码示例:

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDateFROM OrdersINNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID;

 它会产生这样的东西:

OrderIDCustomerNameOrderDate
10308Ana Trujillo Emparedados y helados9/18/1996
10365Antonio Moreno Taquería11/27/1996
10383Around the Horn12/16/1996
10355Around the Horn11/15/1996
10278Berglunds snabbköp8/12/1996

 考虑下面两个表,(a)CUSTOMERS 表:

    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+

 (b)另一个表是 ORDERS 表:

    +-----+---------------------+-------------+--------+    |OID  | DATE                | CUSTOMER_ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我们用 SELECT 语句将这个两张表连接(JOIN)在一起:

    SQL> SELECT ID, NAME, AGE, AMOUNT            FROM CUSTOMERS, ORDERS            WHERE  CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句的运行结果如下所示:

    +----+----------+-----+--------+    | ID | NAME     | AGE | AMOUNT |    +----+----------+-----+--------+    |  3 | kaushik  |  23 |   3000 |    |  3 | kaushik  |  23 |   1500 |    |  2 | Khilan   |  25 |   1560 |    |  4 | Chaitali |  25 |   2060 |    +----+----------+-----+--------+

不同类型的SQL联接


 SQL 中有多种不同的连接:

  • 内连接(INNER JOIN):当两个表中都存在匹配时,才返回行。
  • 左连接(LEFT JOIN):返回左表中的所有行,即使右表中没有匹配的行。
  • 右连接(RIGHT JOIN):返回右表中的所有行,即使左表中没有匹配的行。
  • 全连接(FULL JOIN):只要某一个表存在匹配,就返回行。
  • 笛卡尔连接(CARTESIAN JOIN):返回两个或者更多的表中记录集的笛卡尔积。

SQL INNER JOIN    SQL左连接    SQL RIGHT JOIN    SQL全外连接

内连接

 最常用也最重要的连接形式是内连接,有时候也被称作“EQUIJOIN”(等值连接)。

 内连接根据连接谓词来组合两个表中的字段,以创建一个新的结果表。SQL 查询会比较逐个比较表 1 和表 2 中的每一条记录,来寻找满足连接谓词的所有记录对。当连接谓词得以满足时,所有满足条件的记录对的字段将会结合在一起构成结果表。

语法:

 内连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1INNER JOIN table2ON table1.common_field = table2.common_field;

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在,让我们用内连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     INNER JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+----+----------+--------+---------------------+| ID | NAME     | AMOUNT | DATE                |+----+----------+--------+---------------------+|  3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||  2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||  4 | Chaitali |   2060 | 2008-05-20 00:00:00 |+----+----------+--------+---------------------+

左连接

 左链接返回左表中的所有记录,即使右表中没有任何满足匹配条件的记录。这意味着,如果 ON 子句在右表中匹配到了 0 条记录,该连接仍然会返回至少一条记录,不过返回的记录中所有来自右表的字段都为 NULL。

 这就意味着,左连接会返回左表中的所有记录,加上右表中匹配到的记录,或者是 NULL (如果连接谓词无法匹配到任何记录的话)。

语法:

 左连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1LEFT JOIN table2ON table1.common_field = table2.common_field;

 这里,给出的条件可以是任何根据你的需要写出的条件。

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在,让我们用左连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     LEFT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+----+----------+--------+---------------------+| ID | NAME     | AMOUNT | DATE                |+----+----------+--------+---------------------+|  1 | Ramesh   |   NULL | NULL                ||  2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||  3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||  4 | Chaitali |   2060 | 2008-05-20 00:00:00 ||  5 | Hardik   |   NULL | NULL                ||  6 | Komal    |   NULL | NULL                ||  7 | Muffy    |   NULL | NULL                |+----+----------+--------+---------------------+

右连接

 右链接返回右表中的所有记录,即是左表中没有任何满足匹配条件的记录。这意味着,如果 ON 子句在左表中匹配到了 0 条记录,该连接仍然会返回至少一条记录,不过返回的记录中所有来自左表的字段都为 NULL。

 这就意味着,右连接会返回右表中的所有记录,加上左表中匹配到的记录,或者是 NULL (如果连接谓词无法匹配到任何记录的话)。

语法:

 右连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1RIGHT JOIN table2ON table1.common_field = table2.common_field;

 这里,给出的条件可以是任何根据你的需要写出的条件。

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在,让我们用右连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     RIGHT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+------+----------+--------+---------------------+| ID   | NAME     | AMOUNT | DATE                |+------+----------+--------+---------------------+|    3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||    3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||    2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |+------+----------+--------+---------------------+

全连接

 全连接将左连接和右连接的结果组合在一起。

语法:

 全连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1FULL JOIN table2ON table1.common_field = table2.common_field;

 这里,给出的条件可以是任何根据你的需要写出的条件。

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在让我们用全连接将两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     FULL JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+------+----------+--------+---------------------+| ID   | NAME     | AMOUNT | DATE                |+------+----------+--------+---------------------+|    1 | Ramesh   |   NULL | NULL                ||    2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||    3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||    3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||    4 | Chaitali |   2060 | 2008-05-20 00:00:00 ||    5 | Hardik   |   NULL | NULL                ||    6 | Komal    |   NULL | NULL                ||    7 | Muffy    |   NULL | NULL                ||    3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||    3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||    2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |+------+----------+--------+---------------------+

 如果你所用的数据库不支持全连接,比如 MySQL,那么你可以使用 UNION ALL子句来将左连接和右连接结果组合在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     LEFT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_IDUNION ALL     SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     RIGHT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID

笛卡尔连接(交叉连接)

 笛卡尔连接或者交叉连接返回两个或者更多的连接表中记录的笛卡尔乘积。也就是说,它相当于连接谓词总是为真或者缺少连接谓词的内连接。

语法:

 笛卡尔连接或者说交叉连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM  table1, table2 [, table3 ]

示例:

考虑如下两个表格,(a)CUSTOMERS 表:    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+(b)ORDERS 表:    +-----+---------------------+-------------+--------+    | OID | DATE                |          ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我用内连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS, ORDERS;

 上述语句将会产生如下结果:

+----+----------+--------+---------------------+| ID | NAME     | AMOUNT | DATE                |+----+----------+--------+---------------------+|  1 | Ramesh   |   3000 | 2009-10-08 00:00:00 ||  1 | Ramesh   |   1500 | 2009-10-08 00:00:00 ||  1 | Ramesh   |   1560 | 2009-11-20 00:00:00 ||  1 | Ramesh   |   2060 | 2008-05-20 00:00:00 ||  2 | Khilan   |   3000 | 2009-10-08 00:00:00 ||  2 | Khilan   |   1500 | 2009-10-08 00:00:00 ||  2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||  2 | Khilan   |   2060 | 2008-05-20 00:00:00 ||  3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1560 | 2009-11-20 00:00:00 ||  3 | kaushik  |   2060 | 2008-05-20 00:00:00 ||  4 | Chaitali |   3000 | 2009-10-08 00:00:00 ||  4 | Chaitali |   1500 | 2009-10-08 00:00:00 ||  4 | Chaitali |   1560 | 2009-11-20 00:00:00 ||  4 | Chaitali |   2060 | 2008-05-

SQL UNION 子句


 SQL UNION 子句/运算符用于将两个或者更多的 SELECT 语句的运算结果组合起来。

 在使用 UNION 的时候,每个 SELECT 语句必须有相同数量的选中列、相同数量的列表达式、相同的数据类型,并且它们出现的次序要一致,不过长度不一定要相同。

语法

 UNION 子句的基本语法如下所示:

    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]    UNION    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]

 这里的条件可以是任何根据你的需要而设的条件。


示例


 考虑如下两张表,(a)CUSTOMERS 表:

    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+

 (b)另一张表是 ORDERS 表,如下所示:

    +-----+---------------------+-------------+--------+    |OID  | DATE                | CUSTOMER_ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我们用 SELECT 语句将这两张表连接起来:

    SQL> SELECT  ID, NAME, AMOUNT, DATE         FROM CUSTOMERS         LEFT JOIN ORDERS         ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID    UNION         SELECT  ID, NAME, AMOUNT, DATE         FROM CUSTOMERS         RIGHT JOIN ORDERS         ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 结果如下所示:

    +------+----------+--------+---------------------+    | ID   | NAME     | AMOUNT | DATE                |    +------+----------+--------+---------------------+    |    1 | Ramesh   |   NULL | NULL                |    |    2 | Khilan   |   1560 | 2009-11-20 00:00:00 |    |    3 | kaushik  |   3000 | 2009-10-08 00:00:00 |    |    3 | kaushik  |   1500 | 2009-10-08 00:00:00 |    |    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |    |    5 | Hardik   |   NULL | NULL                |    |    6 | Komal    |   NULL | NULL                |    |    7 | Muffy    |   NULL | NULL                |    +------+----------+--------+---------------------+

UNION ALL 子句:


 UNION ALL 运算符用于将两个 SELECT 语句的结果组合在一起,重复行也包含在内。

 UNION ALL 运算符所遵从的规则与 UNION 一致。

语法:

 UNION ALL的基本语法如下:

    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]    UNION ALL    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]

示例:

 考虑如下两张表,(a)CUSTOMERS 表:

    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+

 (b)另一张表是 ORDERS 表,如下所示:

    +-----+---------------------+-------------+--------+    |OID  | DATE                | CUSTOMER_ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我们用 SELECT 语句将这两张表连接起来

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     LEFT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_IDUNION ALL     SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     RIGHT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 结果如下所示:

    +------+----------+--------+---------------------+    | ID   | NAME     | AMOUNT | DATE                |    +------+----------+--------+---------------------+    |    1 | Ramesh   |   NULL | NULL                |    |    2 | Khilan   |   1560 | 2009-11-20 00:00:00 |    |    3 | kaushik  |   3000 | 2009-10-08 00:00:00 |    |    3 | kaushik  |   1500 | 2009-10-08 00:00:00 |    |    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |    |    5 | Hardik   |   NULL | NULL                |    |    6 | Komal    |   NULL | NULL                |    |    7 | Muffy    |   NULL | NULL                |    |    3 | kaushik  |   3000 | 2009-10-08 00:00:00 |    |    3 | kaushik  |   1500 | 2009-10-08 00:00:00 |    |    2 | Khilan   |   1560 | 2009-11-20 00:00:00 |    |    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |    +------+----------+--------+---------------------+

 另外,还有两个子句(亦即运算法)与 UNION 子句非常相像:

  • SQL INTERSECT 子句:用于组合两个 SELECT 语句,但是只返回两个 SELECT 语句的结果中都有的行。
  • SQL EXCEPT 子句:组合两个 SELECT 语句,并将第一个 SELECT 语句的结果中存在,但是第二个 SELECT 语句的结果中不存在的行返回。

SQL 克隆数据表


 有些情况下,你可能需要原样拷贝某张数据表。但是,CREATE TABLE 却不能满足你的需要,因为复制表必须和原表拥有一样的索引、默认值等等。

 如果你在使用 MySQL 关系型数据库管理系统的话,下面几个步骤可以帮你解决这个问题:

  • 使用 SHOW CREATE TABLE 命令来获取一条指定了原表的结构、索引等信息的 CREATE TABLE 语句。
  • 将语句中的表名修改为克隆表的名字,然后执行该语句。这样你就可以得到一张与原表完全相同的克隆表了。
  • 如果你还想要复制表中的数据的话,请执行 INSERT INTO ... SELECT 语句。

示例:


 请尝试下面的示例,为 TUTORIALS_TBL 创建一张克隆表,其结构如下所示:

步骤一:

 获取数据表的完整结构:

SQL> SHOW CREATE TABLE TUTORIALS_TBL G;*************************** 1. row ***************************       Table: TUTORIALS_TBLCreate Table: CREATE TABLE `TUTORIALS_TBL` (  `tutorial_id` int(11) NOT NULL auto_increment,  `tutorial_title` varchar(100) NOT NULL default '',  `tutorial_author` varchar(40) NOT NULL default '',  `submission_date` date default NULL,  PRIMARY KEY  (`tutorial_id`),  UNIQUE KEY `AUTHOR_INDEX` (`tutorial_author`)) TYPE=MyISAM1 row in set (0.00 sec)

步骤二:

 改变表名,创建新表:

SQL> CREATE TABLE `CLONE_TBL` (  -> `tutorial_id` int(11) NOT NULL auto_increment,  -> `tutorial_title` varchar(100) NOT NULL default '',  -> `tutorial_author` varchar(40) NOT NULL default '',  -> `submission_date` date default NULL,  -> PRIMARY KEY  (`tutorial_id`),  -> UNIQUE KEY `AUTHOR_INDEX` (`tutorial_author`)  -> ) TYPE=MyISAM;Query OK, 0 rows affected (1.80 sec)

步骤三:

 执行完步骤二之后,数据库就会有克隆表了。如果你还想要复制旧表中的数据的话,可以执行 INSERT INTO... SELECT 语句。

SQL> INSERT INTO CLONE_TBL (tutorial_id,    ->                        tutorial_title,    ->                        tutorial_author,    ->                        submission_date)    -> SELECT tutorial_id,tutorial_title,    ->        tutorial_author,submission_date,    -> FROM TUTORIALS_TBL;Query OK, 3 rows affected (0.07 sec)Records: 3  Duplicates: 0  Warnings: 0

 最终,你将如期拥有一张完全相同的克隆表。

SQL 索引


 索引是一种特殊的查询表,可以被数据库搜索引擎用来加速数据的检索。简单说来,索引就是指向表中数据的指针。数据库的索引同书籍后面的索引非常相像。

 例如,如果想要查阅一本书中与某个特定主题相关的所有页面,你会先去查询索引(索引按照字母表顺序列出了所有主题),然后从索引中找到一页或者多页与该主题相关的页面。

 索引能够提高 SELECT 查询和 WHERE 子句的速度,但是却降低了包含 UPDATE 语句或 INSERT 语句的数据输入过程的速度。索引的创建与删除不会对表中的数据产生影响。

 创建索引需要使用 CREATE INDEX 语句,该语句允许对索引命名,指定要创建索引的表以及对哪些列进行索引,还可以指定索引按照升序或者降序排列。

 同 UNIQUE 约束一样,索引可以是唯一的。这种情况下,索引会阻止列中(或者列的组合,其中某些列有索引)出现重复的条目。


CREATE INDEX 命令:


 CREATE INDEX命令的基本语法如下:

CREATE INDEX index_name ON table_name;

单列索引:

 单列索引基于单一的字段创建,其基本语法如下所示:

CREATE INDEX index_nameON table_name (column_name);

唯一索引:

 唯一索引不止用于提升查询性能,还用于保证数据完整性。唯一索引不允许向表中插入任何重复值。其基本语法如下所示:

CREATE UNIQUE INDEX index_nameon table_name (column_name);

聚簇索引:

 聚簇索引在表中两个或更多的列的基础上建立。其基本语法如下所示:

CREATE INDEX index_nameon table_name (column1, column2);

 创建单列索引还是聚簇索引,要看每次查询中,哪些列在作为过滤条件的 WHERE 子句中最常出现。

 如果只需要一列,那么就应当创建单列索引。如果作为过滤条件的 WHERE 子句用到了两个或者更多的列,那么聚簇索引就是最好的选择。

隐式索引:

 隐式索引由数据库服务器在创建某些对象的时候自动生成。例如,对于主键约束和唯一约束,数据库服务器就会自动创建索引。

DROP INDEX 命令:

 索引可以用 SQL DROP 命令删除。删除索引时应当特别小心,数据库的性能可能会因此而降低或者提高。

 其基本语法如下:

DROP INDEX table_name.index_name;

什么时候应当避免使用索引?


 尽管创建索引的目的是提升数据库的性能,但是还是有一些情况应当避免使用索引。下面几条指导原则给出了何时应当重新考虑是否使用索引:

  • 小的数据表不应当使用索引;
  • 需要频繁进行大批量的更新或者插入操作的表;
  • 如果列中包含大数或者 NULL 值,不宜创建索引;
  • 频繁操作的列不宜创建索引。

SQL 子查询


 子查询(Sub Query)或者说内查询(Inner Query),也可以称作嵌套查询(Nested Query),是一种嵌套在其他 SQL 查询的 WHERE 子句中的查询。

 子查询用于为主查询返回其所需数据,或者对检索数据进行进一步的限制。

 子查询可以在 SELECT、INSERT、UPDATE 和 DELETE 语句中,同 =、<、>、>=、<=、IN、BETWEEN 等运算符一起使用。

 使用子查询必须遵循以下几个规则:

  • 子查询必须括在圆括号中。
  • 子查询的 SELECT 子句中只能有一个列,除非主查询中有多个列,用于与子查询选中的列相比较。
  • 子查询不能使用 ORDER BY,不过主查询可以。在子查询中,GROUP BY 可以起到同 ORDER BY 相同的作用。
  • 返回多行数据的子查询只能同多值操作符一起使用,比如 IN 操作符。
  • SELECT 列表中不能包含任何对 BLOB、ARRAY、CLOB 或者 NCLOB 类型值的引用。
  • 子查询不能直接用在聚合函数中。
  • BETWEEN 操作符不能同子查询一起使用,但是 BETWEEN 操作符可以用在子查询中。

SELECT 语句中的子查询


 通常情况下子查询都与 SELECT 语句一起使用,其基本语法如下所示:

SELECT column_name [, column_name ]FROM   table1 [, table2 ]WHERE  column_name OPERATOR      (SELECT column_name [, column_name ]      FROM table1 [, table2 ]      [WHERE])

示例:


 考虑 CUSTOMERS 表,表中记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 现在,让我们试一下在 SELECT 语句中进行子查询:

SQL> SELECT *      FROM CUSTOMERS      WHERE ID IN (SELECT ID                   FROM CUSTOMERS                   WHERE SALARY > 4500) ;

 上述语句的执行结果如下所示:

+----+----------+-----+---------+----------+| ID | NAME     | AGE | ADDRESS | SALARY   |+----+----------+-----+---------+----------+|  4 | Chaitali |  25 | Mumbai  |  6500.00 ||  5 | Hardik   |  27 | Bhopal  |  8500.00 ||  7 | Muffy    |  24 | Indore  | 10000.00 |+----+----------+-----+---------+----------+

INSERT 语句中的子查询:


 子查询还可以用在 INSERT 语句中。INSERT 语句可以将子查询返回的数据插入到其他表中。子查询中选取的数据可以被任何字符、日期或者数值函数所修饰。

 其基本语法如下所示:

INSERT INTO table_name [ (column1 [, column2 ]) ]           SELECT [ *|column1 [, column2 ]           FROM table1 [, table2 ]           [ WHERE VALUE OPERATOR ]

示例:


 考虑与 CUSTOMERS 表拥有相似结构的 CUSTOMERS_BKP 表。现在要将 CUSTOMER 表中所有的数据复制到 CUSTOMERS_BKP 表中,代码如下:

SQL> INSERT INTO CUSTOMERS_BKP     SELECT * FROM CUSTOMERS      WHERE ID IN (SELECT ID                   FROM CUSTOMERS) ;

UPDATE 语句中的子查询:


 子查询可以用在 UPDATE 语句中。当子查询同 UPDATE 一起使用的时候,既可以更新单个列,也可更新多个列。

 其基本语法如下:

UPDATE tableSET column_name = new_value[ WHERE OPERATOR [ VALUE ]   (SELECT COLUMN_NAME   FROM TABLE_NAME)   [ WHERE) ]

示例:


 假设我们有一份 CUSTOMERS_BKP 表作为 CUSTOMERS 表的备份。

 下面的示例将 CUSTOMERS 表中所有 AGE 大于或者等于 27 的客户的 SALARY 字段都变为了原来的 0.25 倍:

SQL> UPDATE CUSTOMERS     SET SALARY = SALARY * 0.25     WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP                   WHERE AGE >= 27 );

 这将影响两行数据,随后 CUSTOMERS 表中的记录将如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |   125.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  2125.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

DELETE 语句中的子查询:


 如同前面提到的其他语句一样,子查询还可以同 DELETE 语句一起使用。

 其基本语法如下所示:

DELETE FROM TABLE_NAME[ WHERE OPERATOR [ VALUE ]   (SELECT COLUMN_NAME   FROM TABLE_NAME)   [ WHERE) ]

示例:


 假设我们有一份 CUSTOMERS_BKP 表作为 CUSTOMERS 表的备份。

 下面的示例将从 CUSTOMERS 表中删除所有 AGE 大于或者等于 27 的记录:

SQL> DELETE FROM CUSTOMERS     WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP                   WHERE AGE > 27 );

 这将影响两行数据,随后 CUSTOMERS 表中的记录将如下所示:

+----+----------+-----+---------+----------+| ID | NAME     | AGE | ADDRESS | SALARY   |+----+----------+-----+---------+----------+|  2 | Khilan   |  25 | Delhi   |  1500.00 ||  3 | kaushik  |  23 | Kota    |  2000.00 ||  4 | Chaitali |  25 | Mumbai  |  6500.00 ||  6 | Komal    |  22 | MP      |  4500.00 ||  7 | Muffy    |  24 | Indore  | 10000.00 |+----+----------+-----+---------+----------+


章节小测


 现在,通过以下题目测测看您对“SQL 子查询”的掌握程度吧!

 SQL 子查询:在本部分测验中,您将练习使用 SQL 子查询。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL ALTER TABLE 命令


 SQL ALTER TABLE 命令用于添加、删除或者更改现有数据表中的列。

 你还可以用 ALTER TABLE 命令来添加或者删除现有数据表上的约束。


语法:


 使用 ALTER TABLE 在现有的数据表中添加新列的基本语法如下:

ALTER TABLE table_name ADD column_name datatype;

 使用 ALTER TABLE 在现有的数据表中删除列的基本语法如下:

ALTER TABLE table_name DROP COLUMN column_name;

 使用 ALTER TABLE 更改现有的数据表中列的数据类型的基本语法如下:

ALTER TABLE table_name MODIFY COLUMN column_name datatype;

 使用 ALTER TABLE 给某列添加 NOT NULL 约束 的基本语法如下:

ALTER TABLE table_name MODIFY column_name datatype NOT NULL;

 使用 ALTER TABLE 给数据表添加 唯一约束 的基本语法如下:

ALTER TABLE table_name ADD CONSTRAINT MyUniqueConstraint UNIQUE(column1, column2...);

 使用 ALTER TABLE 给数据表添加 CHECK 约束 的基本语法如下:

ALTER TABLE table_name ADD CONSTRAINT MyUniqueConstraint CHECK (CONDITION);

 使用 ALTER TABLE 给数据表添加 主键约束 的基本语法如下:

ALTER TABLE table_name ADD CONSTRAINT MyPrimaryKey PRIMARY KEY (column1, column2...);

 使用 ALTER TABLE 从数据表中 删除约束 的基本语法如下:

ALTER TABLE table_name DROP CONSTRAINT MyUniqueConstraint;

 如果你在使用 MySQL,代码应当如下:

ALTER TABLE table_name DROP INDEX MyUniqueConstraint;

 使用 ALTER TABLE 从数据表中 删除主键约束 的基本语法如下:

ALTER TABLE table_name DROP CONSTRAINT MyPrimaryKey;

 如果你在使用 MySQL,代码应当如下:

ALTER TABLE table_name DROP PRIMARY KEY;

示例:


 考虑 CUSTOMERS 表,表中记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例展示了如何在现有的表中添加新的一列:

ALTER TABLE CUSTOMERS ADD SEX char(1);

 现在,CUSTOMERS 已经被更改了,SELECT 语句的输出应当如下所示:

+----+---------+-----+-----------+----------+------+| ID | NAME    | AGE | ADDRESS   | SALARY   | SEX  |+----+---------+-----+-----------+----------+------+|  1 | Ramesh  |  32 | Ahmedabad |  2000.00 | NULL ||  2 | Ramesh  |  25 | Delhi     |  1500.00 | NULL ||  3 | kaushik |  23 | Kota      |  2000.00 | NULL ||  4 | kaushik |  25 | Mumbai    |  6500.00 | NULL ||  5 | Hardik  |  27 | Bhopal    |  8500.00 | NULL ||  6 | Komal   |  22 | MP        |  4500.00 | NULL ||  7 | Muffy   |  24 | Indore    | 10000.00 | NULL |+----+---------+-----+-----------+----------+------+

 下面的示例展示了如何从 CUSTOMERS 表中删除 SEX 列:

ALTER TABLE CUSTOMERS DROP COLUMN SEX;

 现在,CUSTOMERS 已经被更改了,SELECT 语句的输出应当如下所示:

+----+---------+-----+-----------+----------+| ID | NAME    | AGE | ADDRESS   | SALARY   |+----+---------+-----+-----------+----------+|  1 | Ramesh  |  32 | Ahmedabad |  2000.00 ||  2 | Ramesh  |  25 | Delhi     |  1500.00 ||  3 | kaushik |  23 | Kota      |  2000.00 ||  4 | kaushik |  25 | Mumbai    |  6500.00 ||  5 | Hardik  |  27 | Bhopal    |  8500.00 ||  6 | Komal   |  22 | MP        |  4500.00 ||  7 | Muffy   |  24 | Indore    | 10000.00 |+----+---------+-----+-----------+----------+

SQL TRUNCATE TABLE 命令


 SQL TRUNCATE TABLE 命令用于删除现有数据表中的所有数据。

 你也可以使用 DROP TABLE 命令来删除整个数据表,不过 DROP TABLE 命令不但会删除表中所有数据,还会将整个表结构从数据库中移除。如果想要重新向表中存储数据的话,必须重建该数据表。


语法:


 TRUNCATE TABLE 的基本语法如下所示:

TRUNCATE TABLE  table_name;

示例:


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例展示了 TRUNCATE 命令的用法:

TRUNCATE TABLE CUSTOMERS;

 现在,CUSTOMERS 表已经被清空了,SELECT 语句的输出应当如下所示:

SQL> SELECT * FROM CUSTOMERS;Empty set (0.00 sec)

SQL 处理重复数据


 有时候,数据表中会存在相同的记录。在获取表中记录时,相较于取得重复记录来说,取得唯一的记录显然更有意义。

 我们之前讨论过的 SQL DISTINCT 关键字,与 SELECT 语句一起使用可以时,可以达到消除所有重复记录,只返回唯一记录的目的。


语法:


 利用 DISTINCT 关键字来消除重复记录的基本语法如下所示:

SELECT DISTINCT column1, column2,.....columnN FROM table_nameWHERE [condition]

示例:


 考虑 CUSTOMERS 表,表中记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 首先,让我们先看一下 SELECT 语句是如何返回重复的薪水记录的:

SQL> SELECT SALARY FROM CUSTOMERS     ORDER BY SALARY;

 运行上述语句将会得到以下结果,其中 SALARY 为 2000 的记录出现了两次,即来自原始数据表的重复记录:

+----------+| SALARY   |+----------+|  1500.00 ||  2000.00 ||  2000.00 ||  4500.00 ||  6500.00 ||  8500.00 || 10000.00 |+----------+

 现在,让我们在上面的 SELECT 查询中使用 DISTINCT 关键字,然后观察将会得到什么结果:

SQL> SELECT DISTINCT SALARY FROM CUSTOMERS     ORDER BY SALARY;

 上述语句将会产生如下结果,这一再没有任何重复的条目了:

+----------+| SALARY   |+----------+|  1500.00 ||  2000.00 ||  4500.00 ||  6500.00 ||  8500.00 || 10000.00 |+----------+

SQL 使用视图


 视图无非就是存储在数据库中并具有名字的 SQL 语句,或者说是以预定义的 SQL 查询的形式存在的数据表的成分。

 视图可以包含表中的所有列,或者仅包含选定的列。视图可以创建自一个或者多个表,这取决于创建该视图的 SQL 语句的写法。

 视图,一种虚拟的表,允许用户执行以下操作:

  • 以用户或者某些类型的用户感觉自然或者直观的方式来组织数据;
  • 限制对数据的访问,从而使得用户仅能够看到或者修改(某些情况下)他们需要的数据;
  • 从多个表中汇总数据,以产生报表。

创建视图


 在 SQL 中,视图是基于 SQL 语句的结果集的可视化表。

 数据库视图由 CREATE VIEW 语句创建。视图可以创建自单个表、多个表或者其他视图。

 视图中的字段是一个或多个数据库中真实表中的字段。

 在使用时视图可以被视为一个“虚拟表”。    

 要创建视图的话,用户必须有适当的系统权限。具体需要何种权限随数据库系统实现的不同而不同。

 CREATE VIEW 语句的基本语法如下所示:

CREATE VIEW view_name ASSELECT column1, column2.....FROM table_nameWHERE [condition];

 和普通的 SQL SELECT 查询一样,你可以在上面的 SELECT 语句中包含多个数据表。

注释:视图总是显示最新数据!每当用户查询视图时,数据库引擎就使用视图的 SQL 语句重新构建数据。


SQL CREATE VIEW 示例


示例一

 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面是由 CUSTOMERS 表创建视图的例子。该视图包含来自 CUSTOMERS 表的顾客的名字(name)和年龄(age):

SQL > CREATE VIEW CUSTOMERS_VIEW ASSELECT name, ageFROM  CUSTOMERS;

 现在,你就可以像查询普通的数据表一样查询 CUSTOMERS_VIEW 了:

SQL > SELECT * FROM CUSTOMERS_VIEW;

 上述语句将会产生如下运行结果:

+----------+-----+| name     | age |+----------+-----+| Ramesh   |  32 || Khilan   |  25 || kaushik  |  23 || Chaitali |  25 || Hardik   |  27 || Komal    |  22 || Muffy    |  24 |+----------+-----+

示例2

 下面是由 CUSTOMERS 表创建视图的例子。该视图包含来自 CUSTOMERS 表中年龄(age)为25的顾客的ADDRESS信息:

SQL > CREATE VIEW CUSTOMERS_ADDRESS ASSELECT ADDRESSFROM  CUSTOMERS;WHERE AGE=25;

 我们可以像这样查询上面这个 CUSTOMERS_ADDRESS 视图:

SQL > SELECT * FROM CUSTOMERS_ADDRESS;

 我们也可以向查询添加条件。现在,我们仅仅需要查看 "Delhi" 的数据:

SELECT * FROM CUSTOMERS_ADDRESSWHERE ADDRESS='Delhi';


WITH CHECK OPTION


 WITH CHECK OPTION 是 CREATE VIEW 语句的一个可选项。

 WITH CHECK OPTION 用于保证所有的 UPDATE 和 INSERT 语句都满足视图定义中的条件。

 如果不能满足这些条件,UPDATE 或 INSERT 就会返回错误。

 下面的例子创建的也是 CUSTOMERS_VIEW 视图,不过这次 WITH CHECK OPTION 是打开的:

CREATE VIEW CUSTOMERS_VIEW ASSELECT name, ageFROM  CUSTOMERSWHERE age IS NOT NULLWITH CHECK OPTION;

 这里 WITH CHECK OPTION 使得视图拒绝任何 AGE 字段为 NULL 的条目,因为视图的定义中,AGE 字段不能为空。


更新视图


 在SQL视图上也可以使用修改数据的DML语句,如 INSERT、UPDATE和DELETE。

 视图可以在特定的情况下更新:

  • SELECT 子句不能包含 DISTINCT 关键字
  • SELECT 子句不能包含任何汇总函数(summary functions)
  • SELECT 子句不能包含任何集合函数(set functions)
  • SELECT 子句不能包含任何集合运算符(set operators)
  • SELECT 子句不能包含 ORDER BY 子句
  • 视图不能包含连接操作符
  • 视图不能包含伪列或表达式
  • FROM 子句中不能有多个数据表
  • WHERE 子句不能包含子查询(subquery)
  • 查询语句中不能有 GROUP BY 或者 HAVING
  • 计算得出的列不能更新
  • 视图必须包含原始数据表中所有的 NOT NULL 列,从而使 INSERT 查询生效。

 如果视图满足以上所有的条件,该视图就可以被更新。下面的例子中,Ramesh 的年龄被更新了:

SQL > UPDATE CUSTOMERS_VIEW      SET AGE = 35      WHERE name='Ramesh';

 最终更新的还是原始数据表,只是其结果反应在了视图上。现在查询原始数据表,SELECT 语句将会产生以下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

向视图中插入新行


 可以向视图中插入新行,其规则同(使用 UPDATE 命令)更新视图所遵循的规则相同。

 这里我们不能向 CUSTOMERS_VIEW 视图中添加新行,因为该视图没有包含原始数据表中所有 NOT NULL 的列。否则的话,你就可以像在数据表中插入新行一样,向视图中插入新行。

 句法:

INSERT INTO view_nameVALUES (value1, value2, value3, ...);

删除视图中的行


 视图中的数据行可以被删除。删除数据行与更新视图和向视图中插入新行遵循相同的规则。

 下面的例子将删除 CUSTOMERS_VIEW 视图中 AGE=22 的数据行:

SQL > DELETE FROM CUSTOMERS_VIEW      WHERE age = 22;

 该语句最终会将原始数据表中对应的数据行删除,只不过其结果反应在了视图上。现在查询原始数据表,SELECT 语句将会产生以下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

删除视图


 很明显,当我们不再需要某个视图的时候,需要有一种方式可以让我们将其删除。删除视图的语法非常简单,如下所示:

DROP VIEW view_name;

 下面的例子展示了如何从 CUSTOMERS 表中删除 CUSTOMERS_VIEW 视图:

DROP VIEW CUSTOMERS_VIEW;


章节小测


 现在,通过以下题目测测看您对“SQL 使用视图”的掌握程度吧!

 SQL 视图:在本部分测验中,您将练习创建以及更新 SQL 视图。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL 注入


 如果你从网页中获取用户输入,并将其插入到 SQL 数据库中的话,那么你很可能已经暴露于一种被称作 SQL 注入的安全风险之下了。

 本节将会教你如何防止 SQL 注入,以及如何保护 Perl 这样的服务器端脚本中的程序和 SQL 语句。

 注入通常发生在获取用户输入的时候,例如预期得到用户的名字,但是得到的却是一段很可能会在你不知情的情况下运行的 SQL 语句。

 绝对不要相信用户提供的数据,处理这些数据之前必须进行验证;通常,验证工作由模式匹配来完成。

 下面的例子中,name 仅限由字母、数字和下划线组成,并且长度在 8 到 20 之间(你可以根据需要修改这些规则)。

if (preg_match("/^w{8,20}$/", $_GET['username'], $matches)){   $result = mysql_query("SELECT * FROM CUSTOMERS                           WHERE name=$matches[0]");}else {   echo "user name not accepted";}

 为了展示问题所在,请考虑下面这段代码:

// supposed input$name = "Qadir'; DELETE FROM CUSTOMERS;";mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");

 下面的函数调用本来是要从 CUSTOMERS 表中取得 name 字段与用户给定的输入相匹配的记录。通常情况下,$name 只包含字母和数字,或许还有空格,例如字符串 ilia。但是,这里通过在 $name 上附加一段全新的查询语句,将原有的函数调用变为了数据库的灾难:注入的 DELETE 语句将会删除表中所有的记录。

 幸运的是,如果你在使用 MySQL 的话,mysql_query() 函数不允许查询堆积(query stacking),或者说在一次函数调用中执行多次 SQL 查询。如果你试图进行堆积式查询的话,函数调用将会失败。

 然而,其他的 PHP 数据库扩展,例如 SQLite 和 PostgreSQL 会愉快地接受堆积式查询,执行字符串中所有的查询,并由此产生严重的安全问题。


阻止 SQL 注入


 你可以在 Perl 或者 PHP 等脚本语言中巧妙地处理所有的转义字符。PHP 的 MySQL 扩展提供了一个 mysql_real_escape_string() 函数,来转义那些对 MySQL 有特殊意义的字符。

if (get_magic_quotes_gpc()) {  $name = stripslashes($name);}$name = mysql_real_escape_string($name);mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");

LIKE 困境


 要破解 LIKE 困境,必须有一种专门的转义机制,将用户提供的 '%' 和 '_' 转换为字面值。为此你可以使用 addcslashes() 函数,该函数允许指定要进行转义的字符的范围。

$sub = addcslashes(mysql_real_escape_string("%str"), "%_");// $sub == \%str\_mysql_query("SELECT * FROM messages              WHERE subject LIKE '{$sub}%'");

SQL HAVING 子句


HAVING​ 子句使你能够指定过滤条件,从而控制查询结果中哪些组可以出现在最终结果里面。

WHERE ​子句对被选择的列施加条件,而 ​HAVING ​子句则对 ​GROUP BY​ 子句所产生的组施加条件。

语法  

下面可以看到 ​HAVING​ 子句在 ​SEL ECT ​查询中的位置:

SELECTFROMWHEREGROUP BYHAVINGORDER BY

在 ​SELECT​ 查询中,​HAVING​ 子句必须紧随 ​GROUP BY​ 子句,并出现在 ​ORDER BY​ 子句(如果有的话)之前。带有 ​HAVING​ 子句的 ​SELECT​ 语句的语法如下所示:

SELECT column1, column2   FROM table1, table2WHERE [ conditions ]GROUP BY column1, column2HAVING [ conditions ]ORDER BY column1, column2

示例


 考虑 ​CUSTOMERS​ 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面是一个有关 ​HAVING​ 子句使用的实例,该实例将会筛选出出现次数大于或等于 2 的所有记录。

SQL > SELECT ID, NAME, AGE, ADDRESS, SALARYFROM CUSTOMERSGROUP BY ageHAVING COUNT(age) >= 2;

 其执行结果如下所示:

+----+----------+-----+---------+---------+| ID | NAME     | AGE | ADDRESS | SALARY  |+----+----------+-----+---------+---------+|  2 | Khilan   |  25 | Delhi   | 1500.00 ||  4 | Chaitali |  25 | Mumbai  | 6500.00 |+----+----------+-----+---------+---------+

SQL HAVING 实例

现在我们想要查找总访问量大于 200 的网站。

我们使用下面的 SQL 语句:

实例

SELECT Websites.name, Websites.url, SUM(access_log.count) AS nums FROM (access_log INNER JOIN Websites ON access_log.site_id=Websites.id) GROUP BY Websites.name HAVING SUM(access_log.count) > 200;

执行以上 SQL 输出结果如下:

现在我们想要查找总访问量大于 200 的网站,并且 alexa 排名小于 200。

我们在 SQL 语句中增加一个普通的 WHERE 子句:

实例

SELECT Websites.name, SUM(access_log.count) AS nums FROM Websites INNER JOIN access_log ON Websites.id=access_log.site_id WHERE Websites.alexa < 200 GROUP BY Websites.name HAVING SUM(access_log.count) > 200;

执行以上 SQL 输出结果如下:



SQL 事务


 事务是在数据库上按照一定的逻辑顺序执行的任务序列,既可以由用户手动执行,也可以由某种数据库程序自动执行。

 事务实际上就是对数据库的一个或者多个更改。当你在某张表上创建更新或者删除记录的时,你就已经在使用事务了。控制事务以保证数据完整性,并对数据库错误做出处理,对数据库来说非常重要。

 实践中,通常会将很多 SQL 查询组合在一起,并将其作为某个事务一部分来执行。


事务的属性


 事务具有以下四个标准属性,通常用缩略词 ACID 来表示:

  • 原子性:保证任务中的所有操作都执行完毕;否则,事务会在出现错误时终止,并回滚之前所有操作到原始状态。
  • 一致性:如果事务成功执行,则数据库的状态得到了进行了正确的转变。
  • 隔离性:保证不同的事务相互独立、透明地执行。
  • 持久性:即使出现系统故障,之前成功执行的事务的结果也会持久存在。

事务控制


 有四个命令用于控制事务:

  • COMMIT:提交更改;
  • ROLLBACK:回滚更改;
  • SAVEPOINT:在事务内部创建一系列可以 ROLLBACK 的还原点;
  • SET TRANSACTION:命名事务;

COMMIT 命令


 COMMIT 命令用于保存事务对数据库所做的更改。

 COMMIT 命令会将自上次 COMMIT 命令或者 ROLLBACK 命令执行以来所有的事务都保存到数据库中。

 COMMIT 命令的语法如下所示:

COMMIT;

示例


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例将会删除表中 age=25 的记录,然后将更改提交(COMMIT)到数据库中。

SQL> DELETE FROM CUSTOMERS     WHERE AGE = 25;SQL> COMMIT;

 上述语句将会从表中删除两行记录,再执行 SELECT 语句将会得到如下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

ROLLBACK 命令


 ROLLBACK 命令用于撤销尚未保存到数据库中的事务。

 ROLLBACK 命令只能撤销自上次 COMMIT 命令或者 ROLLBACK 命令执行以来的事务。

 ROLLBACK 命令的语法如下所示:

ROLLBACK;

示例:


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例将会从表中删除所有 age=25 的记录,然后回滚(ROLLBACK)对数据库所做的更改。

SQL> DELETE FROM CUSTOMERS     WHERE AGE = 25;SQL> ROLLBACK;

 结果是删除操作并不会对数据库产生影响。现在,执行 SELECT 语句将会得到如下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

SAVEPOINT 命令


 SAVEPOINT 是事务中的一个状态点,使得我们可以将事务回滚至特定的点,而不是将整个事务都撤销。

 SAVEPOINT 命令的记录如下所示:

SAVEPOINT SAVEPOINT_NAME;

 该命令只能在事务语句之间创建保存点(SAVEPOINT)。ROLLBACK 命令可以用于撤销一系列的事务。

 回滚至某一保存点的语法如下所示:

ROLLBACK TO SAVEPOINT_NAME;

 下面的示例中,你计划从 CUSTOMERS 表中删除三条不同的记录,并在每次删除之前创建一个保存点(SAVEPOINT),从而使得你可以在任何任何时候回滚到任意的保存点,以恢复数据至其原始状态。


示例


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 操作序列如下所示:

SQL> SAVEPOINT SP1;Savepoint created.SQL> DELETE FROM CUSTOMERS WHERE ID=1;1 row deleted.SQL> SAVEPOINT SP2;Savepoint created.SQL> DELETE FROM CUSTOMERS WHERE ID=2;1 row deleted.SQL> SAVEPOINT SP3;Savepoint created.SQL> DELETE FROM CUSTOMERS WHERE ID=3;1 row deleted.

 现在,三次删除操作已经生效了,如果此时你改变主意决定回滚至名字为 SP2 的保存点,由于 SP2 于第一次删除操作之后创建,所以后两次删除操作将会被撤销。

SQL> ROLLBACK TO SP2;Rollback complete.

 注意,由于你将数据库回滚至 SP2,所以只有第一次删除真正起效了:

SQL> SELECT * FROM CUSTOMERS;+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+6 rows selected.

RELEASE SAVEPOINT 命令


 RELEASE SAVEPOINT 命令用于删除先前创建的保存点。

 RELEASE SAVEPOINT 的语法如下所示:

RELEASE SAVEPOINT SAVEPOINT_NAME;

 保存点一旦被释放,你就不能够再用 ROLLBACK 命令来撤销该保存点之后的事务了。


SET TRANSACTION 命令


 SET TRANSACTION 命令可以用来初始化数据库事务,指定随后的事务的各种特征。

 例如,你可以将某个事务指定为只读或者读写。

 SET TRANSACTION 命令的语法如下所示:

SET TRANSACTION [ READ WRITE | READ ONLY ];

SQL 使用序列


 序列是根据需要产生的一组有序整数:1, 2, 3 ... 序列在数据库中经常用到,因为许多应用要求数据表中的的每一行都有一个唯一的值,序列为此提供了一种简单的方法。

 本节阐述在 MySQL 中如何使用序列。


使用 AUTO_INCREMENT 列


 在 MySQL 中使用序列最简单的方式是,把某列定义为 AUTO_INCREMENT,然后将剩下的事情交由 MySQL 处理:


示例


 试一下下面的例子,该例将会创建一张新表,然后再里面插入几条记录,添加记录时并不需要指定记录的 ID,因为该列的值由 MySQL 自动增加。

mysql> CREATE TABLE INSECT    -> (    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT,    -> PRIMARY KEY (id),    -> name VARCHAR(30) NOT NULL, # type of insect    -> date DATE NOT NULL, # date collected    -> origin VARCHAR(30) NOT NULL # where collected);Query OK, 0 rows affected (0.02 sec)mysql> INSERT INTO INSECT (id,name,date,origin) VALUES    -> (NULL,'housefly','2001-09-10','kitchen'),    -> (NULL,'millipede','2001-09-10','driveway'),    -> (NULL,'grasshopper','2001-09-10','front yard');Query OK, 3 rows affected (0.02 sec)Records: 3  Duplicates: 0  Warnings: 0mysql> SELECT * FROM INSECT ORDER BY id;+----+-------------+------------+------------+| id | name        | date       | origin     |+----+-------------+------------+------------+|  1 | housefly    | 2001-09-10 | kitchen    ||  2 | millipede   | 2001-09-10 | driveway   ||  3 | grasshopper | 2001-09-10 | front yard |+----+-------------+------------+------------+3 rows in set (0.00 sec)

获取 AUTO_INCREMENT 值


 LAST_INSERT_ID() 是一个 SQL 函数,可以用在任何能够执行 SQL 语句地方。另外,Perl 和 PHP 各自提供了其独有的函数,用于获得最后一条记录的 AUTO_INCREMENT 值。


Perl 示例


 使用 mysql_insertid 属性来获取 SQL 查询产生的 AUTO_INCREMENT 值。根据执行查询的方式不同,该属性可以通过数据库句柄或者语句句柄来访问。下面的示例通过数据库句柄取得自增值:

$dbh->do ("INSERT INTO INSECT (name,date,origin)VALUES('moth','2001-09-14','windowsill')");my $seq = $dbh->{mysql_insertid};

PHP 示例


 在执行完会产生自增值的查询后,可以通过调用 mysql_insert_id() 来获取此值:

mysql_query ("INSERT INTO INSECT (name,date,origin)VALUES('moth','2001-09-14','windowsill')", $conn_id);$seq = mysql_insert_id ($conn_id);

重新编号现有序列


 当你从表中删除了很多记录后,可能会想要对所有的记录重新定序。只要略施小计就能达到此目的,不过如果你的表与其他表之间存在连接的话,请千万小心。

 当你觉得不得不对 AUTO_INCREMENT 列重新定序时,从表中删除该列,然后再将其添加回来,就可以达到目的了。下面的示例展示了如何使用这种方法,为 INSECT 表中的 ID 值重新定序:

mysql> ALTER TABLE INSECT DROP id;mysql> ALTER TABLE insect    -> ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,    -> ADD PRIMARY KEY (id);

从特定值的序列


 默认情况下,MySQL 中序列的起始值为 1,不过你可以在创建数据表的时候,指定任意其他值。下面的示例中,MySQL 将序列的起始值设为 100:

mysql> CREATE TABLE INSECT    -> (    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT = 100,    -> PRIMARY KEY (id),    -> name VARCHAR(30) NOT NULL, # type of insect    -> date DATE NOT NULL, # date collected    -> origin VARCHAR(30) NOT NULL # where collected);

 或者,你也可以先创建数据表,然后使用 ALTER TABLE 来设置序列的起始值:

mysql> ALTER TABLE t AUTO_INCREMENT = 100;

SQL 通配符


 我们已经讨论过 SQL 的 LIKE 操作符了,它可以利用通配符来对两个相似的值作比较。

 SQL 支持以下两个通配符与 LIKE 操作符一起使用:

通配符描述
百分号(%)匹配一个或者多个字符。注意:MS Access 使用星号(*)作为匹配一个或者多个字符的通配符,而不是百分号(%)。
下划线(_)匹配一个字符。注意:MS Access 使用问号(?),而不是下划线,来匹配任一字符。

 百分号代表零个、一个或者多个字符。下划线代表单一的字符。这些符号可以组合在一起使用。


语法


 “%” 和 “_” 的基本语法如下所示:

SELECT FROM table_nameWHERE column LIKE 'XXXX%'or SELECT FROM table_nameWHERE column LIKE '%XXXX%'orSELECT FROM table_nameWHERE column LIKE 'XXXX_'orSELECT FROM table_nameWHERE column LIKE '_XXXX'orSELECT FROM table_nameWHERE column LIKE '_XXXX_'

 你可以用 AND 或 OR 操作符将多个条件合并在一起。这里,XXXX 可以为任何数值或者字符串。


示例


语句描述
WHERE SALARY LIKE '200%'找出任何以 200 开头的值。
WHERE SALARY LIKE '%200%'找出任何存在 200 的值。
WHERE SALARY LIKE '_00%'找出任何第二个位置和第三个位置为 0 的值。
WHERE SALARY LIKE '2_%_%'找出任何以 2 开始,并且长度至少为 3 的值。
WHERE SALARY LIKE '%2'找出任何以 2 结尾的值。
WHERE SALARY LIKE '_2%3'找出任何第二个位置为 2,并且以 3 结束的值。
WHERE SALARY LIKE '2___3'找出任何以 2 开始,以 3 结束的五位数。

 让我们来看一个真实的例子,考虑拥有如下记录的 CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例将会找到 CUSTOMER 表中所有 SALARY 以 200 开头的记录,并显示出来:

SQL> SELECT * FROM CUSTOMERSWHERE SALARY LIKE '200%'; 

 结果如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 |+----+----------+-----+-----------+----------+

SQL 临时表


 某些关系型数据库管理系统支持临时表。临时表是一项很棒的特性,能够让你像操作普通的 SQL 数据表一样,使用 SELECT、UPDATE 和 JOIN 等功能来存储或者操作中间结果。

 临时表有时候对于保存临时数据非常有用。有关临时表你需要知道的最重要的一点是,它们会在当前的终端会话结束后被删除。

 临时表自 MySQL 3.23 起受到支持。如果你的 MySQL 版本比 3.23 还老,那么你就不能使用临时表了,不过你可以使用堆表(heap table)。

 如先前所言,临时表只在会话期间存在。如果你在 PHP 脚本中操作数据库,那么临时表将在脚本执行完毕时被自动销毁。如果你是通过 MySQL 的客户端程序连接到 MySQL 数据库服务器的,那么临时表将会存在到你关闭客户端或者手动将其删除。


示例


 下面的示例向你展示了如何使用临时表:

mysql> CREATE TEMPORARY TABLE SALESSUMMARY (    -> product_name VARCHAR(50) NOT NULL    -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00    -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00    -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0);Query OK, 0 rows affected (0.00 sec)mysql> INSERT INTO SALESSUMMARY    -> (product_name, total_sales, avg_unit_price, total_units_sold)    -> VALUES    -> ('cucumber', 100.25, 90, 2);mysql> SELECT * FROM SALESSUMMARY;+--------------+-------------+----------------+------------------+| product_name | total_sales | avg_unit_price | total_units_sold |+--------------+-------------+----------------+------------------+| cucumber     |      100.25 |          90.00 |                2 |+--------------+-------------+----------------+------------------+1 row in set (0.00 sec)

 当你下达 SHOW TABLES 命令的时候,临时表是不会出现在结果列表当中的。现在,如果你退出 MySQL 会话,然后再执行 SELECT 命令的话,你将不能从数据库中取回任何数据,你的临时表也已经不复存在了。


删除临时表


 默认情况下,所有的临时表都由 MySQL 在数据库连接关闭时删除。不过,有时候你还是会想要在会话期间将其删除,此时你需要使用 DROP TABLE 命令来达到目的。

 下面是删除临时表的示例:

mysql> CREATE TEMPORARY TABLE SALESSUMMARY (    -> product_name VARCHAR(50) NOT NULL    -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00    -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00    -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0);Query OK, 0 rows affected (0.00 sec)mysql> INSERT INTO SALESSUMMARY    -> (product_name, total_sales, avg_unit_price, total_units_sold)    -> VALUES    -> ('cucumber', 100.25, 90, 2);mysql> SELECT * FROM SALESSUMMARY;+--------------+-------------+----------------+------------------+| product_name | total_sales | avg_unit_price | total_units_sold |+--------------+-------------+----------------+------------------+| cucumber     |      100.25 |          90.00 |                2 |+--------------+-------------+----------------+------------------+1 row in set (0.00 sec)mysql> DROP TABLE SALESSUMMARY;mysql>  SELECT * FROM SALESSUMMARY;ERROR 1146: Table 'TUTORIALS.SALESSUMMARY' doesn't exist

SQL 用于各种数据库的数据类型


 Microsoft Access、MySQL 和 SQL Server 所使用的数据类型和范围。


Microsoft Access 数据类型


数据类型描述存储
Text用于文本或文本与数字的组合。最多 255 个字符。
MemoMemo 用于更大数量的文本。最多存储 65,536 个字符。注释:无法对 memo 字段进行排序。不过它们是可搜索的。
Byte允许 0 到 255 的数字。1 字节
Integer允许介于 -32,768 与 32,767 之间的全部数字。2 字节
Long允许介于 -2,147,483,648 与 2,147,483,647 之间的全部数字。4 字节
Single单精度浮点。处理大多数小数。4 字节
Double双精度浮点。处理大多数小数。8 字节
Currency用于货币。支持 15 位的元,外加 4 位小数。提示:您可以选择使用哪个国家的货币。8 字节
AutoNumberAutoNumber 字段自动为每条记录分配数字,通常从 1 开始。4 字节
Date/Time用于日期和时间8 字节
Yes/No逻辑字段,可以显示为 Yes/No、True/False 或 On/Off。在代码中,使用常量 True 和 False (等价于 1 和 0)。注释:Yes/No 字段中不允许 Null 值1 比特
Ole Object可以存储图片、音频、视频或其他 BLOBs(Binary Large OBjects)。最多 1GB
Hyperlink包含指向其他文件的链接,包括网页。
Lookup Wizard允许您创建一个可从下拉列表中进行选择的选项列表。4 字节

MySQL 数据类型


 在 MySQL 中,有三种主要的类型:Text(文本)、Number(数字)和 Date/Time(日期/时间)类型。

 Text 类型:

数据类型描述
CHAR(size)保存固定长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的长度。最多 255 个字符。
VARCHAR(size)保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。注释:如果值的长度大于 255,则被转换为 TEXT 类型。
TINYTEXT存放最大长度为 255 个字符的字符串。
TEXT存放最大长度为 65,535 个字符的字符串。
BLOB用于 BLOBs(Binary Large OBjects)。存放最多 65,535 字节的数据。
MEDIUMTEXT存放最大长度为 16,777,215 个字符的字符串。
MEDIUMBLOB用于 BLOBs(Binary Large OBjects)。存放最多 16,777,215 字节的数据。
LONGTEXT存放最大长度为 4,294,967,295 个字符的字符串。
LONGBLOB用于 BLOBs (Binary Large OBjects)。存放最多 4,294,967,295 字节的数据。
ENUM(x,y,z,etc.)允许您输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。

注释:这些值是按照您输入的顺序排序的。

可以按照此格式输入可能的值: ENUM('X','Y','Z')

SET与 ENUM 类似,不同的是,SET 最多只能包含 64 个列表项且 SET 可存储一个以上的选择。

 

 Number 类型:

数据类型描述
TINYINT(size)-128 到 127 常规。0 到 255 无符号*。在括号中规定最大位数。
SMALLINT(size)-32768 到 32767 常规。0 到 65535 无符号*。在括号中规定最大位数。
MEDIUMINT(size)-8388608 到 8388607 普通。0 to 16777215 无符号*。在括号中规定最大位数。
INT(size)-2147483648 到 2147483647 常规。0 到 4294967295 无符号*。在括号中规定最大位数。
BIGINT(size)-9223372036854775808 到 9223372036854775807 常规。0 到 18446744073709551615 无符号*。在括号中规定最大位数。
FLOAT(size,d)带有浮动小数点的小数字。在 size 参数中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
DOUBLE(size,d)带有浮动小数点的大数字。在 size 参数中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
DECIMAL(size,d)作为字符串存储的 DOUBLE 类型,允许固定的小数点。在 size 参数中规定最大位数。在 d 参数中规定小数点右侧的最大位数。

注意:这些整数类型拥有额外的选项 UNSIGNED。通常,整数可以是负数或正数。如果添加 UNSIGNED 属性,那么范围将从 0 开始,而不是某个负数。


 Date 类型:

数据类型描述
DATE()日期。格式:YYYY-MM-DD

注释:支持的范围是从 '1000-01-01' 到 '9999-12-31'

DATETIME()*日期和时间的组合。格式:YYYY-MM-DD HH:MM:SS

注释:支持的范围是从 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'

TIMESTAMP()*时间戳。TIMESTAMP 值使用 Unix 纪元('1970-01-01 00:00:00' UTC) 至今的秒数来存储。格式:YYYY-MM-DD HH:MM:SS

注释:支持的范围是从 '1970-01-01 00:00:01' UTC 到 '2038-01-09 03:14:07' UTC

TIME()时间。格式:HH:MM:SS

注释:支持的范围是从 '-838:59:59' 到 '838:59:59'

YEAR()2 位或 4 位格式的年。

注释:4 位格式所允许的值:1901 到 2155。2 位格式所允许的值:70 到 69,表示从 1970 到 2069。

注意:即便 DATETIME 和 TIMESTAMP 返回相同的格式,它们的工作方式很不同。在 INSERT 或 UPDATE 查询中,TIMESTAMP 自动把自身设置为当前的日期和时间。TIMESTAMP 也接受不同的格式,比如 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD。


SQL Server 数据类型


 String 类型:

数据类型描述存储
char(n)固定长度的字符串。最多 8,000 个字符。Defined width
varchar(n)可变长度的字符串。最多 8,000 个字符。2 bytes + number of chars
varchar(max)可变长度的字符串。最多 1,073,741,824 个字符。2 bytes + number of chars
text可变长度的字符串。最多 2GB 文本数据。4 bytes + number of chars
nchar固定长度的 Unicode 字符串。最多 4,000 个字符。Defined width x 2
nvarchar可变长度的 Unicode 字符串。最多 4,000 个字符。
nvarchar(max)可变长度的 Unicode 字符串。最多 536,870,912 个字符。
ntext可变长度的 Unicode 字符串。最多 2GB 文本数据。
bit允许 0、1 或 NULL
binary(n)固定长度的二进制字符串。最多 8,000 字节。
varbinary可变长度的二进制字符串。最多 8,000 字节。
varbinary(max)可变长度的二进制字符串。最多 2GB。
image可变长度的二进制字符串。最多 2GB。


 Number 类型:

数据类型描述存储
tinyint允许从 0 到 255 的所有数字。1 字节
smallint允许介于 -32,768 与 32,767 的所有数字。2 字节
int允许介于 -2,147,483,648 与 2,147,483,647 的所有数字。4 字节
bigint允许介于 -9,223,372,036,854,775,808 与 9,223,372,036,854,775,807 之间的所有数字。8 字节
decimal(p,s)固定精度和比例的数字。

允许从 -10^38 +1 到 10^38 -1 之间的数字。

p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。

s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。

5-17 字节
numeric(p,s)固定精度和比例的数字。

允许从 -10^38 +1 到 10^38 -1 之间的数字。

p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。

s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。

5-17 字节
smallmoney介于 -214,748.3648 与 214,748.3647 之间的货币数据。4 字节
money介于 -922,337,203,685,477.5808 与 922,337,203,685,477.5807 之间的货币数据。8 字节
float(n)从 -1.79E + 308 到 1.79E + 308 的浮动精度数字数据。

n 参数指示该字段保存 4 字节还是 8 字节。float(24) 保存 4 字节,而 float(53) 保存 8 字节。n 的默认值是 53。

4 或 8 字节
real从 -3.40E + 38 到 3.40E + 38 的浮动精度数字数据。4 字节


 Date 类型:

数据类型描述存储
datetime从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 3.33 毫秒。8 字节
datetime2从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 100 纳秒。6-8 字节
smalldatetime从 1900 年 1 月 1 日 到 2079 年 6 月 6 日,精度为 1 分钟。4 字节
date仅存储日期。从 0001 年 1 月 1 日 到 9999 年 12 月 31 日。3 bytes
time仅存储时间。精度为 100 纳秒。3-5 字节
datetimeoffset与 datetime2 相同,外加时区偏移。8-10 字节
timestamp存储唯一的数字,每当创建或修改某行时,该数字会更新。timestamp 值基于内部时钟,不对应真实时间。每个表只能有一个 timestamp 变量。 


 其他数据类型:

数据类型描述
sql_variant存储最多 8,000 字节不同数据类型的数据,除了 text、ntext 以及 timestamp。
uniqueidentifier存储全局唯一标识符 (GUID)。
xml存储 XML 格式化数据。最多 2GB。
cursor存储对用于数据库操作的指针的引用。
table存储结果集,供稍后处理。


SQL 函数


 SQL 拥有很多可用于计数和计算的内建函数。


SQL Aggregate 函数


 SQL Aggregate 函数计算从列中取得的值,返回一个单一的值。

 有用的 Aggregate 函数:

  • AVG() - 返回平均值
  • COUNT() - 返回行数
  • FIRST() - 返回第一个记录的值
  • LAST() - 返回最后一个记录的值
  • MAX() - 返回最大值
  • MIN() - 返回最小值
  • SUM() - 返回总和

SQL Scalar 函数


 SQL Scalar 函数基于输入值,返回一个单一的值。

 有用的 Scalar 函数:

  • UCASE() - 将某个字段转换为大写
  • LCASE() - 将某个字段转换为小写
  • MID() - 从某个文本字段提取字符
  • LEN() - 返回某个文本字段的长度
  • ROUND() - 对某个数值字段进行指定小数位数的四舍五入
  • NOW() - 返回当前的系统日期和时间
  • FORMAT() - 格式化某个字段的显示方式

提示:在下面的章节,我们会详细讲解 Aggregate 函数和 Scalar 函数。


章节小测


 现在,通过以下题目测测看您对“SQL 函数”的掌握程度吧!

 SQL 函数:在本部分测验中,您将练习使用 SQL 函数。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费



SQL MAX() 函数


MAX() 函数

 MAX() 函数返回所选列的最大值。

SQL MAX() 语法

SELECT MAX(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars22
5Chef Anton's Gumbo Mix2236 boxes21.35

SQL MAX() 实例


 以下SQL语句查找最昂贵的产品的价格:

实例

SELECT MAX(Price) AS LargestPriceFROM Products;

结果集类似这样:

LargestPrice22


SQL MIN() Function


MIN() 函数

 MIN() 函数返回所选列的最小值。

SQL MIN() 语法

SELECT MIN(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars22
5Chef Anton's Gumbo Mix2236 boxes21.35

SQL MIN() 实例


 以下SQL语句查找最便宜的产品的价格:

实例

SELECT MIN(Price) AS SmallestPrice
FROM Products;


章节小测


 现在,通过以下题目测测看您对“SQL MIN() 函数”的掌握程度吧!

 SQL MIN() 函数:在本部分测验中,您将练习使用 SQL MIN() 函数完成从指定表中选择相应的语句,并按照条件进行筛选。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

COUNT() 函数返回匹配指定条件的行数。

SQL COUNT(column_name) 语法

COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):

SELECT COUNT(column_name) FROM table_name;

SQL COUNT(*) 语法

COUNT(*) 函数返回表中的记录数:

SELECT COUNT(*) FROM table_name;

SQL COUNT(DISTINCT column_name) 语法

COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:

SELECT COUNT(DISTINCT column_name) FROM table_name;

注释:COUNT(DISTINCT) 适用于 ORACLE 和 Microsoft SQL Server,但是无法用于 Microsoft Access。

演示数据库

在本教程中,我们将使用 RUNOOB 样本数据库。

下面是选自 "access_log" 表的数据:

+-----+---------+-------+------------+
| aid | site_id | count | date       |
+-----+---------+-------+------------+
|   1 |       1 |   45 | 2016-05-10 |
|   2 |       3 |   100 | 2016-05-13 |
|   3 |       1 |   230 | 2016-05-14 |
|   4 |       2 |   10 | 2016-05-14 |
|   5 |       5 |   205 | 2016-05-14 |
|   6 |       4 |   13 | 2016-05-15 |
|   7 |       3 |   220 | 2016-05-15 |
|   8 |       5 |   545 | 2016-05-16 |
|   9 |       3 |   201 | 2016-05-17 |
+-----+---------+-------+------------+

SQL COUNT(column_name) 实例

下面的 SQL 语句计算 "access_log" 表中 "site_id"=3 的总访问量:

实例

SELECT COUNT(count) AS nums FROM access_logWHERE site_id=3;

SQL COUNT(*) 实例

下面的 SQL 语句计算 "access_log" 表中总记录数:

实例

SELECT COUNT(*) AS nums FROM access_log;

执行以上 SQL 输出结果如下:

img

SQL COUNT(DISTINCT column_name) 实例

下面的 SQL 语句计算 "access_log" 表中不同 site_id 的记录数:

实例

SELECT COUNT(DISTINCT site_id) AS nums FROM access_log;

执行以上 SQL 输出结果如下:

count2


SQL AVG() 函数


AVG() 函数

 AVG() 函数返回数字列的平均值。

SQL AVG() 语法

SELECT AVG(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars22
5Chef Anton's Gumbo Mix2236 boxes21.35

SQL AVG() 实例


 以下SQL语句查找所有产品的平均价格:

实例

SELECT AVG(Price)
FROM Products;

 下面的 SQL 语句选择价格高于平均价格的 "ProductName" 和 "Price" 记录:

实例

SELECT ProductName, Price FROM Products
WHERE Price>(SELECT AVG(Price) FROM Products);


SQL SUM() 函数


 SUM() 函数返回数字列的总和。

SQL SUM() 语法

SELECT SUM(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "OrderDetails" 表的数据:

OrderDetailIDOrderIDProductIDQuantity
1102481112
2102484210
310248725
410249149
5102495140

SQL SUM() 实例


 下面的 SQL 语句查找 "OrderDetails" 表的 "Quantity" 字段的总数:

实例

SELECT SUM(Quantity)
FROM OrderDetails;


章节小测


 现在,通过以下题目测测看您对“SQL SUM() 函数”的掌握程度吧!

 SQL SUM() 函数:在本部分测验中,您将练习使用 SQL SUM() 函数。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL 日期函数


 下面的列表中是 SQL 中所有与日期和时间相关的重要函数。你所用的 RDBMS 可能会支持更多其他的函数。下面的列表基于 MySQL 关系型数据库管理系统。

名称描述
ADDDATE()增加日期
ADDTIME()增加时间
CONVERT_TZ()将当前时区更改为另一时区
CURDATE()返回当前日期
CURRENT_DATE(), CURRENT_DATECURDATE() 的别名
CURRENT_TIME(), CURRENT_TIMECURTIME() 的别名
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMPNOW() 的别名
CURTIME()返回当前时间
DATE_ADD()将两个日期相加
DATE_FORMAT()按照指定格式格式化日期
DATE_SUB()将两个日期相减
DATE()从 date 或者 datetime 表达式中提取出日期部分
DATEDIFF()将两个日期相减
DAY()DAYOFMONTH() 的别名
DAYNAME()返回某天在用星期中的名称
DAYOFMONTH()返回某天是当月的第几天 (1-31)
DAYOFWEEK()返回某天是该星期的第几天
DAYOFYEAR()返回某天是一年中的第几天(1-366)
EXTRACT提取日期中的某一部分
FROM_DAYS()将天数转换为日期
FROM_UNIXTIME()将某个日期格式化为 UNIX 时间戳
HOUR()提取小时
LAST_DAY返回参数日期所在月份的最后一天
LOCALTIME(), LOCALTIMENOW() 的别名
LOCALTIMESTAMP, LOCALTIMESTAMP()NOW() 的别名
MAKEDATE()利用年份和某天在该年所处的天数来创建日期
MAKETIMEMAKETIME()
MICROSECOND()由参数返回微秒
MINUTE()由参数返回分钟
MONTH()返回日期参数的月份
MONTHNAME()返回月份的名字
NOW()返回当前日期和时间
PERIOD_ADD()向年月格式的日期数据之间添加一段时间
PERIOD_DIFF()返回两个年月格式的日期数据之间的月份数
QUARTER()返回日期参数所在的季度
SEC_TO_TIME()将秒数转换为 'HH:MM:SS' 格式
SECOND()返回参数中的秒数 (0-59)
STR_TO_DATE()将字符串转换为日期数据
SUBDATE()以三个参数调用的时候是 DATE_SUB() 的同义词
SUBTIME()减去时间
SYSDATE()返回函数执行的时的时刻
TIME_FORMAT()格式化时间
TIME_TO_SEC()将时间参数转换为秒数
TIME()返回参数表达式中的时间部分
TIMEDIFF()将两个时间相减
TIMESTAMP()只有一个参数时,该函数返回 date 或者 datetime 表达式。当有两个参数时,将两个参数相加。
TIMESTAMPADD()在 datetime 表达式上加上一段时间
TIMESTAMPDIFF()在 datetime 表达式上减去一段时间
TO_DAYS()将日期参数转换为天数
UNIX_TIMESTAMP()返回 UNIX 时间戳
UTC_DATE()返回当前 UTC 日期
UTC_TIME()返回当前 UTC 时间
UTC_TIMESTAMP()返回当前 UTC 日期和时间
WEEK()返回参数的星期数
WEEKDAY()返回日期参数时一个星期中的第几天
WEEKOFYEAR()返回日期参数是日历上的第几周 (1-53)
YEAR()返回日期参数中的年份
YEARWEEK()返回年份和星期

ADDDATE(date, INTERVAL expr unit), ADDDATE(expr, days)


 如果调用时第二个参数为 INTERVAL 形式的话,ADDDATE() 就是 DATE_ADD() 的同义词。同样的情况下,SUBDATE() 是 DATE_SUB() 的同义词。有关 INTERVAL 单位参数的信息,见有关 DATE_ADD() 的讨论。

mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| DATE_ADD('1998-01-02', INTERVAL 31 DAY)                 |+---------------------------------------------------------+| 1998-02-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| ADDDATE('1998-01-02', INTERVAL 31 DAY)                  |+---------------------------------------------------------+| 1998-02-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

 如果调用时第二个参数为天数形式的话,则 MySQL 会将其作为整数加到 expr 上。

mysql> SELECT ADDDATE('1998-01-02', 31);+---------------------------------------------------------+| DATE_ADD('1998-01-02', INTERVAL 31 DAY)                 |+---------------------------------------------------------+| 1998-02-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

ADDTIME(expr1,expr2)


 ADDTIME() 将 expr2 加到 expr1 上,并返回结果。expr1 为 time 或者 datetime 表达式,expr2 为 time 表达式。

mysql> SELECT ADDTIME('1997-12-31 23:59:59.999999','1 1:1:1.000002');+---------------------------------------------------------+| DATE_ADD('1997-12-31 23:59:59.999999','1 1:1:1.000002') |+---------------------------------------------------------+| 1998-01-02 01:01:01.000001                              |+---------------------------------------------------------+1 row in set (0.00 sec)

CONVERT_TZ(dt,from_tz,to_tz)


 该函数将 datetime 类型的值 dt 的时区从 from_dt 转换为 to_dt,并返回结果。如果参数无效,则函数返回 NULL。

mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');+---------------------------------------------------------+| CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')           |+---------------------------------------------------------+| 2004-01-01 13:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');+---------------------------------------------------------+| CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00')     |+---------------------------------------------------------+| 2004-01-01 22:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

CURDATE()


 以 'YYYY-MM-DD'(字符串) 或者 YYYYMMDD(数值) 的形式返回当前日期, 具体形式取决于函数处于字符串还是数值型的上下文环境中。

mysql> SELECT CURDATE();+---------------------------------------------------------+| CURDATE()                                               |+---------------------------------------------------------+| 1997-12-15                                              |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT CURDATE() + 0;+---------------------------------------------------------+| CURDATE() + 0                                           |+---------------------------------------------------------+| 19971215                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

CURRENT_DATE and CURRENT_DATE()


 CURRENT_DATE 和 CURRENT_DATE() 是 CURDATE() 的别名。


CURTIME()


 以 'HH:MM:SS'(字符串) 或者 HHMMSS(数值) 的形式返回当前时间, 具体形式取决于函数处于字符串还是数值型的上下文环境中。该函数按照当前时区来表示返回值。

mysql> SELECT CURTIME();+---------------------------------------------------------+| CURTIME()                                               |+---------------------------------------------------------+| 23:50:26                                                |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT CURTIME() + 0;+---------------------------------------------------------+| CURTIME() + 0                                           |+---------------------------------------------------------+| 235026                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

CURRENT_TIME and CURRENT_TIME()


 CURRENT_TIME 和 CURRENT_TIME() 是 CURTIME() 的别名。


CURRENT_TIMESTAMP and CURRENT_TIMESTAMP()


 CURRENT_TIMESTAMP 和 CURRENT_TIMESTAMP() 是 NOW() 的别名。


DATE(expr)


 提取 date 表达式或者 datetime 表达式中的日期部分。

mysql> SELECT DATE('2003-12-31 01:02:03');+---------------------------------------------------------+| DATE('2003-12-31 01:02:03')                             |+---------------------------------------------------------+|  2003-12-31                                             |+---------------------------------------------------------+1 row in set (0.00 sec)

DATEDIFF(expr1,expr2)


 DATEDIFF() 返回 expr1 和 expr2 的差,以天数的形式表示。expr1 和 expr2 应为 date 或者 datetime 表达式。只有参数的日期部分参与了计算。

mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');+---------------------------------------------------------+| DATEDIFF('1997-12-31 23:59:59','1997-12-30')            |+---------------------------------------------------------+| 1                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

DATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)


 这些函数进行有关日期的算术运算。date 是一个 DATETIME 或者 DATE 类型的值,指明了起始时间。expr 表达式则是 date 要增加或者减去的时间间隔。expr 是一个字符串,可以以 '-' 开始来表示负时间区间。 unit 是一个关键词,指明了expr 的单位。

 INTERVAL 关键字和 unit(单位)指示符不区分大小写。

 下表列出了对于每种单位,expr 应有的形式。

unit 值expr 应有的格式
MICROSECOND微秒
SECOND
MINUTE分钟
HOUR小时
DAY
WEEK星期
MONTH
QUARTER季度
YEAR
SECOND_MICROSECOND'秒.微秒'
MINUTE_MICROSECOND'分.微秒'
MINUTE_SECOND'分:秒'
HOUR_MICROSECOND'小时.微秒'
HOUR_SECOND'时:分:秒'
HOUR_MINUTE'时:分'
DAY_MICROSECOND'天.微秒'
DAY_SECOND'天 时:分:秒'
DAY_MINUTE'天 时:分'
DAY_HOUR'天 时'
YEAR_MONTH'年-月'

 QUARTER 和 WEEK 自 MySQL 5.0.0 起受到支持。

mysql> SELECT DATE_ADD('1997-12-31 23:59:59',     -> INTERVAL '1:1' MINUTE_SECOND);+---------------------------------------------------------+| DATE_ADD('1997-12-31 23:59:59', INTERVAL...             |+---------------------------------------------------------+| 1998-01-01 00:01:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);+---------------------------------------------------------+| DATE_ADD('1999-01-01', INTERVAL 1 HOUR)                 |+---------------------------------------------------------+| 1999-01-01 01:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

DATE_FORMAT(date,format)


 根据格式字符串对日期值进行格式化。

 下面这些占位符可以用在格式字符串中,'%' 必须出现在特定的格式字符之前。

占位符描述
%a简写的星期名称(Sun..Sat)
%b简写的月份名称 (Jan..Dec)
%c月份,以数值形式表示(0..12)
%D月份中的日期,带有英文后缀(0th,1st,2nd,3rd 等等)
%d月份中的日期,以数值表示 (00..31)
%e月份中的日期,以数值表示 (0..31)
%f微秒(000000..999999)
%H小时(00..23)
%h小时(01..12)
%I小时(01..12)
%i分钟,以数值表示(00..59)
%j一年中的第几天(001..366)
%k小时(0..23)
%l小时(1..12)
%M月份的名称(January..December)
%m月份,以数值形式表示(00..12)
%pAM 或者 PM
%r时间,12 小时制(hh:mm:ss followed by AM or PM)
%S秒(00..59)
%s秒(00..59)
%T时间,24小时制(hh:mm:ss)
%U星期(00..53),此处星期日为一周的第一天
%u星期(00..53),此处星期一为一周的第一天
%V星期(01..53),此处星期日为一周的第一天;与 %X 一起使用。
%v星期(01..53),此处星期一为一周的第一天;与 %x 一起使用。
%W一周中日期的名称(Sunday..Saturday)
%w一周中的第几天(0=Sunday..6=Saturday)
%X以星期日为第一天的周所处的年份,四位数字表示;同 %V 一起使用。
%x以星期一为第一天的周所处的年份,四位数字表示;同 %v 一起使用。
%Y年份,四位数字表示。
%y年份,两位数字表示。
%%% 字面值
%xx,针对任何以上没有列出的情况。
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');+---------------------------------------------------------+| DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y')          |+---------------------------------------------------------+| Saturday October 1997                                   |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00'    -> '%H %k %I %r %T %S %w');+---------------------------------------------------------+| DATE_FORMAT('1997-10-04 22:23:00.......                 |+---------------------------------------------------------+|  22 22 10 10:23:00 PM 22:23:00 00 6                     |+---------------------------------------------------------+1 row in set (0.00 sec)

DATE_SUB(date,INTERVAL expr unit)


 同 DATE_ADD() 函数相似。


DAY(date)


 DAY() 是 DAYOFMONTH() 的别名。


DAYNAME(date)


 返回 date 在星期中的名称。

mysql> SELECT DAYNAME('1998-02-05');+---------------------------------------------------------+| DAYNAME('1998-02-05')                                   |+---------------------------------------------------------+| Thursday                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

DAYOFMONTH(date)


 返回 date 是当月的第几天,范围为 0 到 31。

mysql> SELECT DAYOFMONTH('1998-02-03');+---------------------------------------------------------+| DAYOFMONTH('1998-02-03')                                |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

DAYOFWEEK(date)


 返回 date 是其所在星期的第几天(1 = Sunday, 2 = Monday,.., 7 = Saturday),这里一星期中日期的名称与数字的对应关系符合 ODBC 标准。

mysql> SELECT DAYOFWEEK('1998-02-03');+---------------------------------------------------------+|DAYOFWEEK('1998-02-03')                                  |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

DAYOFYEAR(date)


 返回 date 是当年的第几天,范围为 1 到 366。

mysql> SELECT DAYOFYEAR('1998-02-03');+---------------------------------------------------------+| DAYOFYEAR('1998-02-03')                                 |+---------------------------------------------------------+| 34                                                      |+---------------------------------------------------------+1 row in set (0.00 sec)

EXTRACT(unit FROM date)


 EXTRACT() 与 DATE_ADD() 和 DATE_SUB() 使用相同的表示单位的占位符,其作用是提取日期值中相应的组成部分,而不是进行日期运算。

mysql> SELECT EXTRACT(YEAR FROM '1999-07-02');+---------------------------------------------------------+| EXTRACT(YEAR FROM '1999-07-02')                         |+---------------------------------------------------------+| 1999                                                    |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03');+---------------------------------------------------------+| EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03')          |+---------------------------------------------------------+| 199907                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

FROM_DAYS(N)


 给出天数 N,返回 DATE 值。

mysql> SELECT FROM_DAYS(729669);+---------------------------------------------------------+| FROM_DAYS(729669)                                       |+---------------------------------------------------------+| 1997-10-07                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

 在使用 FROM_DAYS() 处理比较老的日期的时候应当特别小心,该函数不适用于格里高利历诞生(1582)之前的日期。


FROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)


 返回 UNIX 时间戳对应的日期值,根据函数所处的上下文环境不同,返回值得格式也不同,字符串上下文返回格式为 'YYYY-MM-DD HH:MM:SS',数值型上下文返回格式则为 YYYYMMDDHHMMSS。返回值的时区为系统当前时区。UNIX 时间戳是一种系统内部时间表示,例如 UNIX_TIMESTAMP() 的返回值。

 如果给定格式的话,返回结果将会根据格式字符串进行格式化,其规则同 DATE_FORMAT() 函数。

mysql> SELECT FROM_UNIXTIME(875996580);+---------------------------------------------------------+| FROM_UNIXTIME(875996580)                                |+---------------------------------------------------------+| 1997-10-04 22:23:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

HOUR(time)


 返回时间值的小时部分。对于一天中的时间来说,返回值的范围为 0 到 23。不过,TIME 类型的值可以大得多,所以 HOUR 函数可以返回比 23 大的值。

mysql> SELECT HOUR('10:05:03');+---------------------------------------------------------+| HOUR('10:05:03')                                        |+---------------------------------------------------------+| 10                                                      |+---------------------------------------------------------+1 row in set (0.00 sec)

LAST_DAY(date)


 返回 date 或者 datetime 值所在月份的最后一天。如果参数无效的话,返回 NULL。

mysql> SELECT LAST_DAY('2003-02-05');+---------------------------------------------------------+| LAST_DAY('2003-02-05')                                  |+---------------------------------------------------------+| 2003-02-28                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

LOCALTIME and LOCALTIME()


 LOCALTIME 和 LOCALTIME() 是 NOW() 的别名。


LOCALTIMESTAMP and LOCALTIMESTAMP()


 LOCALTIMESTAMP 和 LOCALTIMESTAMP() 是 NOW() 的别名。


MAKEDATE(year,dayofyear)


 给定年份和(某天在一年中)的天数,返回对应的日期值。天数必须大于 0,否则返回值为 NULL。

mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);+---------------------------------------------------------+| MAKEDATE(2001,31), MAKEDATE(2001,32)                    |+---------------------------------------------------------+| '2001-01-31', '2001-02-01'                              |+---------------------------------------------------------+1 row in set (0.00 sec)

MAKETIME(hour,minute,second)


 根据参数给出的时、分、秒,返回对应的时间值。

mysql> SELECT MAKETIME(12,15,30);+---------------------------------------------------------+| MAKETIME(12,15,30)                                      |+---------------------------------------------------------+| '12:15:30'                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

MICROSECOND(expr)


 根据 time 或者 datetime 表达式 expr,返回微秒数,结果在 0 到 999999 之间。

mysql> SELECT MICROSECOND('12:00:00.123456');+---------------------------------------------------------+| MICROSECOND('12:00:00.123456')                          |+---------------------------------------------------------+| 123456                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

MINUTE(time)


 返回时间型值中的分钟部分,范围为 0 到 59。

mysql> SELECT MINUTE('98-02-03 10:05:03');+---------------------------------------------------------+| MINUTE('98-02-03 10:05:03')                             |+---------------------------------------------------------+| 5                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

MONTH(date)


 返回日期型值中的月份,范围为 0 到 12。

mysql> SELECT MONTH('1998-02-03')+---------------------------------------------------------+| MONTH('1998-02-03')                                     |+---------------------------------------------------------+| 2                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

MONTHNAME(date)


 返回日期型值所处月份的全名。

mysql> SELECT MONTHNAME('1998-02-05');+---------------------------------------------------------+| MONTHNAME('1998-02-05')                                 |+---------------------------------------------------------+| February                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

NOW()


 返回当前的日期和时间,结果的格式为 'YYYY-MM-DD HH:MM:SS' 或者 YYYYMMDDHHMMSS,如果函数上下文环境为字符型,则返回前者,否则如果函数处于数值型的上下文环境,则返回后者。返回值的时区为系统当前时区。

mysql> SELECT NOW();+---------------------------------------------------------+| NOW()                                                   |+---------------------------------------------------------+| 1997-12-15 23:50:26                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

PERIOD_ADD(P,N)


 在时间 P(格式为 YYMM 或者 YYYYMM)上加上 N 个月,结果格式为 YYYYMM。注意,时间参数 P 并不是日期型值。

mysql> SELECT PERIOD_ADD(9801,2);+---------------------------------------------------------+| PERIOD_ADD(9801,2)                                      |+---------------------------------------------------------+| 199803                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

PERIOD_DIFF(P1,P2)


 返回时间 P1 和 P2 之间相差的月份。 P1 和 P2 的格式应为 YYMM 或者 YYYYMM。注意I,P1 和 P2 不是日期型值。

mysql> SELECT PERIOD_DIFF(9802,199703);+---------------------------------------------------------+| PERIOD_DIFF(9802,199703)                                |+---------------------------------------------------------+| 11                                                      |+---------------------------------------------------------+1 row in set (0.00 sec)

QUARTER(date)


 返回日期型值 date 所处的季度值,范围为 1 到 4。

mysql> SELECT QUARTER('98-04-01');+---------------------------------------------------------+| QUARTER('98-04-01')                                     |+---------------------------------------------------------+| 2                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

SECOND(time)


 返回时间型值中秒的部分,范围为 0 到 59。

mysql> SELECT SECOND('10:05:03');+---------------------------------------------------------+| SECOND('10:05:03')                                      |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

SEC_TO_TIME(seconds)


 将参数中的秒数转换为时分秒的格式 'HH:MM:SS' 或者 HHMMSS,如果函数所处的上下文为字符串型,则返回前者,否则如果上下文环境为数值型,则返回后者。


STR_TO_DATE(str,format)


 这是 DATE_FORMATE() 函数的逆函数,其参数为表示时间和日期的字符串 str 和一个格式字符串 format。如果格式字符串中既有日期又有时间,则 STR_TO_DATE() 返回 DATETIME() 型的值,否则返回日期型(DATE)或者时间型(TIME)的值。

mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y');+---------------------------------------------------------+| STR_TO_DATE('04/31/2004', '%m/%d/%Y')                   |+---------------------------------------------------------+| 2004-04-31                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

SUBDATE(date,INTERVAL expr unit) and SUBDATE(expr,days)


 当第二个参数为 INTERVAL 形式时,SUBDATE() 就是 DATE_SUB() 的别名。INTERVAL 参数中单位的信息,请见有关 DATE_ADD() 的讨论。

mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| DATE_SUB('1998-01-02', INTERVAL 31 DAY)                 |+---------------------------------------------------------+| 1997-12-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| SUBDATE('1998-01-02', INTERVAL 31 DAY)                  |+---------------------------------------------------------+| 1997-12-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

SUBTIME(expr1,expr2)


 SUBTIME() 返回 expr1-expr2,结果的格式与 expr1 相同。expr1 是一个时间型(time)或者 datetime 型的表达式,expr2 是时间型值。


SYSDATE()


 返回当前的日期和时间,格式为 'YYYY-MM-DD HH:MM:SS' 或 YYYYMMDDHHMMSS,如果函数所处的上下文环境为字符串,则返回前者,否则如果上下文环境为数值型,则返回后者。

mysql> SELECT SYSDATE();+---------------------------------------------------------+| SYSDATE()                                               |+---------------------------------------------------------+| 2006-04-12 13:47:44                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

TIME(expr)


 提取时间型或者 datetime 型表达式 expr 中的时间部分,返回结果为字符串。

mysql> SELECT TIME('2003-12-31 01:02:03');+---------------------------------------------------------+| TIME('2003-12-31 01:02:03')                             |+---------------------------------------------------------+| 01:02:03                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMEDIFF(expr1,expr2)


 TIMEDIFF() 返回 expr1-expr2,结果为时间型值。expr1 和 expr2 可以为时间型或者 datetime 型表达式,不过二者必须为相同类型。

mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001',    -> '1997-12-30 01:01:01.000002');+---------------------------------------------------------+| TIMEDIFF('1997-12-31 23:59:59.000001'.....              |+---------------------------------------------------------+|  46:58:57.999999                                        |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMESTAMP(expr), TIMESTAMP(expr1,expr2)


 只有一个参数的时候,该函数由日期型或者 datetime 型表达式返回一个 datetime 型值。有两个参数的时候,该函数将 expr2 加到日期型或 datetime 型值 expr1 上,并返回 datetime 型的结果。

mysql> SELECT TIMESTAMP('2003-12-31');+---------------------------------------------------------+| TIMESTAMP('2003-12-31')                                 |+---------------------------------------------------------+| 2003-12-31 00:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMESTAMPADD(unit,interval,datetime_expr)


 将整数型的表达式 interval 加到日期型或者 datetime 型表达式 datetime_expr 上。单位由 unit 参数给出,其取值应为以下几种中的一种:FRAC_SECOND、SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER 或者 YEAR。

 单位 unit 可以为上述关键字中的一个,也可以添加一个 SQLTSI 前缀,例如 DAY 和 SQL_TSI_DAY 都是合法的。

mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');+---------------------------------------------------------+| TIMESTAMPADD(MINUTE,1,'2003-01-02')                     |+---------------------------------------------------------+| 2003-01-02 00:01:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)


 返回日期型或者 datetime 型表达式 datetime_expr1 和 datetime_expr2 的差。结果的单位由 unit 参数给出,unit 的取值规定同 TIMESTAMPADD() 函数。

mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');+---------------------------------------------------------+| TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01')          |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

TIME_FORMAT(time,format)


 该函数使用起来类似 DATE_FORMAT() 函数,但是格式字符串 format 中只能有与小时、分钟和秒有关的那些占位符。

 如果时间型值的小时部分大于 23,则 %H 和 %k 格式占位符将会产生一个大于通常的 0-23 的值,其他与小时有关的占位符则会返回小时值除以 12 后的余数(modulo 12)。

mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');+---------------------------------------------------------+| TIME_FORMAT('100:00:00', '%H %k %h %I %l')              |+---------------------------------------------------------+| 100 100 04 04 4                                         |+---------------------------------------------------------+1 row in set (0.00 sec)

TIME_TO_SEC(time)


 将时间型值转换为秒。

mysql> SELECT TIME_TO_SEC('22:23:00');+---------------------------------------------------------+| TIME_TO_SEC('22:23:00')                                 |+---------------------------------------------------------+| 80580                                                   |+---------------------------------------------------------+1 row in set (0.00 sec)、

TO_DAYS(date)


 给定日期型值 date,返回天数(自公元 0 年以来的天数)。

mysql> SELECT TO_DAYS(950501);+---------------------------------------------------------+| TO_DAYS(950501)                                         |+---------------------------------------------------------+| 728779                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)


 不带任何参数时,该函数返回一个 unsigned integer 型的 UNIX 时间戳(自 '1970-01-01 00:00:00' UTC 以来的秒数)。如果有一个参数 date 的话,该函数返回自 '1970-01-01 00:00:00' UTC 至 date 的秒数。date 可以是日期型的字符串、DATETIME 型的字符串、时间戳或者 YYMMDD 或 YYYYMMDD 格式的数字。

mysql> SELECT UNIX_TIMESTAMP();+---------------------------------------------------------+| UNIX_TIMESTAMP()                                        |+---------------------------------------------------------+| 882226357                                               |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');+---------------------------------------------------------+| UNIX_TIMESTAMP('1997-10-04 22:23:00')                   |+---------------------------------------------------------+| 875996580                                               |+---------------------------------------------------------+1 row in set (0.00 sec)

UTC_DATE, UTC_DATE()


 返回当前 UTC 日期,格式为 'YYYY-MM-DD' 或者 YYYYMMDD,如果函数所处的上下文环境为字符串,则返回前者,否则如果上下文环境为数值型的,则返回后者。

mysql> SELECT UTC_DATE(), UTC_DATE() + 0;+---------------------------------------------------------+| UTC_DATE(), UTC_DATE() + 0                              |+---------------------------------------------------------+| 2003-08-14, 20030814                                    |+---------------------------------------------------------+1 row in set (0.00 sec)

UTC_TIME, UTC_TIME()


 返回当前 UTC 时间,格式为 'HH:MM:SS' 或者 HHMMSS,如果函数所处的上下文环境为字符串,则返回前者,否则如果上下文环境为数值型的,则返回后者。

mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;+---------------------------------------------------------+| UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0                    |+---------------------------------------------------------+| 2003-08-14 18:08:04, 20030814180804                     |+---------------------------------------------------------+1 row in set (0.00 sec)

WEEK(date[,mode])


 该函数将返回 date 所在的周是当年的第几周。两个参数的 WEEK() 函数的使你能够指明一周起始于周日还是周一,以及返回值的范围应该是 0 到 53,还是 1 到 53。如果 mode 参数被忽略,则将使用 default_week_format 系统变量。

Mode一周的第一天范围周 1 是第一周
0Sunday0-53该年包括一个星期天
1Monday0-53该年包含超过 3 天
2Sunday1-53该年包括一个星期天
3Monday1-53该年包含超过 3 天
4Sunday0-53该年包含超过 3 天
5Monday0-53该年包括一个星期一
6Sunday1-53该年包含超过 3 天
7Monday1-53该年包括一个星期一
mysql> SELECT WEEK('1998-02-20');+---------------------------------------------------------+| WEEK('1998-02-20')                                      |+---------------------------------------------------------+| 7                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

WEEKDAY(date)


 返回 date 是其所在星期的第几天 (0 = Monday, 1 = Tuesday, . 6 = Sunday)。

mysql> SELECT WEEKDAY('1998-02-03 22:23:00');+---------------------------------------------------------+| WEEKDAY('1998-02-03 22:23:00')                          |+---------------------------------------------------------+| 1                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

WEEKOFYEAR(date)


 返回 date 所在的周是当年的第几周,范围从 1 到 53. WEEKOFYEAR() 是一个兼容性函数,其功能同 WEEK(date, 3)相同。

mysql> SELECT WEEKOFYEAR('1998-02-20');+---------------------------------------------------------+| WEEKOFYEAR('1998-02-20')                                |+---------------------------------------------------------+| 8                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

YEAR(date)


 返回 date 的年份部分,范围为 1000 到 9999,对于日期 0 则返回 0。

mysql> SELECT YEAR('98-02-03');+---------------------------------------------------------+| YEAR('98-02-03')                                        |+---------------------------------------------------------+| 1998                                                    |+---------------------------------------------------------+1 row in set (0.00 sec)

YEARWEEK(date), YEARWEEK(date,mode)


 返回 date 所在的年份和周数。mode 参数意义与 WEEK() 函数的完全一样。对于一年中的第一周和最后一周来说,结果中的年份可能会和 date 参数中的年份不同。

mysql> SELECT YEARWEEK('1987-01-01');+---------------------------------------------------------+| YEAR('98-02-03')YEARWEEK('1987-01-01')                  |+---------------------------------------------------------+| 198653                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

注意,这里的周数同 WEEK() 返回的不同,因为 WEEK() 函数的返回值在给定年份的的上下文环境中得出。


SQL FIELD()函数


 SQL FIELD()函数实例代码教程 

 FIELD()函数返回的索引(从1开始的位置)的str在str1,str2,str3,...列表中。如果str没有找到,则返回0。

 就是用第一个参数str,跟后面的N个字符串参数中寻找,如果寻找到一模一样的字符串,则返回其索引位置

FIELD(str,str1,str2,str3,...)


 返回的索引(从1开始的位置)的str在str1,str2,str3,...列表中。如果str没有找到,则返回0。

例子

 在第2个位置找到了字符串“ej”

SQL> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');+---------------------------------------------------------+| FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo')          |+---------------------------------------------------------+| 2                                                       |+---------------------------------------------------------+1 row in set (0.00 sec) 


SQL FIRST() 函数


 FIRST() 函数返回指定的列中第一个记录的值。

SQL FIRST() 语法

SELECT FIRST(column_name) FROM table_name;      

注释:只有 MS Access 支持 FIRST() 函数。


SQL Server、MySQL 和 Oracle 中的 SQL FIRST() 工作区


SQL Server 语法

SELECT TOP 1 column_nameFROM table_nameORDER BY column_name ASC;  

实例

SELECT TOP 1 CustomerName FROM Customers                ORDER BY CustomerID ASC;      

MySQL 语法

SELECT column_name FROM table_name                ORDER BY column_name ASC                LIMIT 1; 

实例

SELECT CustomerName FROM Customers               ORDER BY CustomerID ASC                LIMIT 1;   

Oracle 语法

SELECT column_name FROM table_name                ORDER BY column_name ASC               WHERE ROWNUM <=1;                     

实例

SELECT CustomerName FROM Customers                ORDER BY CustomerID ASC                WHERE ROWNUM <=1;       

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL FIRST() 实例


 下面的 SQL 语句选取 "Customers" 表的 "CustomerName" 列中第一个记录的值:

实例

SELECT FIRST(CustomerName) AS FirstCustomer FROM Customers;


SQL LAST() 函数


 LAST() 函数返回指定的列中最后一个记录的值。

SQL LAST() 语法

SELECT LAST(column_name) FROM table_name;    

注释:只有 MS Access 支持 LAST() 函数。


SQL Server、MySQL 和 Oracle 中的 SQL LAST() 工作区


SQL Server 语法

SELECT TOP 1 column_nameFROM table_nameORDER BY column_name DESC;        

实例

SELECT TOP 1 CustomerName FROM Customers               ORDER BY CustomerID DESC;        

MySQL 语法

SELECT column_name FROM table_name                ORDER BY column_name DESC                LIMIT 1;        

实例

SELECT CustomerName FROM Customers                ORDER BY CustomerID DESC                LIMIT 1;     

Oracle 语法

SELECT column_name FROM table_name               ORDER BY column_name DESC                WHERE ROWNUM <=1;       

实例

SELECT CustomerName FROM Customers                ORDER BY CustomerID DESC                WHERE ROWNUM <=1;       

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LAST() Example


 下面的 SQL 语句选取 "Customers" 表的 "CustomerName" 列中最后一个记录的值:

实例

SELECT LAST(CustomerName) AS LastCustomer FROM Customers;


SQL GROUP BY 语句


 Aggregate 函数常常需要添加 GROUP BY 语句。

 GROUP BY语句通常与集合函数(COUNT,MAX,MIN,SUM,AVG)一起使用,以按一个或多个列对结果集进行分组。


GROUP BY 语句


 GROUP BY 语句用于结合 Aggregate 函数,根据一个或多个列对结果集进行分组。

SQL GROUP BY 语法

SELECT column_name(s)FROM table_nameWHERE conditionGROUP BY column_name(s)ORDER BY column_name(s);

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers"表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL GROUP BY示例


 以下SQL语句列出了每个国家/地区的客户数量:

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY Country;

 以下SQL语句列出每个国家的客户数量,从高到低排序:

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY CountryORDER BY COUNT(CustomerID) DESC;

演示数据库


 以下是罗斯文示例数据库中“订单”表的一个选择:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
102489051996-07-043
102498161996-07-051
102503441996-07-082

 并从“Shippers”表中选择:

ShipperIDShipperName
1Speedy Express
2United Package
3Federal Shipping

GROUP BY使用JOIN示例


 以下SQL语句列出了每个发货人发送的订单数量:

SELECT Shippers.ShipperName, COUNT(Orders.OrderID) AS NumberOfOrders FROM OrdersLEFT JOIN Shippers ON Orders.ShipperID = Shippers.ShipperIDGROUP BY ShipperName;

SQL HAVING 子句


 在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与 Aggregate 函数一起使用。

 HAVING子句已添加到SQL中,因为WHERE关键字不能用于聚合函数。

SQL HAVING 语法

SELECT column_name(s)FROM table_nameWHERE conditionGROUP BY column_name(s)HAVING conditionORDER BY column_name(s);

演示数据库


 以下是罗斯文示例数据库中"Customers"表的选择:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL HAVING示例


 以下SQL语句列出了每个国家/地区的客户数量。只包括超过5位客户的国家/地区:

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY CountryHAVING COUNT(CustomerID) > 5;

 以下SQL语句列出每个国家的客户数量,从高到低排序(仅包括拥有超过5名客户的国家/地区):

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY CountryHAVING COUNT(CustomerID) > 5ORDER BY COUNT(CustomerID) DESC;


演示数据库


 以下是罗斯文示例数据库中"Orders"表的一个选择:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
102489051996-07-043
102498161996-07-051
102503441996-07-082

并从"Employees"表中选择:

EmployeeIDLastNameFirstNameBirthDatePhotoNotes
1DavolioNancy1968-12-08EmpID1.picEducation includes a BA....
2FullerAndrew1952-02-19EmpID2.picAndrew received his BTS....
3LeverlingJanet1963-08-30EmpID3.picJanet has a BS degree....

更多HAVING示例


 以下SQL语句列出已注册超过10个订单的员工:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrdersFROM OrdersINNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeIDGROUP BY LastNameHAVING COUNT(Orders.OrderID) > 10;

 以下SQL语句列出员工“Davolio”或“Fuller”是否已注册超过25个订单:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrdersFROM OrdersINNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeIDWHERE LastName = 'Davolio' OR LastName = 'Fuller'GROUP BY LastNameHAVING COUNT(Orders.OrderID) > 25;


SQL 字母大小写转换函数UPPER(s)、UCASE(s)、LOWER(s)和LCASE(s)


1、LOWER(s)函数和LCASE(s)函数

 LOWER(s)或者LCASE(s)函数可以将字符串s中的字母字符全部转换成小写字母。

 实例:

 使用LOWER函数或者LCASE函数将字符串中所有字母字符转换为小写。SQL语句如下:

SELECT LOWER('WWW.W3Cschool.cn'),LCASE('W3CSCHOOL.CN');
 执行结果如下:

2、UPPER(s)函数和UCASE(s)函数

 UPPER(s)或UCASE(s)函数可以将字符串s中的字母字符全部转换成大写字母。
 实例:
 使用UPPER函数或者UCASE函数将字符串中的所有字母字符转换为大写。SQL语句如下:
SELECT UPPER('www.51coolma.cn'),UCASE('W3Cschool');
 执行结果如下:


不论是使用哪个函数都可以达到目的,区别不大,你可以根据需要选择一个函数进行使用


SQL UPPER()函数


 SQL upper()函数字母大小写转换函数,将字母转成大写 - 返回字符串str,根据当前字符集映射的所有字符更改为大写。

UPPER(str)

 返回字符串str,根据当前字符集映射的所有字符更改为大写。

SQL> SELECT UPPER('Allah-hus-51coolma');+---------------------------------------------------------+| UPPER('Allah-hus-51coolma')                                |+---------------------------------------------------------+| ALLAH-HUS-W3CSCHOOL                                         |+---------------------------------------------------------+1 row in set (0.00 sec)

 另外还可以参考UCASE()函数 ,它是把字段的值转换为大写。


SQL LOWER()函数


 SQL lower()字母大小写转换函数,将字母转成小写 - 返回根据当前字符集映射所有字符改变为小写,即返回小写的字符串。

LOWER(str)

 返回根据当前字符集映射所有字符改变为小写,即返回小写的字符串。

SQL> SELECT LOWER('W3CSCHOOL');+---------------------------------------------------------+| LOWER('W3CSCHOOL')                                  |+---------------------------------------------------------+| 51coolma                                           |+---------------------------------------------------------+1 row in set (0.00 sec) 

 另外还可以参考LCASE()函数,它是把字段的值转换为小写。

SQL UCASE() 函数


 UCASE() 函数把字段的值转换为大写。

SQL UCASE() 语法

SELECT UCASE(column_name) FROM table_name;      

用于 SQL Server 的语法

SELECT UPPER(column_name) FROM table_name;      

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL UCASE() 实例


 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "City" 列,并把 "CustomerName" 列的值转换为大写:

实例

SELECT UCASE(CustomerName) AS Customer, City
FROM Customers;

SQL LCASE() 函数


 LCASE() 函数把字段的值转换为小写。

SQL LCASE() 语法

SELECT LCASE(column_name) FROM table_name;     

用于 SQL Server 的语法

SELECT LOWER(column_name) FROM table_name;     

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LCASE() 实例


 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "City" 列,并把 "CustomerName" 列的值转换为小写:

实例

SELECT LCASE(CustomerName) AS Customer, City
FROM Customers;

SQL MID() 函数


 MID() 函数用于从文本字段中提取字符。

SQL MID() 语法

SELECT MID(column_name,start[,length]) FROM table_name;       

参数描述
column_name必需。要提取字符的字段。
start必需。规定开始位置(起始值是 1)。
length可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL MID() 实例


 下面的 SQL 语句从 "Customers" 表的 "City" 列中提取前 4 个字符:

实例

SELECT MID(City,1,4) AS ShortCity
FROM Customers;

SQL LEN() 函数


 LEN() 函数返回文本字段中值的长度。

SQL LEN() 语法

SELECT LEN(column_name) FROM table_name;    

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LEN() 实例


 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "Address" 列中值的长度:

实例

SELECT CustomerName,LEN(Address) as LengthOfAddress
FROM Customers;

SQL ROUND() 函数


 ROUND() 函数用于把数值字段舍入为指定的小数位数。

SQL ROUND() 语法

SELECT ROUND(column_name,decimals) FROM table_name;        

参数描述
column_name必需。要舍入的字段。
decimals必需。规定要返回的小数位数。

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars21.35
5Chef Anton's Gumbo Mix2236 boxes25

SQL ROUND() 实例


 下面的 SQL 语句从 "Products" 表中选取产品名称和价格舍入为最接近的整数:。提取前 4 个字符:

实例

SELECT ProductName, ROUND(Price,0) AS RoundedPrice
FROM Products;

SQL NOW() 函数


 NOW() 函数返回当前系统的日期和时间。

SQL NOW() 语法

SELECT NOW() FROM table_name;        

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars21.35
5Chef Anton's Gumbo Mix2236 boxes25


SQL NOW() 实例

 下面的 SQL 语句从 "Products" 表中选取产品名称以及当天的价格:

实例

SELECT ProductName, Price, Now() AS PerDate
FROM Products;

SQL FORMAT() 函数


 FORMAT() 函数用于对字段的显示进行格式化。

SQL FORMAT() 语法

SELECT FORMAT(column_name,format) FROM table_name;        

参数描述
column_name必需。要格式化的字段。
format必需。规定格式。

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars21.35
5Chef Anton's Gumbo Mix2236 boxes25

SQL FORMAT() 实例


 下面的 SQL 语句从 "Products" 表中选取产品名称以及当天(格式化为 YYYY-MM-DD)的价格:

实例

SELECT ProductName, Price, FORMAT(Now(),'YYYY-MM-DD') AS PerDate
FROM Products;

SQL SQRT 函数


 SQRT 函数用于计算得出任何数值的平方根。你可以像下面这样使用 SELECT 语句计算任何数值的平方根:

    SQL>  select SQRT(16);    +----------+    | SQRT(16) |    +----------+    | 4.000000 |    +----------+    1 row in set (0.00 sec)

 你在这里看到的是浮点数,因为 SQL 以浮点数类型来进行平方根的计算。

 你还可以使用 SQRT 函数来计算表中记录的平方根。要获得对 SQRT 函数更深入的了解,请考虑 employee_tbl 表,表中记录如下所示:

    SQL> SELECT * FROM employee_tbl;    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    1 | John | 2007-01-24 |                250 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    3 | Jack | 2007-04-06 |                100 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-06-06 |                300 |    |    5 | Zara | 2007-02-06 |                350 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

 现在,假设你想要获取每个记录中 daily_typing_pages 的平方根,那么你可以用如下命令来达到目的:

    SQL> SELECT name, SQRT(daily_typing_pages)        -> FROM employee_tbl;    +------+--------------------------+    | name | SQRT(daily_typing_pages) |    +------+--------------------------+    | John |                15.811388 |    | Ram  |                14.832397 |    | Jack |                13.038405 |    | Jack |                10.000000 |    | Jill |                14.832397 |    | Zara |                17.320508 |    | Zara |                18.708287 |    +------+--------------------------+    7 rows in set (0.00 sec)

SQL RAND 函数


 SQL 有一个 RAND 函数,用于产生 0 至 1 之间的随机数:

    SQL>  SELECT RAND( ), RAND( ), RAND( );    +------------------+-----------------+------------------+    | RAND( )          | RAND( )         | RAND( )          |    +------------------+-----------------+------------------+    | 0.45464584925645 | 0.1824410643265 | 0.54826780459682 |    +------------------+-----------------+------------------+    1 row in set (0.00 sec)

 当以某个整数值作为参数来调用的时候,RAND() 会将该值作为随机数发生器的种子。对于每一个给定的种子,RAND() 函数都会产生一列可以复现的数字:

    SQL>  SELECT RAND(1), RAND( ), RAND( );    +------------------+------------------+------------------+    | RAND(1 )         | RAND( )          | RAND( )          |    +------------------+------------------+------------------+    | 0.18109050223705 | 0.75023211143001 | 0.20788908117254 |    +------------------+------------------+------------------+    1 row in set (0.00 sec)

 你可以使用 ORDER BY RAND() 来对一组记录进行随机化排列,如下所示:

    SQL> SELECT * FROM employee_tbl;    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    1 | John | 2007-01-24 |                250 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    3 | Jack | 2007-04-06 |                100 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-06-06 |                300 |    |    5 | Zara | 2007-02-06 |                350 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

 现在,试试下面的命令:

    SQL> SELECT * FROM employee_tbl ORDER BY RAND();    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    5 | Zara | 2007-06-06 |                300 |    |    3 | Jack | 2007-04-06 |                100 |    |    3 | Jack | 2007-05-06 |                170 |    |    2 | Ram  | 2007-05-27 |                220 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-02-06 |                350 |    |    1 | John | 2007-01-24 |                250 |    +------+------+------------+--------------------+    7 rows in set (0.01 sec)    SQL> SELECT * FROM employee_tbl ORDER BY RAND();    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    5 | Zara | 2007-02-06 |                350 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-04-06 |                100 |    |    1 | John | 2007-01-24 |                250 |    |    4 | Jill | 2007-04-06 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    5 | Zara | 2007-06-06 |                300 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

SQL CONCAT 函数


 CONCAT 函数用于将两个字符串连接为一个字符串,试一下下面这个例子:

    SQL> SELECT CONCAT('FIRST ', 'SECOND');    +----------------------------+    | CONCAT('FIRST ', 'SECOND') |    +----------------------------+    | FIRST SECOND               |    +----------------------------+    1 row in set (0.00 sec)

 要对 CONCAT 函数有更为深入的了解,请考虑 employee_tbl 表,表中记录如下所示:

    SQL> SELECT * FROM employee_tbl;    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    1 | John | 2007-01-24 |                250 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    3 | Jack | 2007-04-06 |                100 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-06-06 |                300 |    |    5 | Zara | 2007-02-06 |                350 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

 现在,假设你想要将上表中所有的姓名(name)、id和工作日(work_date)连接在一起,那么可以通过如下的命令来达到目的:

    SQL> SELECT CONCAT(id, name, work_date)        -> FROM employee_tbl;    +-----------------------------+    | CONCAT(id, name, work_date) |    +-----------------------------+    | 1John2007-01-24             |    | 2Ram2007-05-27              |    | 3Jack2007-05-06             |    | 3Jack2007-04-06             |    | 4Jill2007-04-06             |    | 5Zara2007-06-06             |    | 5Zara2007-02-06             |    +-----------------------------+    7 rows in set (0.00 sec)

SQL NULL 函数


SQL ISNULL()、NVL()、IFNULL() 和 COALESCE() 函数

 请看下面的 "Products" 表:

P_IdProductNameUnitPriceUnitsInStockUnitsOnOrder
1Jarlsberg10.451615
2Mascarpone32.5623
3Gorgonzola15.67920

 假如 "UnitsOnOrder" 是可选的,而且可以包含 NULL 值。

 我们使用下面的 SELECT 语句:

SELECT ProductName,UnitPrice*(UnitsInStock+UnitsOnOrder)                FROM Products        

 在上面的实例中,如果有 "UnitsOnOrder" 值是 NULL,那么结果是 NULL。

 微软的 ISNULL() 函数用于规定如何处理 NULL 值。

 NVL()、IFNULL() 和 COALESCE() 函数也可以达到相同的结果。

 在这里,我们希望 NULL 值为 0。

 下面,如果 "UnitsOnOrder" 是 NULL,则不会影响计算,因为如果值是 NULL 则 ISNULL() 返回 0:

SQL Server / MS Access

SELECT ProductName,UnitPrice*(UnitsInStock+ISNULL(UnitsOnOrder,0))                FROM Products       

Oracle

 Oracle 没有 ISNULL() 函数。不过,我们可以使用 NVL() 函数达到相同的结果:

SELECT ProductName,UnitPrice*(UnitsInStock+NVL(UnitsOnOrder,0))                FROM Products        

MySQL

 MySQL 也拥有类似 ISNULL() 的函数。不过它的工作方式与微软的 ISNULL() 函数有点不同。

 在 MySQL 中,我们可以使用 IFNULL() 函数,如下所示:

SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0))                FROM Products        

 或者我们可以使用 COALESCE() 函数,如下所示:

SELECT ProductName,UnitPrice*(UnitsInStock+COALESCE(UnitsOnOrder,0))               FROM Products       

SQL REPLACE()字符串替换函数


实例

 把数据库表article中的所有title字段里的51coolma字符串替换成hello。
update `article` set title=replace(title,'51coolma','hello');

replace函数定义

replace(original-string,search-string,replace-string)

参数

  • original-string: 被搜索的字符串。可为任意长度。 
  • search-string: 要搜索并被 replace-string 替换的字符串。该字符串的长度不应超过 255 个字节。如果 search-string 是空字符串,则按原样返回原始字符串。 
  • replace-string: 该字符串用于替换 search-string。可为任意长度。如果 replace-string 是空字符串,则删除出现的所有 search-string。 

说明

 用字符串表达式3替换字符串表达式1中出现的所有字符串表达式2的匹配项。返回新的字符串。
 如果有某个参数为 NULL,此函数返回 NULL。

SQL TRIM()函数去除字符串头尾空格


 SQL 中的 TRIM 函数是用来移除掉一个字串中的字头或字尾。最常见的用途是移除字首或字尾的空白。这个函数在不同的资料库中有不同的名称:

  • MySQL: TRIM( ), RTRIM( ), LTRIM( )
  • Oracle: RTRIM( ), LTRIM( )
  • SQL Server: RTRIM( ), LTRIM( )

 各种 trim 函数的语法如下:

  • TRIM ( [ [位置] [要移除的字串] FROM ] 字串): [位置] 的可能值为 LEADING (起头), TRAILING (结尾), or BOTH (起头及结尾)。 这个函数将把 [要移除的字串] 从字串的起头、结尾,或是起头及结尾移除。如果我们没有列出 [要移除的字串] 是什么的话,那空白就会被移除。
  • LTRIM(字串): 将所有字串起头的空白移除。
  • RTRIM(字串): 将所有字串结尾的空白移除。

例1 TRIM()

SELECT TRIM('   Sample   ');

 结果:

'Sample'

例2 LTRIM()

SELECT LTRIM('   Sample   ');

 结果:

'Sample   '

例3 RTRIM()

SELECT RTRIM('   Sample   ');

 结果:

'   Sample'

SQL 主机


 如果您想要您的网站存储数据在数据库并从数据库显示数据,您的 Web 服务器必须能使用 SQL 语言访问数据库系统。

 如果您的 Web 服务器托管在互联网服务提供商(ISP,全称 Internet Service Provider),您必须寻找 SQL 主机计划。

 最常见的 SQL 主机数据库是 MySQL、MS SQL Server 和 MS Access。

 您可以在 Windows 和 Linux/UNIX 操作系统上运行 SQL 主机数据库。

 下面是操作系统上对应运行的数据库系统的概览。

  • MS SQL Server
    只在 Windows OS 上运行。
  • MySQL
    在 Windows, Mac OS X 和 Linux/UNIX 操作系统上运行。
  • MS Access(只建议用于小型网站)
    只在 Windows OS 上运行。

 如需学习有关 Web 主机的知识,请访问我们的 主机教程

我们已经学习了 SQL,下一步学习什么呢?


SQL 总结

 本 SQL 教程已经向您讲解了用来访问和处理数据库系统的标准计算机语言。

 我们已经学习了如何使用 SQL 在数据库中执行查询、获取数据、插入新的记录、删除记录以及更新记录。

 我们已经学习了如何通过 SQL 创建数据库、表、索引,以及如何撤销它们。

 我们已经学习了 SQL 中最重要的 Aggregate 函数。

 SQL 是一种与数据库系统协同工作的标准语言,这些数据库系统包括 MS SQL Server、IBM DB2、Oracle、MySQL 和 MS Access 等等。


我们已经学习了 SQL,下一步学习什么呢?


 我们建议接下来学习 ADO 或 PHP MySQL。

 如果您想要学习有关 ADO 的知识,请访问我们的 ADO 教程

 如果您想要学习有关 MySQL 的知识,请访问我们的 PHP 教程

您可以通过 W3Cschool 的测验程序来测试您的 SQL 技能。

关于本测验


 本测验包含 20 道题,每道题的最长答题时间是 20 分钟(这是由于每个 session 的默认有效时间是 20 钟)。

 本测验是非官方的测试,它仅仅提供了一个了解您对 SQL 的掌握程度的工具。


测验会被记分


 每道题的分值是 1 分。在您完成全部的20道题之后,系统会为您的测验打分,并提供您做错的题目的正确答案。其中,绿色为正确答案,而红色为错误答案。

 现在就开始测验!祝您好运。


详尽的SQL语句大全分类整理


Structured Query Language 即结构化查询语言,简称 SQL。SQL 是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。SQL 语句的种类还和数量都很多,其中的很多语句也是经常要用到的,下面就把常用的 SQL 语句分类整理一下,并且还可以打包下载,希望能对你有所帮助。


一、基础篇


 1、说明:创建数据库

CREATE DATABASE database-name

2、说明:删除数据库

drop database dbname

3、说明:备份sql server

 --- 创建 备份数据的 device

USE masterEXEC sp_addumpdevice 'disk', 'testBack', 'c:mssql7backupMyNwind_1.dat'


 --- 开始 备份

BACKUP DATABASE pubs TO testBack

4、说明:创建新表

create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)

 根据已有的表创建新表: 
 Acreate table tab_new like tab_old (使用旧表创建新表)
 B
create table tab_new as select col1,col2… from tab_old definition only

5、说明:删除新表

drop table tabname

6、说明:增加一个列

Alter table tabname add column col type

注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。

7、说明:添加主键

Alter table tabname add primary key(col)

 删除主键:

Alter table tabname drop primary key(col)

8、说明:创建索引

create [unique] index idxname on tabname(col….)

 删除索引:

drop index idxname

注:索引是不可更改的,想更改必须删除重新建。

9、说明:创建视图

create view viewname as select statement

 删除视图:

drop view viewname

10、说明:几个简单的基本的sql语句

  • 选择:

  • select * from table1 where 范围
  • 插入:
    insert into table1(field1,field2) values(value1,value2)
  • 删除:
    delete from table1 where 范围
  • 更新:
    update table1 set field1=value1 where 范围
  • 查找:
    select * from table1 where field1 like ’%value1%’ 
    ---like的语法很精妙,请查资料!
  • 排序:
    select * from table1 order by field1,field2 [desc]
  • 总数:
    select count as totalcount from table1
  • 求和:
    select sum(field1) as sumvalue from table1
  • 平均:
    select avg(field1) as avgvalue from table1
  • 最大:
    select max(field1) as maxvalue from table1
  • 最小:
    select min(field1) as minvalue from table1

11、说明:几个高级查询运算词

 A: UNION 运算符 
 UNION 运算符通过组合其他两个结果表(例如  TABLE1  TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL  UNION一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自  TABLE2


 B EXCEPT 运算符 
 EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL  EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。


 C INTERSECT 运算符
 INTERSECT 运算符通过只包括  TABLE1  TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL  INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。

注:使用运算词的几个查询结果行必须是一致的。

12、说明:使用外连接

 Aleft outer join 
 左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。
 
 SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c


 Bright outer join: 
 右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。


 Cfull/cross outer join 
 全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。

13、分组:Group by:

 一张表,一旦分组 完成后,查询后只能得到组相关的信息。
 组相关的信息:(统计信息) count,sum,max,min,avg 分组的标准)
 在SQLServer中分组时:不能以 text,ntext,image类型的字段作为分组依据
 在selecte统计函数中的字段,不能和普通的字段放在一起;

14、对数据库进行操作

 分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后接表明,附加需要完整的路径名

15、如何修改数据库的名称

sp_renamedb 'old_name', 'new_name'



二、提升篇


1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)

 方法一:(仅用于SQlServer) 

select * into b from a where 1<>1

 方法二:

select top 0 * into b from a

2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)

insert into b(a, b, c) select d,e,f from a;

3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)

insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件 

 例子:

..from b in '"&Server.MapPath(".")&"data.mdb" &"' where..

4、说明:子查询(表名1:a 表名2:b)

select a,b,c from a where a IN (select d from b ) 

 或者: 

select a,b,c from a where a IN (1,2,3)

5、说明:显示文章、提交人和最后回复时间

select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b

6、说明:外连接查询(表名1:a 表名2:b)

select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c

7、说明:在线视图查询(表名1:a )

select * from (SELECT a,b,c FROM a) T where t.a > 1;

8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括

select * from table1 where time between time1 and time2 
select a,b,c, from table1 where a not between 数值1 and 数值2

9、说明:in 的使用方法

select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)

10、说明:两张关联表,删除主表中已经在副表中没有的信息

delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )

11、说明:四表联查问题

select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where ......

12、说明:日程安排提前五分钟提醒

select * from 日程安排 where datediff('minute',f开始时间,getdate())>5

13、说明:一条sql 语句搞定数据库分页

select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段


 具体实现:
 关于数据库分页:

declare @start int,@end int@sql nvarchar(600)set @sql=’select top’+str(@end-@start+1)+’+from T where rid not in(select top’+str(@str-1)+’Rid from T where Rid>-1)’exec sp_executesql @sql

注意:在top后不能直接跟一个变量,所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列,如果top后还有具体的字段,这样做是非常有好处的。因为这样可以避免 top的字段如果是逻辑索引的,查询的结果后实际表中的不一致(逻辑索引中的数据有可能和数据表中的不一致,而查询时如果处在索引则首先查询索引)

14、说明:前10条记录

select top 10 * form table1 where 范围

15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)

select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)

16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表

(select a from tableA ) except (select a from tableB) except (select a from tableC)

17、说明:随机取出10条数据

select top 10 * from tablename order by newid()

18、说明:随机选择记录

select newid()

19、说明:删除重复记录

 1、

delete from tablename where id not in (select max(id) from tablename group by col1,col2,...) 

 2、

select distinct * into temp from tablename delete from tablename insert into tablename select * from temp

评价: 这种操作牵连大量的数据的移动,这种做法不适合大容量但数据操作

3、例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段

alter table tablename --添加一个自增列 add column_b int identity(1,1) delete from tablename where column_b not in( select max(column_b) from tablename group by column1,column2,...) alter table tablename drop column column_b

20、说明:列出数据库里所有的表名

select name from sysobjects where type='U' // U代表用户

21、说明:列出表里的所有的列名

select name from syscolumns where id=object_id('TableName') 

22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。

select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type 

 显示结果:

type vender pcs电脑 A 1 电脑 A 1 光盘 B 2 光盘 A 2 手机 B 3 手机 C 3

23、说明:初始化表table1

TRUNCATE TABLE table1

24、说明:选择从10到15的记录

select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc


三、技巧篇


11=11=2的使用,在SQL语句组合时用的较多

 “where 1=1” 是表示选择全部 “where 1=2”全部不选,
 如:

if @strWhere !='' beginset @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere endelse beginset @strSQL = 'select count(*) as Total from [' + @tblName + ']' end

 我们可以直接写成:

错误!未找到目录项。set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定'+ @strWhere

2、收缩数据库

--重建索引DBCC REINDEXDBCC INDEXDEFRAG--收缩数据和日志DBCC SHRINKDBDBCC SHRINKFILE

3、压缩数据库

dbcc shrinkdatabase(dbname)

4、转移数据库给新用户以已存在用户权限

exec sp_change_users_login 'update_one','newname','oldname'go

5、检查备份集

RESTORE VERIFYONLY from disk='E:dvbbs.bak'

6、修复数据库

ALTER DATABASE [dvbbs] SET SINGLE_USERGODBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCKGOALTER DATABASE [dvbbs] SET MULTI_USERGO

7、日志清除

SET NOCOUNT ONDECLARE @LogicalFileName sysname,@MaxMinutes INT,@NewSize INT


USE tablename -- 要操作的数据库名SELECT @LogicalFileName = 'tablename_log', -- 日志文件名 @MaxMinutes = 10, -- Limit on time allowed to wrap log.@NewSize = 1 -- 你想设定的日志文件的大小(M)Setup / initializeDECLARE @OriginalSize intSELECT @OriginalSize = size FROM sysfilesWHERE name = @LogicalFileNameSELECT 'Original Size of ' + db_name() + ' LOG is ' + CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'FROM sysfilesWHERE name = @LogicalFileNameCREATE TABLE DummyTrans(DummyColumn char (8000) not null)


DECLARE @Counter INT,@StartTime DATETIME,@TruncLog VARCHAR(255)SELECT @StartTime = GETDATE(),@TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'DBCC SHRINKFILE (@LogicalFileName, @NewSize)EXEC (@TruncLog)-- Wrap the log if necessary.WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expiredAND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName) AND (@OriginalSize * 8 /1024) > @NewSize BEGIN -- Outer loop.SELECT @Counter = 0WHILE ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))BEGIN -- updateINSERT DummyTrans VALUES ('Fill Log') DELETE DummyTransSELECT @Counter = @Counter + 1ENDEXEC (@TruncLog) ENDSELECT 'Final Size of ' + db_name() + ' LOG is ' +CONVERT(VARCHAR(30),size) + ' 8K pages or ' + CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'FROM sysfiles WHERE name = @LogicalFileNameDROP TABLE DummyTransSET NOCOUNT OFF

8、说明:更改某个表

exec sp_changeobjectowner 'tablename','dbo' 

9、存储更改全部表 

CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch@OldOwner as NVARCHAR(128),@NewOwner as NVARCHAR(128)ASDECLARE @Name as NVARCHAR(128)DECLARE @Owner as NVARCHAR(128)DECLARE @OwnerName as NVARCHAR(128)DECLARE curObject CURSOR FOR select 'Name' = name,'Owner' = user_name(uid)from sysobjectswhere user_name(uid)=@OldOwnerorder by nameOPEN curObjectFETCH NEXT FROM curObject INTO @Name, @OwnerWHILE(@@FETCH_STATUS=0)BEGIN if @Owner=@OldOwner beginset @OwnerName = @OldOwner + '.' + rtrim(@Name)exec sp_changeobjectowner @OwnerName, @NewOwnerend-- select @name,@NewOwner,@OldOwnerFETCH NEXT FROM curObject INTO @Name, @OwnerENDclose curObjectdeallocate curObjectGO

10SQL SERVER中直接循环写入数据

declare @i intset @i=1while @i<30begininsert into test (userid) values(@i)set @i=@i+1end

 案例

 有如下表,要求就裱中所有沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:

Name scoreZhangshan 80Lishi 59Wangwu 50Songquan 69while((select min(score) from tb_table)<60) begin update tb_table set score =score*1.01 where score<60 if (select min(score) from tb_table)>60 break else continue end


四、数据开发篇


1.按姓氏笔画排序

Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as //从少到多

2.数据库加密

select encrypt('原始密码') select pwdencrypt('原始密码') select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同 encrypt('原始密码') select pwdencrypt('原始密码') select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同

3.取回表中字段

declare @list varchar(1000), @sql nvarchar(1000)  select @list=@list+','+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name='表A' set @sql='select '+right(@list,len(@list)-1)+' from 表A'  exec (@sql)

4.查看硬盘分区

EXEC master..xp_fixeddrives

5.比较A,B表是否相等

if (select checksum_agg(binary_checksum(*)) from A) = (select checksum_agg(binary_checksum(*)) from B) print '相等' else print '不相等'

6.杀掉所有的事件探察器进程

DECLARE hcforeach CURSOR GLOBAL FOR SELECT 'kill '+RTRIM(spid) FROM master.dbo.sysprocesses WHERE program_name IN('SQL profiler',N'SQL 事件探查器') EXEC sp_msforeach_worker '?'

7.记录搜索

 开头到N条记录

Select Top N * From 表 


 N到M条记录(要有主索引ID)

Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID Desc 


 N到结尾记录

Select Top N * From 表 Order by ID Desc


 案例

 示例1:一张表有一万多条记录,表的第一个字段 RecID 是自增长字段, 写一个SQL语句, 找出表的第31到第40个记录。

select top 10 recid from A where recid not in(select top 30 recid from A)

 分析:如果这样写会产生某些问题,如果recid在表中存在逻辑索引。

 select top 10 recid from A where……是从索引中查找,而后面的select top 30 recid from A则在数据表中查找,这样由于索引中的顺序有可能和数据表中的不一致,这样就导致查询到的不是本来的欲得到的数据。


 解决方案

 1, 用order by select top 30 recid from A order by ricid 如果该字段不是自增长,就会出现问题

 2, 在那个子查询中也加条件:select top 30 recid from A where recid>-1

 

 示例2:查询表中的最后以条记录,并不知道这个表共有多少数据,以及表结构。

set @s = 'select top 1 * from T where pid not in (select top ' + str(@count-1) + ' pid from T)'print @s exec sp_executesql @s

9:获取当前数据库中的所有用户表

select Name from sysobjects where xtype='u' and status>=0

10:获取某一个表的所有字段

select name from syscolumns where id=object_id('表名')
select name from syscolumns where id in (select id from sysobjects where type = 'u' and name = '表名')

注:以上两种方式的效果相同

11:查看与某一个表相关的视图、存储过程、函数

select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'

12:查看当前数据库中所有存储过程

select name as 存储过程名称 from sysobjects where xtype='P'

13:查询用户创建的所有数据库

select * from master..sysdatabases D where sid not in(select sid from master..syslogins where name='sa')

 或者:

select dbid, name AS DB_NAME from master..sysdatabases where sid <> 0x01

14:查询某一个表的字段和数据类型

select column_name,data_type from information_schema.columns where table_name = '表名'

15:不同服务器数据库之间的数据操作

 --创建链接服务器

exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 'exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用户名 ', '密码 '

 

 --查询示例

select * from ITSV.数据库名.dbo.表名


 --导入示例

select * into 表 from ITSV.数据库名.dbo.表名


 --以后不再使用时删除链接服务器

exec sp_dropserver 'ITSV ', 'droplogins '


 --连接远程/局域网数据(openrowset/openquery/opendatasource) 

 --1、openrowset

 --查询示例:

select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)

 --生成本地表:

select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)

 --把本地表导入远程表:

insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)select *from 本地表

 --更新本地表:

update bset b.列A=a.列Afrom openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 bon a.column1=b.column1

 --openquery用法需要创建一个连接

 --首先创建一个连接创建链接服务器

exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 '

 --查询

select *FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')

 --把本地表导入远程表

insert openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')select * from 本地表

 --更新本地表

update bset b.列B=a.列BFROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') as ainner join 本地表 b on a.列A=b.列A

 --3、opendatasource/openrowset

SELECT *FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码' ).test.dbo.roy_ta

 --把本地表导入远程表

insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名select * from 本地表

全面解析SQL存储过程


 存储过程(Stored Procedure),是一组为了完成特定功能的SQL 语句,类似一门程序设计语言,也包括了数据类型、流程控制、输入和输出和它自己的函数库。存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。不过SQL存储过程对于一些初学者来说还是比较抽象难理解的,因此本文将由浅至深地剖析SQL存储过程,帮助你学习它。


存储过程的优点


  1. 存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度,效率要比T-SQL语句高。
  2. 当对数据库进行复杂操作时,可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
  3. 一个存储过程在程序在网络中交互时可以替代大堆的T-SQL语句,所以也能降低网络的通信量,提高通信速率。
  4. 存储过程可以重复使用,可减少数据库开发人员的工作量。
  5. 安全性高,可设定只有某些用户才具有对指定存储过程的使用权


存储过程基本语法


--------------创建存储过程-----------------CREATE PROC [ EDURE ] procedure_name [ ; number ]    [ { @parameter data_type }        [ VARYING ] [ = default ] [ OUTPUT ]    ] [ ,...n ][ WITH    { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ][ FOR REPLICATION ]AS sql_statement [ ...n ]--------------调用存储过程-----------------EXECUTE Procedure_name '' --存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value--------------删除存储过程-----------------drop procedure procedure_name    --在存储过程中能调用另外一个存储过程,而不能删除另外一个存储过程

创建存储过程的参数


  1. procedure_name :存储过程的名称,在前面加#为局部临时存储过程,加##为全局临时存储过程。
  2. number:是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。 
  3. @parameter:存储过程的参数。可以有一个或多个。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2100 个参数。
    使用 @ 符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。有关更多信息,请参见 EXECUTE。 
  4. data_type:参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。有关 SQL Server 提供的数据类型及其语法的更多信息,请参见数据类型。
    说明对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。 
  5. VARYING:指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。 
  6. default: 参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。
  7. OUTPUT:表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。 
  8. RECOMPILE: 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。
  9. ENCRYPTION: 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。 说明在升级过程中,SQL Server 利用存储在 syscomments 中的加密注释来重新创建加密过程。 
  10. FOR REPLICATION:指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。 
  11. AS:指定过程要执行的操作。
  12. sql_statement:过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。


实例操作学习


 下面通过表Student来具体了解一下存储过程,因为是要了解存储过程的简单用法,所以例子很简单。


Student


无参数存储过程

 选出Student表中的所有信息

create proc StuProcas      //此处 as 不可以省略不写begin   //begin 和 end 是一对,不可以只写其中一个,但可以都不写select S#,Sname,Sage,Ssex from studentendgo

有参数存储过程

 全局变量

 全局变量也称为外部变量,是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。

 选出指定姓名的学生信息:

create proc StuProc@sname varchar(100)   as beginselect S#,Sname,Sage,Ssex from student where sname=@snameendgoexec StuProc '赵雷'   //执行语句

 上面是在外部给变量赋值,也可以在内部直接给变量设置默认值

create proc StuProc@sname varchar(100)='赵雷'as beginselect S#,Sname,Sage,Ssex from student where sname=@snameendgoexec StuProc

 也可以把变量的内容输出,使用output

create proc StuProc@sname varchar(100),@IsRight int  output //传出参数as if exists (select S#,Sname,Sage,Ssex from student where sname=@sname)set @IsRight =1elseset @IsRight=0godeclare @IsRight int exec StuProc '赵雷' , @IsRight outputselect @IsRight
 以上是全局变量,下面来了解局部变量

 局部变量

 局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内部,离开该函数后再使用这种变量是非法的。

 局部变量的定义

 必须先用Declare命令定以后才可以使用,declare{@变量名 数据类型}

 局部变量的赋值方法

 set{@变量名=表达式}或者select{@变量名=表达式}

 局部变量的显示

create proc StuProcas declare @sname varchar(100)set @sname='赵雷'select S#,Sname,Sage,Ssex from student where sname=@snamegoexec StuProc

 那如果是要把局部变量的数据显示出来怎么办呢?

create proc StuProcas declare @sname varchar(100)set @sname=(select Sname from student where S#=01)select @snamegoexec StuProc


更详细的实例操作学习


 比如,在SQL Server查询编辑器窗口中用CREATE PROCEDURE语句创建存储过程PROC_InsertEmployee,用于实现向员工信息表(tb_Employee)中添加信息,同时生成自动编号。其SQL语句如下:
IF EXISTS (SELECT name     FROM   sysobjects     WHERE  name = 'Proc_InsertEmployee'     AND          type = 'P') DROP PROCEDURE Proc_InsertEmployee GO CREATE PROCEDURE Proc_InsertEmployee @PName nvarchar(50), @PSex nvarchar(4), @PAge int, @PWage money AS begin    declare @PID nvarchar(50)    select @PID=Max(员工编号) from tb_Employee    if(@PID is null)        set @PID='P1001'    else        set @PID='P'+cast(cast(substring(@PID,2,4) as int)+1 as nvarchar(50))    begin        insert into tb_Employee values(@PID,@PName,@PSex,@PAge,@PWage)    end end go 

存储过程的修改

 创建完存储过程之后,如果需要重新修改存储过程的功能及参数,可以在SQL Server 2005中通过以下两种方法进行修改:一种是用Microsoft SQL Server Mangement修改存储过程;另外一种是用T-SQL语句修改存储过程。

 使用Microsoft SQL Server Mangement修改存储过程,步骤如下:
    
 (1)在SQL Server Management Studio的“对象资源管理器”中,选择要修改存储过程所在的数据库(如:db_18),然后在该数据库下,选择“可编程性”。
 (2)打开“存储过程”文件夹,右键单击要修改的存储过程(如:PROC_SEINFO),在弹出的快捷菜单中选择“修改”命令,将会出现查询编辑器窗口。用户可以在此窗口中编辑T-SQL代码,完成编辑后,单击工具栏中的“执行(X)”按钮,执行修改代码。用户可以在查询编辑器下方的Message窗口中看到执行结果信息。

 使用Transact-SQL修改存储过程: 
 使用ALTER PROCEDURE语句修改存储过程,它不会影响存储过程的权限设定,也不会更改存储过程的名称。

 语法:
ALTER PROC [ EDURE ] procedure_name [ ; number ]     [ { @parameter data_type }           [ VARYING ] [ = default ] [ OUTPUT ]     ] [ ,...n ]  [ WITH     { RECOMPILE | ENCRYPTION         | RECOMPILE , ENCRYPTION   }  ] [ FOR REPLICATION ]  AS     sql_statement [ ...n ]

参数说明

 procedure_name:是要更改的存储过程的名称。

 交叉链接:关于ALTER PROCEDURE语句的其他参数与CREATE PROCEDURE语句相同,可参见上面的“创建存储过程的参数”。

 例如,修改存储过程PROC_SEINFO,用于查询年龄大于35的员工信息。SQL语句如下:

ALTER PROCEDURE [dbo].[PROC_SEINFO] AS BEGIN SELECT * FROM tb_Employee where 员工年龄>35 END

存储过程的删除

 使用Microsoft SQL Server Mangement删除存储过程,步骤如下:

 (1)在SQL Server Management Studio的“对象资源管理器”中,选择要删除存储过程所在的数据库(如:db_student),然后在该数据库下选择“可编程性”。  

 (2)打开“存储过程”文件夹,右键单击要删除的存储过程(如:PROC_SEINFO),在弹出的快捷菜单中选择“删除”命令。

 (3)单击“确定”按钮,即可删除所选定的存储过程。  

注意:删除数据表后,并不会删除相关联的存储过程,只是其存储过程无法执行。


 使用T-SQL删除存储过程:

 DROP PROCEDURE语句用于从当前数据库中删除一个或多个存储过程或过程组。 

 语法:

DROP PROCEDURE { procedure } [ ,...n ]

 参数说明:   

  • Procedure:是要删除的存储过程或存储过程组的名称。过程名称必须符合标识符规则。可以选择是否指定过程所有者名称,但不能指定服务器名称和数据库名称。   
  • n:是表示可以指定多个过程的占位符。

    

 例如删除PROC_SEINFO存储过程的SQL语句如下。

DROP PROCEDURE PROC_SEINFO
 例如,删除多个存储过程proc10、proc20和proc30。
DROP PROCEDURE proc10, proc20, proc30
  例如,删除存储过程组procs(其中包含存储过程proc1、proc2、proc3)。
DROP PROCEDURE procs

注意:SQL语句DROP不能删除存储过程组中的单个存储过程。

应用存储过程验证用户登录身份:

 目前,验证用户登录身份的方法有多种,而通过调用存储过程来实现用户身份验证是目前最好的解决方案之一。因为存储过程在创建时即在服务器上进行编译,所以执行起来比单个SQL语句要快得多。

 本例是通过调用存储过程来验证用户登录的用户名和密码是否正确。运行本实例,在“用户名”和“密码”文本框中输入相应的用户名和密码,单击“登录”按钮即可。

 程序开发步骤:

 (1)新建一个网站,将其命名为"index",默认主页名为Default.aspx。    

 (2)Default.aspx页面涉及到的控件如表1所示。


Default.aspx页面涉及到的控件


 (3)主要程序代码如下。
 打开SQL Server Management Studio,并连接到SQL Server2005中的数据库。单击工具栏中“ ”按钮,新建查询编辑器。在该查询编辑器中,创建验证登录用户身份的存储过程PROC_EXISTS,具体的SQL语句如下:

CREATE PROC PROC_EXISTS ( @UserName NVARCHAR(20), @PassWord NVARCHAR(20), @ReturnValue int OUTPUT ) AS IF EXISTS(select * from tb_member where userName=@UserName AND passWord=@PassWord)        set @ReturnValue= 100 ELSE        set @ReturnValue= -100 GO

 在"登录"按钮的Click事件下,执行验证登录用户身份的存储过程,如果输入的用户名和密码正确,则弹出对话框提示用户登录成功,代码如下:

protected void btnLogin_Click(object sender, EventArgs e)     {         //连接数据库         myConn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"].ToString());         myCmd = new SqlCommand("PROC_EXISTS", myConn);   //调用存储过程,判断用户是否存在        myCmd.CommandType = CommandType.StoredProcedure;         //为存储过程的参数赋值         SqlParameter userName=new SqlParameter("@UserName", SqlDbType.NVarChar, 20);         userName.Value=this.txtName.Text.Trim();         myCmd.Parameters.Add(userName);         SqlParameter passWord=new SqlParameter("@PassWord", SqlDbType.NVarChar, 20);         passWord.Value = this.txtPassword.Text.Trim();         myCmd.Parameters.Add(passWord);         //指出该参数是存储过程的OUTPUT参数         SqlParameter ReturnValue = new SqlParameter("@ReturnValue",SqlDbType.Int ,4);         ReturnValue.Direction = ParameterDirection.Output;         myCmd.Parameters.Add(ReturnValue);         try         {             myConn.Open();             myCmd.ExecuteNonQuery();             if (int.Parse(ReturnValue.Value.ToString()) == 100)             {                 Response.Write("<script>alert('您是合法用户,登录成功!')</script>");                 return;             }             else             {                 Response.Write("<script>alert('您输入的用户名和密码不正确,请重新输入!')</script>");                 return;             }         }         catch(Exception ex)         {             Response.Write(ex.Message.ToString());         }         finally         {             myConn.Close();             myConn.Dispose();             myCmd.Dispose();         }}


SQL

 SQL 是用于访问和处理数据库的标准的计算机语言。

 在本教程中,您将学到如何使用 SQL 访问和处理数据系统中的数据,这类数据库包括:MySQL、SQL Server、Access、Oracle、Sybase、DB2和其他数据库系统。


每一章实例


 每章节都提供了简单的 SQL 简单实例。

实例

SELECT * FROM Customers;

 开始学习SQL吧!

 SQL查询从用户表中选择所有记录:

SELECT * FROM users;

 SQL查询通过使用where子句从用户表中删除单个记录:

DELETE FROM users WHERE user_id=299;

适用人群


 本参考的目的在于帮助初学者深入浅出地学习 SQL 语言。


SQL测验测试


 在51coolma测试你的SQL技能!

 开始SQL测验!


SQL快速参考


 一个SQL快速参考。打印并放在口袋里。

 SQL快速参考


SQL数据类型


 Microsoft Access,MySQL和SQL Server的数据类型和范围。

 SQL数据类型


W3Cschool实战认证


 实践出真知,通过获得证书是编程实例最好的证明

 去闯关



学习前提


 本参考准备了各种各样的示例,在正式开始练习之前,我假定你对什么是数据库——尤其是关系型数据库管理系统(RDBMS)——已经有所了解,同时也知道什么是计算机编程语言。


SQL简介


    SQL(结构化查询语言)是用于访问和操作数据库中的数据的标准数据库编程语言。

    SQL是关系数据库系统的标准语言。所有关系数据库管理系统(RDMS),如MySQL、MS Access、Oracle、Sybase、Informix、Postgres和SQL Server都使用SQL作为它们的标准数据库语言。

    为了处理数据库和数据库相关的编程,程序员需要有一些介质,或者可以说接口来详细说明一组命令或代码来处理数据库或访问数据库的数据。在本章中,将简要介绍在学习SQL的过程中您将学习的术语。


你会从SQL中学到什么?


    SQL为结构化查询语言提供了独特的学习和数据库处理技术,并将帮助您更好地控制SQL查询并有效处理这些代码。由于SQL帮助您包括数据库创建,数据库或表删除,获取行数据和修改这些数据等,并行SQL使得事情自动和平滑,最终用户可以轻松访问和处理该应用程序的数据。


SQL 是什么?


  • SQL 发音为“sequel”。
  • SQL 指结构化查询语言,全称是 Structured Query Language(是最初由IBM开发)。
  • SQL 是关系数据库系统的标准语言。
  • SQL 是一种 ANSI(American National Standards Institute 美国国家标准化组织)标准的计算机语言。


SQL 能做什么?


  • SQL可以创建新的数据库及其对象(表,索引,视图,存储过程,函数和触发器)。
  • SQL可以修改现有数据库的结构。
  • SQL可以从数据库中删除(删除)对象。
  • SQL可以TRUNCATE(删除)表中的所有记录。
  • SQL可以对数据字典进行COMMENT。
  • SQL可以RENAME一个对象。
  • SQL可以从数据库中选择(检索)数据。
  • SQL可以将数据插入到表中。
  • SQL可以更新表中的现有数据。
  • SQL可以从数据库表中删除记录。
  • SQL可以在数据库中设置用户的GRANT和REVOKE权限。


SQL 的历史


  • 1970年,SQL由IBM的Donald D. Chamberlin和Raymond F. Boyce开发。
  • 1974年,开发版本最初被称为SEQUEL(结构化英语查询语言)。
  • 1979年,关系软件发布了第一个叫做System / R的商业产品。
  • 由于商标冲突问题,SEQUEL首字母缩略词后来更改为SQL。
  • 后来IBM基于System / R的原型开始在SQL上开发商业产品。
  • 第一个关系数据库由RelationalSoftware发布,后来被称为Oracle。


SQL 是一种标准 - 但是...


    虽然 SQL 是一门 ANSI(American National Standards Institute 美国国家标准化组织)标准的计算机语言,但是仍然存在着多种不同版本的 SQL 语言。

然而,为了与 ANSI 标准相兼容,它们必须以相似的方式共同地来支持一些主要的命令(比如 SELECT、UPDATE、DELETE、INSERT、WHERE 等等)。

lamp注释:除SQL标准之外,大多数SQL数据库程序还具有自己的专有扩展名!

在您的网站中使用 SQL


    要创建一个显示数据库中数据的网站,您需要:

  • 一个RDBMS数据库程序(即MS Access,SQL Server,MySQL)。
  • 使用服务器端脚本语言,如PHP或ASP。
  • 使用SQL来获取所需的数据。
  • 使用HTML / CSS来设置页面的样式


RDBMS


    RDBMS 指关系型数据库管理系统,全称 Relational Database Management System。

    RDBMS 是 SQL 的基础,同样也是所有现代数据库系统的基础,比如 MS SQL Server、IBM DB2、Oracle、MySQL 以及 Microsoft Access。

    RDBMS 中的数据存储在被称为表的数据库对象中。

    表是相关的数据项的集合,它由列和行组成。

    代码示例:

SELECT * FROM Customers;

    每个表都被分解成称为字段的更小的实体。Customers表中的字段由CustomerID,CustomerName,ContactName,Address,City,PostalCode和Country组成。字段是表中的一列,用于维护表中每条记录的特定信息。

    记录(也称为行)是表中存在的每个单独条目。例如,在上面的Customers表中有91条记录。记录是表中的横向实体。

    列是表中的垂直实体,其包含与表中的特定字段相关联的所有信息。


SQL进程


    当您对任何RDBMS执行SQL命令时,系统将确定执行请求的最佳方式,并由SQL引擎确定如何解释该任务。

    在此过程中包含了各种组件。

    查询调度器优化引擎经典查询引擎SQL查询引擎

典型的查询引擎处理所有非SQL查询,但SQL查询引擎不会处理逻辑文件。


SQL标准命令


    与关系数据库交互的标准SQL命令是创建、选择、插入、更新、删除和删除,简单分为以下几组:

DDL(数据定义语言)

    数据定义语言用于改变数据库结构,包括创建、更改和删除数据库对象。用于操纵表结构的数据定义语言命令有:

  • CREATE TABLE-- 创建(在数据库中创建新表、表视图或其他对象)
  • ALTER TABLE-- 更改 (修改现有的数据库对象,如表)
  • DROP TABLE-- 删除  (删除数据库中的整个表、表或其他对象的视图)

DML(数据操纵语言)

    数据操纵语言用于检索、插入和修改数据,数据操纵语言是最常见的SQL命令。

    数据操纵语言命令包括:

  • INSERT-- 插入 (创建记录)
  • DELETE-- 删除 (删除记录)
  • UPDATE-- 修改(修改记录)
  • SELECT -- 检索 (从一个或多个表检索某些记录)

DCL(数据控制语言)

    数据控制语言为用户提供权限控制命令。

    用于权限控制的命令有:

  • GRANT-- 授予权限
  • REVOKE-- 撤销已授予的权限


SQL格式化


    使用SQL格式化工具可以比较直观的看到您想要的操作



章节小测


 现在,相信您已经了解了SQL的基础知识,那么,测验一下吧!

 SQL微课 - 数据库介绍:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL RDBMS 概念


 RDBMS是关系数据库管理系统(Relational Database Management System)的缩写。

 RDBMS是SQL的基础,也是所有现代数据库系统(如MS SQL Server、IBMDB2、Oracle、MySQL和MicrosoftAccess)的基础。

 关系数据库管理系统(Relational Database Management System,RDBMS)是一种基于E.F.Codd提出的关系模型的数据库管理系统。


什么是表?


 RDBMS中的数据存储在称为表的数据库对象中。这个表基本上是一个相关数据条目的集合,它由许多列和行组成。请记住,表是关系数据库中最常见和最简单的数据存储形式。

 下面的程序是Customers表的一个示例

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

什么是字段?


 每个表都被分解成更小的实体,称为字段。Customers表中的字段由ID、姓名、年龄、地址和薪资组成。

 字段是表中的列,用于维护有关表中每条记录的特定信息。


什么是记录或者行数据?


 记录也称为数据行,即表中存在的每个单独的条目。例如,上面的Customers表中有7条记录。下面是Customers表中的单行数据或记录。

+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |+----+----------+-----+-----------+----------+

 记录是表中的水平实体。


什么是列?


 列是表中的垂直实体,其中包含与表中特定字段关联的所有信息。

 例如,Customers表中的一列是Address,它表示位置描述,如下所示:

+-----------+| ADDRESS   |+-----------+| Ahmedabad || Delhi     || Kota      || Mumbai    || Bhopal    || MP        || Indore    |+----+------+

什么是空值?


 表中的空值是显示为空的字段中的值,这意味着具有空值的字段是没有值的字段。

 非常重要的一点是空值不同于零值或包含空格的字段。具有空值的字段是在创建记录时留空的字段。


SQL约束


 约束是在表上的数据列上强制执行的规则。它们用于限制可以进入表中的数据类型。

 这确保了数据库中数据的准确性和可靠性。

 约束可以是列级别,也可以是表级别。列级约束仅应用于一列,而表级约束则应用于整个表。

 以下是sql−中可用的一些最常用的约束

 约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。


数据完整性


 每个关系数据库管理系统都存在以下类型的数据完整性:

实体完整性−表中没有重复行。
域完整性−通过限制值的类型、格式或范围来强制执行给定列的有效条目。
引用完整性−不能删除其他记录使用的行。
用户定义的完整性−强制执行一些不属于实体、域或引用完整性的特定业务规则。

数据库规范化


 数据库规范化是在数据库中有效地组织数据的过程。这个规范化过程有两个原因:

  • 消除冗余数据,例如,将相同的数据存储在多个表中。 
  • 确保数据依赖关系是有意义的。

 这两个原因都是值得追求的目标,因为它们减少了数据库消耗的空间量,并确保了数据的逻辑存储。

 规范化由一系列指导原则组成,有助于指导您创建良好的数据库结构。

 规范化指导原则称为范式,范式的目的是组织数据库结构,使其符合第一范式、第二范式和第三范式的规则。

 你可以更长远的去选择第四范式,第五范式,等等,但一般来说,第三范式已经足够了。

第一范式(1NF)
第二范式(2NF)
第三范式(3NF)


SQL 语法规则


  • SQL语句总是以关键字开始,如SELECT、INSERT、UPDATE、DELETE、DROP、CREATE。
  • SQL语句以分号结尾。
  • SQL不区分大小写,意味着update与UPDATE相同。

数据库表


 数据库通常包含一个或多个表。每个表都用一个名称标识(例如,"Customers"或"Orders")。该表包含带有数据(行)的记录。
 在本教程中,我们将使用著名的Northwind示例数据库(包括MSAccess和MSSQLServer)。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

 上面的表包含五条记录(每一条对应一个客户)和七个列(CustomerID、CustomerName、ContactName、Address、City、PostalCode 和 Country)。


SQL 语句


 您需要在数据库上执行的大部分操作都是使用SQL语句完成的。

 以下SQL语句选择“Customers”表中的所有记录:

实例

SELECT * FROM Customers;

 在本教程中,我们将向您解释各种不同的SQL语句。


请记住...


  • SQL 对大小写不敏感:SELECT 与 select 是相同的。
  • 在本教程中,我们将以大写形式编写所有SQL关键字。

SQL 语句后面的分号?


  • 一些数据库系统需要在每个SQL语句的末尾使用分号。
  • 分号是分离数据库系统中每个SQL语句的标准方法,这样您就可以在对服务器的同一请求中执行多个SQL语句。
  • 在本教程中,我们将在每个SQL语句的末尾使用分号。

一些最重要的 SQL 命令


  • SELECT - 从数据库中提取数据
  • UPDATE - 更新数据库中的数据
  • DELETE - 从数据库中删除数据
  • INSERT INTO - 向数据库中插入新数据
  • CREATE DATABASE - 创建新数据库
  • ALTER DATABASE - 修改数据库
  • CREATE TABLE - 创建新表
  • ALTER TABLE - 变更(改变)数据库表
  • DROP TABLE - 删除表
  • CREATE INDEX - 创建索引(搜索键)
  • DROP INDEX - 删除索引


SELECT语句

 句法:

SELECT column_name(s) FROM table_name

SELECT语句和WHERE子句

 句法:

SELECT [*] FROM [TableName] WHERE [condition1]

SELECT语句与WHERE和/或子句

 句法:

SELECT [*] FROM [TableName] WHERE [condition1] [AND [OR]] [condition2]...

SELECT语句与ORDER BY

 句法:

SELECT column_name()FROM table_nameORDER BY column_name() ASC or DESC

SELECT  DISTINCT(区分)子句

 句法:

SELECT DISTINCT column1, column2....columnNFROM   table_name;

SELECT  IN子句

 句法:

SELECT column1, column2....columnNFROM   table_nameWHERE  column_name IN (val-1, val-2,...val-N);

SELECT LIKE (类)子句

 句法:

SELECT column1, column2....columnNFROM   table_nameWHERE  column_name LIKE { PATTERN };

SELECT  COUNT(计数)子句

 句法:

SELECT COUNT(column_name)FROM   table_nameWHERE  CONDITION;

SELECT与HAVING子句

 句法:

SELECT SUM(column_name)FROM   table_nameWHERE  CONDITIONGROUP BY column_nameHAVING (arithematic function condition);

INSERT INTO语句

 句法:

INSERT INTO table_name (column, column1, column2, column3, ...)VALUES (value, value1, value2, value3 ...)

UPDATE语句

 句法:

UPDATE table_nameSET column=value, column1=value1,...WHERE someColumn=someValue

DELETE语句

 句法:

DELETE FROM tableNameWHERE someColumn = someValue

CREATE 语句

 句法:

CREATE TABLE table_name(column1 datatype,column2 datatype,column3 datatype,.....columnN datatype,PRIMARY KEY( one or more columns ));

DROP 语句

 句法:

DROP TABLE table_name;

CREATE INDEX语句

 句法:

CREATE UNIQUE INDEX index_nameON table_name ( column1, column2,...columnN);

DROP INDEX语句

 句法:

ALTER TABLE table_nameDROP INDEX index_name;

DESC语句

 句法:

DESC table_name;

TRUNCATE 截断表语句

 句法:

TRUNCATE TABLE table_name;

ALTER TABLE语句

 句法:

ALTER TABLE table_name {ADD|DROP|MODIFY} column_name {data_ype};

ALTER TABLE语句(对表名重命名)

 句法:

ALTER TABLE table_name RENAME TO new_table_name;

Use语句 

 句法:

USE database_name;

COMMIT语句

 句法:

COMMIT;

ROLLBACK语句

 句法:

ROLLBACK;


章节小测


 现在,通过以下题目测测看您对“SQL 语法”的掌握程度吧!

 SQL语法规则:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL SELECT 语法


 SELECT 语法用于从数据库中选择数据。 

 返回的数据存储在结果表中,称为结果集。

基本语法:SELECT和FROM

 在任何SQL查询语句中都:SELECT和FROM他们必须按顺序排列。SELECT指示要查看哪些列,FROM标识它们所在的表。

 SQL SELECT 语法如下所示:

SELECT column1, column2, ...FROM table_name;

 这里,column1,column2,...是要从中选择数据的表的字段名称。如果要选择表中可用的所有字段,请使用以下语法:

SELECT * FROM table_name;

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是罗斯文示例数据库中“Customers”表的一个选择:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SELECT Column 实例


 我们将为以下三种用例提供实例

1、检索一列  
2、检索多列 
3、检索所有列

 我们将用上述的“Customers”表来说明三种用例的使用。

SELECT  检索一列

 下面的 SQL 语句从 "Customers" 表中选取 "City" 列:

实例

SELECT City FROM Customers; 

SELECT  检索多列

 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "City" 列:

实例

SELECT CustomerName, City FROM Customers;

注意:这两个列名在查询中用逗号分隔。每当您选择多个列时,它们必须用逗号分隔,但最后一列名称之后不能添加逗号。

SELECT * 实例 - 检索所有列

 下面的 SQL 语句从 "Customers" 表中选取所有列:

实例

SELECT * FROM Customers;

 如果要选择表中的所有列,则可以使用 * 而不需要把所有列名罗列查询。


结果集中的导航


 大多数数据库软件系统都允许使用编程函数在结果集中进行导航,例如:Move-To-First-Record、Get-Record-Content、Move-To-Next-Record 等等。

 本教程中不包括与这些编程函数类似的功能。要了解如何通过函数调用访问数据,请访问我们的 ADO 教程 或者 PHP 教程


章节小测


 现在,通过以下题目测测看您对“SQL Select(选择)语法”的掌握程度吧!

 SQL选择多列:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL SELECT DISTINCT 语法


 SELECT DISTINCT语法用于仅返回不同的(different)值。

 在一张表内,一列通常包含许多重复的值; 有时你只想列出不同的(different)值。

 SELECT DISTINCT语句用于仅返回不同的(different)值。

 SQL SELECT DISTINCT语法如下所示:

SELECT DISTINCT column1, column2, ...FROM table_name;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是罗斯文示例数据库中 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SELECT实例


 以下SQL语句从“Customers”表中的“Country”列中选择所有(包括重复)值:

 代码示例:

 SELECT Country FROM Customers;

SELECT Country FROM Customers;

 以上查询的结果:

CountryGermanyMexicoMexicoUK

Sweden

 现在,让我们在上面的SELECT语法中使用DISTINCT关键字并查看结果。


SELECT DISTINCT 实例


 以下SQL语句仅从"Customers" 表中的 "Country" 列中选择DISTINCT值:

实例1

SELECT DISTINCT Country FROM Customers;

 查询结果:

CountryGermanyMexicoUKSweden


 以下SQL语句列出了不同(distinct)客户国家的数量: 

实例2

SELECT COUNT(DISTINCT Country) FROM Customers; 

注意:上述示例在Firefox和Microsoft Edge中不起作用!

 由于在Microsoft Access数据库中不支持COUNT(DISTINCT column_name)。在我们的示例中Firefox和Microsoft Edge使用Microsoft Access。


章节小测


 现在,通过以下题目测测看您对“SQL SELECT DISTINCT(选择不同) 语法”的掌握程度吧!

 SQL DISTINCT关键字:点击此处进行测试>>

 更多测试题请参考:《SQL测验》题库>>


SQL WHERE 子句


 WHERE 子句用于过滤记录。

 WHERE 子句用于提取满足指定标准的记录。 

SQL WHERE 语法

SELECT column1, column2, ...FROM table_nameWHERE condition;
注意: WHERE子句不仅用于SELECT语法,还用于UPDATE,DELETE语法等!

 WHERE子句可以与以下类型的SQL语句一起使用:

  • UPDATE
  • DELETE

 UPDATE语句:

UPDATE "table_name"SET "column_1" = [new value]WHERE "condition";

 DELETE语句:

DELETE FROM "table_name"WHERE "condition";

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。
 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

WHERE 子句实例


 以下SQL语句从"Customers"表中选择其国家为"Mexico"的所有客户:

实例

SELECT * FROM Customers
WHERE Country='Mexico';

 你也可以使用OR运算符的查询子句:

实例

SELECT * FROM Customers
WHERE Country='Mexico' OR PostalCode='05021';

文本字段与数值字段


 SQL在文本值周围使用单引号(大多数数据库系统也接受双引号)。

 如果是数值字段,则不要使用引号。

实例

SELECT * FROM Customers
WHERE CustomerID=1;

WHERE 子句中的运算符


 WHERE子句中可以使用以下运算符:

运算符描述
=等于
<>不等于。 注意:在某些版本的SQL中,这个操作符可能写成!=
>大于
<小于
>=大于等于
<=小于等于
BETWEEN在某个范围内
LIKE搜索某种模式
IN为列指定多个可能的值


章节小测


 现在,通过以下题目测测看您对“SQL WHERE Clause(查询子句)”的掌握程度吧!

 SQL WHERE语句:在本部分测验中,您将练习使用 WHERE 语句的基础语法,以及如何在 WHERE 子句中使用 SQL 运算符。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL AND & OR 运算符


 AND&OR运算符用于根据一个以上的条件过滤记录,即用于组合多个条件以缩小SQL语句中的数据。

 WHERE子句可以与AND,OR和NOT运算符结合使用。

 AND和OR运算符用于根据多个条件筛选记录:

  • 如果由AND分隔的所有条件为TRUE,则AND运算符显示记录。
  • 如果使用AND运算符组合N个条件。对于SQL语句执行的操作(无论是事务还是查询),所有由AND分隔的条件都必须为TRUE。
  • 如果由OR分隔的任何条件为真,则OR运算符显示记录。
  • 如果使用OR运算符组合N个条件。对于SQL语句执行的操作(无论是事务还是查询),OR分隔的任何一个条件都必须为TRUE。

 如果条件不为TRUE,则NOT运算符显示记录。 

AND语法

SELECT column1, column2, ...FROM table_nameWHERE condition1 AND condition2 AND condition3 ...;

OR语法

SELECT column1, column2, ...FROM table_nameWHERE condition1 OR condition2 OR condition3 ...;

NOT语法

SELECT column1, column2, ...FROM table_nameWHERE NOT condition;


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers"表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

AND 运算符实例


 以下SQL语句从 "Customers" 表中选择其国家为 "Germany" 、其城市为"Berlin" 的所有客户:

实例

SELECT * FROM Customers
WHERE Country='Germany'
AND City='Berlin';

OR 运算符实例


 以下SQL语句选择城市为“Berlin”或“München”的“Customers”的所有字段:

实例

SELECT * FROM Customers
WHERE City='Berlin' OR City='München';

NOT 运算符实例


 以下SQL语句选择国家不是 "Germany"的"Customers"的所有字段:

SELECT * FROM CustomersWHERE NOT Country='Germany';

结合 AND & OR


 您还可以组合AND和OR(使用括号来组成成复杂的表达式)。

 以下SQL语句从国家 "Germany" 且城市为"Berlin" 或"München"的"Customers" 表中选择所有客户:

实例

SELECT * FROM Customers
WHERE Country='Germany'
AND (City='Berlin' OR City='München');


结合AND,OR和NOT


 你也可以结合AND,OR和NOT运算符。

 以下SQL语句选择国家是“德国”的“客户”的所有字段,城市必须是“柏林”或“慕尼黑”(用括号形成复杂表达式):

 代码示例:

SELECT * FROM CustomersWHERE Country='Germany' AND (City='Berlin' OR City='München');

 以下SQL语句选择来自"Customers" 的国家不是 "Germany" 且不是 "USA"的所有字段:

 代码示例:

SELECT * FROM CustomersWHERE NOT Country='Germany' AND NOT Country='USA';

章节小测


 现在,通过以下题目测测看您对“SQL AND, OR and NOT(与,或不是运算符)”的掌握程度吧!

 SQL AND, OR运算符:在本部分测验中,您将练习使用 SQL 的 AND, OR 运算符。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL ORDER BY 关键字


 ORDER BY 关键字用于按升序或降序对结果集进行排序。

 ORDER BY 关键字默认情况下按升序排序记录。

 如果需要按降序对记录进行排序,可以使用DESC关键字。

SQL ORDER BY 语法

SELECT column1, column2, ...FROM table_nameORDER BY column1, column2, ... ASC|DESC;

 您可以在ORDER BY子句中使用多个列,但要确保用于对该列进行排序的列应该在列表中。


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

ORDER BY 实例


 下面的 SQL 语句从 "Customers" 表中选取所有客户,并按照 "Country" 列排序:

实例

SELECT * FROM Customers
ORDER BY Country;

ORDER BY DESC 实例


 下面的 SQL 语句从 "Customers" 表中选取所有客户,并按照 "Country" 列降序排序:

实例

SELECT * FROM Customers
ORDER BY Country DESC;

ORDER BY 多列 实例1


 下面的 SQL 语句从 "Customers" 表中选取所有客户,并按照 "Country" 和 "CustomerName" 列排序:

实例

SELECT * FROM Customers
ORDER BY Country, CustomerName;

ORDER BY 多列 实例2


 以下SQL语句从"Customers" 表中选择所有客户,按 "Country" 升序排列,并按 "CustomerName" 列降序排列:

SELECT * FROM CustomersORDER BY Country ASC, CustomerName DESC;


章节小测


 更多测试题请参考:《SQL测验》题库>>


SQL INSERT INTO 语句


 INSERT INTO 语句用于向表中插入新的数据行。

SQL INSERT INTO 语法

 INSERT INTO 语句可以用两种形式编写。
 第一个表单没有指定要插入数据的列的名称,只提供要插入的值,即可添加一行新的数据:

INSERT INTO table_name (column1, column2, column3, ...)VALUES (value1, value2, value3, ...);

 第二种,如果要为表中的所有列添加值,则不需要在SQL查询中指定列名称。但是,请确保值的顺序与表中的列顺序相同。INSERT INTO语法如下所示:

INSERT INTO table_nameVALUES (value1, value2, value3, ...);

演示数据库


 在本教程中,我们将使用著名的 Northwind 示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
87Wartian HerkkuPirkko KoskitaloTorikatu 38Oulu90110Finland
88Wellington ImportadoraPaula ParenteRua do Mercado, 12Resende08737-363Brazil
89White Clover MarketsKarl Jablonski305 - 14th Ave. S. Suite 3BSeattle98128USA
90
Wilman KalaMatti KarttunenKeskuskatu 45Helsinki21240Finland
91
WolskiZbyszekul. Filtrowa 68Walla01-012Poland

INSERT INTO 实例


 假设我们想在"Customers"表中插入一个新行。

 我们可以使用以下SQL语句:

实例

INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
VALUES ('Cardinal','Tom B. Erichsen','Skagen 21','Stavanger','4006','Norway');

 现在,选自 "Customers" 表的数据如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
87Wartian HerkkuPirkko KoskitaloTorikatu 38Oulu90110Finland
88Wellington ImportadoraPaula ParenteRua do Mercado, 12Resende08737-363Brazil
89White Clover MarketsKarl Jablonski305 - 14th Ave. S. Suite 3BSeattle98128USA
90
Wilman KalaMatti KarttunenKeskuskatu 45Helsinki21240Finland
91
WolskiZbyszekul. Filtrowa 68Walla01-012Poland
92CardinalTom B. ErichsenSkagen 21Stavanger4006Norway

lamp注意到了吗?我们没有将任何号码插入 CustomerID 字段。
CustomerID列是一个自动递增字段,在将新记录插入到表中时自动生成。

仅在指定的列中插入数据


 我们还可以只在指定的列中插入数据。

 以下SQL语句插入一个新行,但只在“CustomerName”、“City”和“Country”列中插入数据(CustomerID字段将自动更新):

实例

INSERT INTO Customers (CustomerName, City, Country)
VALUES ('Cardinal', 'Stavanger', 'Norway');

 现在,选自 "Customers" 表的数据如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
87Wartian HerkkuPirkko KoskitaloTorikatu 38Oulu90110Finland
88Wellington ImportadoraPaula ParenteRua do Mercado, 12Resende08737-363Brazil
89White Clover MarketsKarl Jablonski305 - 14th Ave. S. Suite 3BSeattle98128USA
90
Wilman KalaMatti KarttunenKeskuskatu 45Helsinki21240Finland
91
WolskiZbyszekul. Filtrowa 68Walla01-012Poland
92CardinalnullnullStavangernullNorway

使用另一个表填充一个表


 您可以通过另一个表上的SELECT语句查询出来的字段值,然后将数据填充到本表中,条件是另一个表所查询的字段与本表要插入数据的字段是一一对应的。

INSERT INTO first_table_name [(column1, column2, ... columnN)] SELECT column1, column2, ...columnN FROM second_table_name[WHERE condition];


章节小测


 现在,通过以下题目测测看您对“SQL INSERT INTO 语句(在表中插入)”的掌握程度吧!

 SQL INSERT语句:在本部分测验中,您将通过选择填空、排序、判断的题型来练习在 SQL 中插入数据。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


什么是SQL NULL值?


 SQL 中,NULL 用于表示缺失的值。数据表中的 NULL 值表示该值所处的字段为空。

 具有NULL值的字段是没有值的字段。

 如果表中的字段是可选的,则可以插入新记录或更新记录而不向该字段添加值。然后,该字段将被保存为NULL值。

 值为 NULL 的字段没有值。尤其要明白的是,NULL 值与 0 或者包含空白(spaces)的字段是不同的。

注意:理解NULL值与零值或包含空格的字段不同是非常重要的。具有NULL值的字段是在记录创建期间留空的字段!


如何测试NULL值?


 使用比较运算符(例如=,<或<>)来测试NULL值是不可行的。

 我们将不得不使用IS NULL和IS NOT NULL运算符。

IS NULL语法

SELECT column_namesFROM table_nameWHERE column_name IS NULL;

IS NOT NULL语法

SELECT column_namesFROM table_nameWHERE column_name IS NOT NULL;

演示数据库


 假设我们有以下的“人员”表:

IDLastNameFirstNameAddressCity
1DoeJohn542 W. 27th StreetNew York
2BloggsJoe London
3RoeJane New York
4SmithJohn110 BishopsgateLondon

 假设“人员”表中的“Address”列是可选的。如果插入的记录没有“Address”值,则“Address”列将以空值保存。


IS NULL运算符


 以下SQL语句使用IS NULL运算符来列出所有没有地址的人员:

SELECT LastName, FirstName, Address FROM PersonsWHERE Address IS NULL;

 结果集将如下所示:

LastNameFirstNameAddress
BloggsJoe 
RoeJane 

提示:始终使用IS NULL来查找空值。


IS NOT NULL运算符


 以下SQL语句使用IS NOT NULL运算符来列出所有具有地址的人员:

SELECT LastName, FirstName, Address FROM PersonsWHERE Address IS NOT NULL;

 结果集将如下所示:

LastNameFirstNameAddress
DoeJohn542 W. 27th Street
SmithJohn110 Bishopsgate


语法:


 创建表的时候,NULL 的基本语法如下:

SQL> CREATE TABLE CUSTOMERS(   ID   INT              NOT NULL,   NAME VARCHAR (20)     NOT NULL,   AGE  INT              NOT NULL,   ADDRESS  CHAR (25) ,   SALARY   DECIMAL (18, 2),          PRIMARY KEY (ID));

 这里,NOT NULL表示对于给定列,必须按照其数据类型明确赋值。有两列并没有使用 NOT NULL 来限定,也就是说这些列可以为 NULL。

 值为 NULL 的字段是在记录创建的过程中留空的字段。


示例:


 NULL 值会给选取数据带来麻烦。不过,因为 NULL 和其他任何值作比较,其结果总是未知的,所以含有 NULL 的记录不会包含在最终结果里面。

 必须使用 IS NULL 或者 IS NOT NULL 来检测某个字段是否为 NULL。

 考虑下面的 CUSTOMERS 数据表,里面包含的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |          ||  7 | Muffy    |  24 | Indore    |          |+----+----------+-----+-----------+----------+

 下面是 IS NOT NULL 运算符的用法:

SQL> SELECT  ID, NAME, AGE, ADDRESS, SALARY     FROM CUSTOMERS     WHERE SALARY IS NOT NULL;

 上面语句的运行结果如下:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 |+----+----------+-----+-----------+----------+

 下面是 IS NULL 运算符的用法:

SQL> SELECT  ID, NAME, AGE, ADDRESS, SALARY     FROM CUSTOMERS     WHERE SALARY IS NULL;

 其运行结果如下:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  6 | Komal    |  22 | MP        |          ||  7 | Muffy    |  24 | Indore    |          |+----+----------+-----+-----------+----------+



SQL UPDATE 语句


 UPDATE 语句用于更新表中已存在的记录。

 还可以使用AND或OR运算符组合多个条件。               

SQL UPDATE 语法

 具有WHERE子句的UPDATE查询的基本语法如下所示:

UPDATE table_nameSET column1 = value1, column2 = value2, ...WHERE condition;

lamp请注意
更新表中的记录时要小心!
要注意SQL UPDATE 语句中的 WHERE 子句!

WHERE子句指定哪些记录需要更新。如果省略WHERE子句,所有记录都将更新!

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL UPDATE 实例


 以下SQL语句为第一个客户(CustomerID = 1)更新了“ContactName”和“City”:

实例

UPDATE Customers
SET ContactName = 'Alfred Schmidt', City= 'Frankfurt'
WHERE CustomerID = 1;

 现在,选自 "Customers" 表的数据如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteAlfred SchmidtObere Str. 57Frankfurt12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

更新多个记录


 WHERE子句决定了将要更新的记录数量。

 以下SQL语句将把国家/地区为"Mexico"的所有记录的联系人姓名更新为“Juan”:

UPDATE CustomersSET ContactName='Juan'WHERE Country='Mexico';

 “Customers”表中的选择现在看起来像这样:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteAlfred SchmidtObere Str. 57Frankfurt12209Germany
2Ana Trujillo Emparedados y heladosJuanAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaJuanMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden


Update 警告!


 更新记录时要小心。如果您省略WHERE子句,所有记录将被更新!

UPDATE CustomersSET ContactName='Juan';


 "Customers" 表将如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteJuanObere Str. 57Frankfurt12209Germany
2Ana Trujillo Emparedados y heladosJuanAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaJuanMataderos 2312México D.F.05023Mexico
4

Around the HornJuan120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpJuanBerguvsvägen 8LuleåS-958 22Sweden


章节小测


 现在,通过以下题目测测看您对“SQL UPDATE 语句(更新表中的记录)”的掌握程度吧!

 SQL UPDATE语句:在本部分测验中,您将练习使用 SQL 的 UPDATE 语句来更新数据。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL DELETE 语句


 DELETE语句用于删除表中现有记录。

SQL DELETE 语法

DELETE FROM table_nameWHERE condition;

lamp请注意
删除表格中的记录时要小心!
注意SQL DELETE 语句中的 WHERE 子句!

WHERE子句指定需要删除哪些记录。如果省略了WHERE子句,表中所有记录都将被删除!

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL DELETE 实例


 假设我们想从"Customers" 表中删除客户“Alfreds Futterkiste”。

 我们使用以下SQL语句:

实例

DELETE FROM Customers
WHERE CustomerName='Alfreds Futterkiste';

 现在,"Customers" 表如下所示:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

删除所有数据


 您可以删除表中的所有行,而不需要删除该表。这意味着表的结构、属性和索引将保持不变:

DELETE FROM table_name;

 或者

DELETE * FROM table_name;
注意:在没有备份的情况下,删除记录要格外小心!因为你删除了不能重复!


章节小测


 现在,通过以下题目测测看您对“SQL Delete 语句(删除表中的记录)”的掌握程度吧!

 SQL Delete语句:在本部分测验中,您将通过一道选择填空来练习使用 SQL 的 Delete 语句。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL 运算符


运算符是保留字或主要用于 SQL 语句的 WHERE 子句中的字符,用于执行操作,例如:比较和算术运算。 这些运算符用于指定 SQL 语句中的条件,并用作语句中多个条件的连词。

常见运算符有以下几种:

  • 算术运算符
  • 比较运算符
  • 逻辑运算符
  • 否定条件运算符

SQL 算术运算符


假设变量 a 的值是:10,变量 b 的值是:20,以下为各运算符执行结果:

运算符描述例子

+

加法,执行加法运算。

a + b 得到 30

-

减法,执行减法运算。

a - b 得到  -10

*

乘法,执行乘法运算。

a * b 得到  200

/

用左操作数除以右操作数。

b / a 得到  2

%

用左操作数除以右操作数并返回余数。

b % a 得到  0


SQL 比较运算符


假设变量 a 的值是:10,变量 b 的值是:20,以下为各运算符执行结果:

运算符描述例子
=检查两个操作数的值是否相等,如果是,则条件为真(true)。
(a = b) is false.
!=检查两个操作数的值是否相等,如果值不相等则条件为真(true)。
(a != b)  is  true.
<>检查两个操作数的值是否相等,如果值不相等则条件为真(true)。(a <> b) is true.
>检查左操作数的值是否大于右操作数的值,如果是,则条件为真(true)。
(a > b) is false.
<检查左操作数的值是否小于右操作数的值,如果是,则条件为真(true)。(a < b) is true.
>=检查左操作数的值是否大于或等于右操作数的值,如果是,则条件为真(true)。(a >= b) is false
<=检查左操作数的值是否小于或等于右操作数的值,如果是,则条件为真(true)。(a <= b) is true.
!<检查左操作数的值是否不小于右操作数的值,如果是,则条件变为真(true)。(a !< b) is false.
!>检查左操作数的值是否不大于右操作数的值,如果是,则条件变为真(true)。(a !> b) is true.

SQL 逻辑运算符:


这是在 SQL 所有的逻辑运算符的列表。

运算符描述
ALLALL运算符用于将值与另一个值集中的所有值进行比较。
ANDAND运算符允许在SQL语句的WHERE子句中指定多个条件。
ANYANY运算符用于根据条件将值与列表中的任何适用值进行比较。
BETWEENBETWEEN运算符用于搜索在给定最小值和最大值内的值。
EXISTSEXISTS运算符用于搜索指定表中是否存在满足特定条件的行。
ININ运算符用于将值与已指定的文字值列表进行比较。
LIKELIKE运算符用于使用通配符运算符将值与类似值进行比较。
NOTNOT运算符反转使用它的逻辑运算符的含义。 例如:NOT EXISTS, NOT BETWEEN, NOT IN等等,这是一个否定运算符。
OROR运算符用于组合SQL语句的WHERE子句中的多个条件。
IS NULLIS NULL运算符用于将值与NULL值进行比较。
UNIQUEUNIQUE运算符搜索指定表的每一行的唯一性(无重复项)。


章节小测


 现在,通过以下题目测测看您对“SQL 运算符”的掌握程度吧!

 SQL  IN,NOT IN 运算符:在本部分测验中,您将练习使用 SQL 的 IN 运算符以及 NOT IN 运算符

 点击此处进行测试>>

 SQL  LIKE 运算符:在本部分测验中,您将练习使用 SQL 的 LIKE 运算符

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>


SQL 表达式


 表达式是计算值的一个或多个值、运算符和SQL函数的组合。这些SQL表达式类似于公式,它们是用查询语言编写的。

 您还可以使用它们查询数据库中的特定数据集。

句法

 考虑SELECT语句的基本语法,如下所示:

SELECT column1, column2, columnN FROM table_name WHERE [CONDITION|EXPRESSION];

 有不同类型的sql表达式,如下所示:

  • 布尔型
  • 数值型
  • 日期

 现在让我们详细讨论每一个问题。


布尔表达式


 SQL布尔表达式基于匹配单个值获取数据。

 句法:

SELECT column1, column2, columnN FROM table_name WHERE SINGLE VALUE MATCHING EXPRESSION;

 使用具有以下记录的Customers表:

SQL> SELECT * FROM CUSTOMERS;+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+7 rows in set (0.00 sec)

 下表是一个简单的示例,展示了各种sql布尔表达式的用法。

SQL> SELECT * FROM CUSTOMERS WHERE SALARY = 10000;+----+-------+-----+---------+----------+| ID | NAME  | AGE | ADDRESS | SALARY   |+----+-------+-----+---------+----------+|  7 | Muffy |  24 | Indore  | 10000.00 |+----+-------+-----+---------+----------+1 row in set (0.00 sec)

数值表达式


 数值表达式用于在任何查询中执行任何数学运算。

 句法:

SELECT numerical_expression as  OPERATION_NAME[FROM table_nameWHERE CONDITION] ;

 这里,数值表达式用于数学表达式或任何公式。下面是一个简单的示例,展示了SQLNDigitic表达式的用法:

SQL> SELECT (15 + 6) AS ADDITION+----------+| ADDITION |+----------+|       21 |+----------+1 row in set (0.00 sec)

 有几个内置函数,如avg()、sum()、count()等,用于对表或特定表列执行所谓的聚合数据计算。

SQL> SELECT COUNT(*) AS "RECORDS" FROM CUSTOMERS; +---------+| RECORDS |+---------+|       7 |+---------+1 row in set (0.00 sec)

日期表达式


 日期表达式返回当前系统日期和时间值:

SQL>  SELECT CURRENT_TIMESTAMP;+---------------------+| Current_Timestamp   |+---------------------+| 2009-11-12 06:40:23 |+---------------------+1 row in set (0.00 sec)

 另一个日期表达式如下所示:

SQL>  SELECT  GETDATE();;+-------------------------+| GETDATE                 |+-------------------------+| 2009-10-22 12:07:18.140 |+-------------------------+1 row in set (0.00 sec)


SQL 选择数据库 USE语句


 当SQL Schema中有多个数据库时,在开始操作之前,需要选择一个执行所有操作的数据库。

 SQL USE语句用于选择SQL架构中的任何现有数据库。

句法

 USE语句的基本语法如下所示 :

USE DatabaseName;

 数据库名称在RDBMS中必须是唯一的。


实例


 您可以查看可用的数据库,如下所示:

SQL> SHOW DATABASES;+--------------------+| Database           |+--------------------+| information_schema || AMROOD             || TUTORIALSPOINT     || mysql              || orig               || test               |+--------------------+6 rows in set (0.00 sec)

 现在,如果您想使用AMROOD数据库,那么您可以执行以下SQL命令并开始使用AMROOD数据库。

SQL> USE AMROOD;


SQL SELECT TOP 子句


  • SELECT TOP 子句用于指定要返回的记录数量。
  • SELECT TOP子句在包含数千条记录的大型表上很有用。返回大量记录会影响性能。

注:并不是所有的数据库系统都支持SELECT TOP子句。MySQL支持LIMIT子句来选择有限数量的记录,而Oracle使用ROWNUM。

SQL Server / MS Access 语法

SELECT TOP number|percent column_name(s)FROM table_nameWHERE condition;

MySQL 和 Oracle 中的 SQL SELECT TOP 是等价的


MySQL语法:

SELECT column_name(s)FROM table_nameWHERE conditionLIMIT number;

实例

SELECT *FROM PersonsLIMIT 5;

Oracle 语法

SELECT column_name(s)FROM table_nameWHERE ROWNUM <= number;

实例

SELECT *FROM PersonsWHERE ROWNUM <=5;

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL SELECT TOP 实例


 以下SQL语句从"Customers" 表中选择前两条记录:

实例

SELECT TOP 2 * FROM Customers;

SQL SELECT TOP PERCENT 实例


 以下SQL语句从 "Customers" 表中选择前50%的记录:

实例

SELECT TOP 50 PERCENT * FROM Customers;

SQL TOP,LIMIT和ROWNUM示例


 以下SQL语句从"Customers"表中选择前三个记录:

SELECT TOP 3 * FROM Customers;

 以下SQL语句显示了使用LIMIT子句的等效示例:

SELECT * FROM CustomersLIMIT 3;

 以下SQL语句显示了使用ROWNUM的等效示例:

SELECT * FROM CustomersWHERE ROWNUM <= 3;

SQL TOP PERCENT示例


 以下SQL语句从"Customers"表中选择记录的前50%:

SELECT TOP 50 PERCENT * FROM Customers;

添加一个条件


 以下SQL语句从"Customers"表中选择国家为"Germany"的前三条记录:

SELECT TOP 3 * FROM CustomersWHERE Country='Germany';

 以下SQL语句显示了使用LIMIT子句的等效示例:

SELECT * FROM CustomersWHERE Country='Germany'LIMIT 3;

 以下SQL语句显示了使用ROWNUM的等效示例:

SELECT * FROM CustomersWHERE Country='Germany' AND ROWNUM <= 3;

为什么要LIMIT你的查询结果


 LIMIT作为一种简单的分页方法,主要是为了减少数据返回的时间,如果您查询一个非常大的表(例如一个有数十万或数百万行的表)而不使用限制,那么您可能会等待很长时间才能显示所有的结果,所以使用LIMIT可以减少查询数据返回的时间,提高效率。


章节小测


 现在,通过以下题目测测看您对本章节内容的掌握程度吧!

 SQL LIMIT关键字:在本部分测验中,您将练习使用 SQL LIMIT 关键字返回所有符合 SQL 语句中指定条件的结果。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL LIKE 运算符


 在WHERE子句中使用LIKE运算符来搜索列中的指定模式。 

 有两个通配符与LIKE运算符一起使用:

  • - 百分号表示零个,一个或多个字符
  • _ - 下划线表示单个字符

 注意: MS Access使用问号(?)而不是下划线(_)。

 百分号和下划线也可以组合使用! 

SQL LIKE 语法

SELECT column1, column2, ...FROM table_nameWHERE columnN LIKE pattern;
 提示:您还可以使用AND或OR运算符组合任意数量的条件。

 下面是一些使用'%'和'_'通配符显示不同LIKE运算符的例子:

LIKE 运算符描述
WHERE CustomerName LIKE 'a%'查找以“a”开头的任何值
WHERE CustomerName LIKE '%a'查找以“a”结尾的任何值
WHERE CustomerName LIKE '%or%'在任何位置查找任何具有“or”的值
WHERE CustomerName LIKE '_r%'在第二个位置查找任何具有“r”的值
WHERE CustomerName LIKE 'a_%_%'查找以“a”开头且长度至少为3个字符的值
WHERE ContactName LIKE 'a%o'找到以"a"开头,以"o"结尾的值

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers"表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LIKE 运算符实例


 以下SQL语句选择以“a”开头的CustomerName的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE 'a%';

 以下SQL语句选择客户名称以“a”结尾的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE '%a';

 以下SQL语句选择客户名称在任何位置都具有“或”的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE '%or%';

 以下SQL语句选择客户名称在第二位具有“r”的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE '_r%';

 以下SQL语句选择客户名称以“a”开头且长度至少为3个字符的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE 'a_%_%';

 以下SQL语句选择联系人名称以“a”开头并以“o”结尾的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE ContactName LIKE 'a%o';

 以下SQL语句选择客户名称不以“a”开头的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName NOT LIKE 'a%';

 以下SQL语句选择客户名称以“a”开头,以“s”结尾的5位字符的所有客户:

 代码示例:

SELECT * FROM CustomersWHERE CustomerName LIKE 'a___s';


SQL Wildcards 通配符


 通配符用于替换字符串中的任何其他字符。

 通配符与 SQL LIKE 运算符一起使用。在 WHERE 子句中使用LIKE运算符来搜索列中的指定模式。 

 有两个通配符与 LIKE 运算符一起使用:

  • - 百分号表示零个,一个或多个字符
  • _ - 下划线表示单个字符

 注意: 

  • MS Access 使用星号(*)通配符而不是百分比符号(%)通配符。 
  • MS Access 使用问号(?)而不是下划线(_)。

 在MS Access和SQL Server中,你也可以使用:

  • [ charlist ] - 定义要匹配的字符的集合和范围
  • [^ charlist ]或[!charlist ] - 定义不匹配字符的集合和范围

 通配符也可以组合使用!

 下面是一些使用''和'_'通配符显示不同LIKE运算符的例子:

LIKE运算符描述
WHERE CustomerName LIKE 'a%'查找以“a”开头的任何值
WHERE CustomerName LIKE '%a'查找以"a"结尾的任何值
WHERE CustomerName LIKE '%or%'在任何位置查找任何具有“or”的值
WHERE CustomerName LIKE '_r%'在第二个位置查找任何具有“r”的值
WHERE CustomerName LIKE 'a_%_%'查找以“a”开头并且长度至少为3个字符的值
WHERE ContactName LIKE 'a%o'查找以“a”开始并以“o”结尾的任何值

演示数据库


 在本教程中,我们将使用著名的 Northwind 示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

使用 SQL % 通配符


 以下 SQL 语句选择所有客户 City 以字母“ber”开头:

实例

SELECT * FROM Customers
WHERE City LIKE 'ber%';

 以下 SQL 语句选择 City 中包含“es”模式的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE '%es%';

使用 SQL _ 通配符


 以下 SQL 语句选择 City 以任意字符开头,然后是“erlin”的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE '_erlin';

 以下 SQL 语句选择 City 开头为“L”,后面是任意字符,后面是“n”,后面是任意字符,后面是“on”的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE 'L_n_on';

使用 SQL [charlist] 通配符


以下 SQL 语句选择所有客户 City 以"b"、"s"或"p"开头:

实例

SELECT * FROM Customers
WHERE City LIKE '[bsp]%';

以下 SQL 语句选择“City”以“a”、“b”或“c”开头的所有客户:

实例

SELECT * FROM Customers
WHERE City LIKE '[a-c]%';

以下 SQL 语句选择所有客户 City 不以"b"、"s"或"p"开头:

实例

SELECT * FROM Customers
WHERE City LIKE '[!bsp]%';

使用[!charlist]通配符


以下两个 SQL 语句选择所有客户的城市不以“b”,“s”或“p”开头:

代码示例:

SELECT * FROM CustomersWHERE City LIKE '[!bsp]%';

要么:

代码示例:

SELECT * FROM CustomersWHERE City NOT LIKE '[bsp]%';


SQL IN 运算符


 IN 运算符允许您在 WHERE 子句中指定多个值。

 IN 运算符是多个 OR 条件的简写。

SQL IN 语法

SELECT column_name(s)FROM table_nameWHERE column_name IN (value1, value2, ...);

或者

SELECT column_name(s)FROM table_nameWHERE column_name IN (SELECT STATEMENT);

演示数据库


 在本教程中,我们将使用著名的 Northwind 示例数据库。

 以下数据选取自"Customers" 表:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4
Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

IN 操作符实例


 以下 SQL 语句选取位于“Germany”,“France”和“UK”的所有客户:

代码示例:

SELECT * FROM CustomersWHERE Country IN ('Germany', 'France', 'UK');

 以下 SQL 语句选取不在“Germany”,“France”或“UK”中的所有客户:

代码示例:

SELECT * FROM CustomersWHERE Country NOT IN ('Germany', 'France', 'UK');

 以下 SQL 语句选取来自同一国家的所有客户作为供应商:

代码示例:

SELECT * FROM CustomersWHERE Country IN (SELECT Country FROM Suppliers);


SQL BETWEEN 运算符


 BETWEEN运算符用于选取介于两个值之间的数据范围内的值。

 BETWEEN运算符选择给定范围内的值。值可以是数字,文本或日期。

 BETWEEN运算符是包含性的:包括开始和结束值,且开始值需小于结束值。 

SQL BETWEEN 语法

SELECT column_name(s)FROM table_nameWHERE column_name BETWEEN value1 AND value2;

 要否定BETWEEN运算符的结果,可以添加NOT运算符:

SELECT column_name(s)FROM table_nameWHERE column_name NOT BETWEEN value1 AND value2;

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Products"表中的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning1248 - 6 oz jars22
5Chef Anton's Gumbo Mix1236 boxes21.35

BETWEEN 运算符实例


 以下SQL语句选择价格在10到20之间的所有产品:

实例

SELECT * FROM Products
WHERE Price BETWEEN 10 AND 20;


NOT BETWEEN 操作符实例

 要显示前面示例范围之外的产品,请使用NOT BETWEEN:

实例

SELECT * FROM Products
WHERE Price NOT BETWEEN 10 AND 20;

带有 IN 的 BETWEEN 操作符实例


 以下SQL语句选择价格在10到20之间但CategoryID不是1、2或3的所有产品:

实例

SELECT * FROM Products
WHERE (Price BETWEEN 10 AND 20)
AND NOT CategoryID IN (1,2,3);

带有文本值的 BETWEEN 操作符实例


 以下SQL语句选择所有带有ProductName BETWEEN'Carnarvon Tigers'和'Mozzarella di Giovanni'的产品:

实例

SELECT * FROM Products
WHERE ProductName BETWEEN 'Carnarvon Tigers' AND 'Mozzarella di Giovanni'
ORDER BY ProductName;

带有文本值的 NOT BETWEEN 操作符实例


 以下SQL语句选择ProductName不是BETWEEN'Carnarvon Tigers'和'Mozzarella di Giovanni'的所有产品:

实例

SELECT * FROM Products
WHERE ProductName NOT BETWEEN 'Carnarvon Tigers' AND 'Mozzarella di Giovanni'
ORDER BY ProductName;

示例表


 下面是选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
102489057/4/19963
102498167/5/19961
102503447/8/19962
102518437/9/19961
102527647/10/19962

带有日期值的 BETWEEN 操作符实例


 以下 SQL 语句选取 OrderDate 介于 '04-July-1996' 和 '09-July-1996' 之间的所有订单:

实例

SELECT * FROM Orders
WHERE OrderDate BETWEEN #07/04/1996# AND #07/09/1996#;

lamp

请注意,在不同的数据库中,BETWEEN 操作符会产生不同的结果!
在一些数据库中,BETWEEN 选取介于两个值之间但不包括两个测试值的字段。
在一些数据库中,BETWEEN 选取介于两个值之间且包括两个测试值的字段。
在一些数据库中,BETWEEN 选取介于两个值之间且包括第一个测试值但不包括最后一个测试值的字段。

因此,请检查您的数据库是如何处理 BETWEEN 操作符!


章节小测


 现在,通过以下题目测测看您对“SQL BETWEEN运算符”内容的掌握程度吧!

 SQL BETWEEN运算符:在本部分测验中,您将练习使用 SQL BETWEEN 运算符返回介于两个值之间的数据范围内的值。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

 更多测试题请参考:《SQL测验》题库>>

SQL 通用数据类型


 数据类型定义了存储在列中的值的类型。


SQL 通用数据类型


 数据库表中的每一列都需要有一个名称和数据类型。

 SQL 开发人员必须在创建 SQL 表时决定表中的每个列将要存储的数据的类型。数据类型是一个标签,是便于 SQL 了解每个列期望存储什么类型的数据的指南,它也标识了 SQL 如何与存储的数据进行交互。

 下面的表格列出了 SQL 中通用的数据类型:

数据类型描述
CHARACTER(n)字符/字符串。固定长度 n。
VARCHAR(n) 或
CHARACTER VARYING(n)
字符/字符串。可变长度。最大长度 n。
BINARY(n)二进制串。固定长度 n。
BOOLEAN存储 TRUE 或 FALSE 值
VARBINARY(n) 或
BINARY VARYING(n)
二进制串。可变长度。最大长度 n。
INTEGER(p)整数值(没有小数点)。精度 p。
SMALLINT整数值(没有小数点)。精度 5。
INTEGER整数值(没有小数点)。精度 10。
BIGINT整数值(没有小数点)。精度 19。
DECIMAL(p,s)精确数值,精度 p,小数点后位数 s。例如:decimal(5,2) 是一个小数点前有 3 位数小数点后有 2 位数的数字。
NUMERIC(p,s)精确数值,精度 p,小数点后位数 s。(与 DECIMAL 相同)
FLOAT(p)近似数值,尾数精度 p。一个采用以 10 为基数的指数计数法的浮点数。该类型的 size 参数由一个指定最小精度的单一数字组成。
REAL近似数值,尾数精度 7。
FLOAT近似数值,尾数精度 16。
DOUBLE PRECISION近似数值,尾数精度 16。
DATE存储年、月、日的值。
TIME存储小时、分、秒的值。
TIMESTAMP存储年、月、日、小时、分、秒的值。
INTERVAL由一些整数字段组成,代表一段时间,取决于区间的类型。
ARRAY元素的固定长度的有序集合
MULTISET元素的可变长度的无序集合
XML存储 XML 数据

SQL 数据类型快速参考手册


 然而,不同的数据库为数据类型定义提供了不同的选择。
 下表显示了不同数据库平台上某些数据类型的通用名称:

数据类型AccessSQLServerOracleMySQLPostgreSQL
booleanYes/NoBitByteN/ABoolean
integerNumber (integer)IntNumberInt
Integer
Int
Integer
floatNumber (single)Float
Real
NumberFloatNumeric
currencyCurrencyMoneyN/AN/AMoney
string (fixed)N/ACharCharCharChar
string (variable)Text (<256)
Memo (65k+)
VarcharVarchar
Varchar2
VarcharVarchar
binary objectOLE Object MemoBinary (fixed up to 8K)
Varbinary (<8K)
Image (<2GB)
Long
Raw
Blob
Text
Binary
Varbinary

lamp

注释:在不同的数据库中,相同的数据类型可能有不同的名称。即使名字相同,大小和其他细节也可能不同!请随时检查文件!

来自 W3CSchool 的 SQL 快速参考


SQL 语句 语法
AND / OR SELECT column_name(s)
FROM table_name
WHERE condition
AND|OR condition
ALTER TABLE ALTER TABLE table_name
ADD column_name datatype

or

ALTER TABLE table_name
DROP COLUMN column_name

AS (alias) SELECT column_name AS column_alias
FROM table_name

or

SELECT column_name
FROM table_name AS table_alias

BETWEEN SELECT column_name(s)
FROM table_name
WHERE column_name
BETWEEN value1 AND value2
CREATE DATABASE CREATE DATABASE database_name
CREATE TABLE CREATE TABLE table_name
(
column_name1 data_type,
column_name2 data_type,
column_name2 data_type,
...
)
CREATE INDEX CREATE INDEX index_name
ON table_name (column_name)

or

CREATE UNIQUE INDEX index_name
ON table_name (column_name)

CREATE VIEW CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
DELETE DELETE FROM table_name
WHERE some_column=some_value

or

DELETE FROM table_name
(Note: Deletes the entire table!!)

DELETE * FROM table_name
(Note: Deletes the entire table!!)

DROP DATABASE DROP DATABASE database_name
DROP INDEX DROP INDEX table_name.index_name (SQL Server)
DROP INDEX index_name ON table_name (MS Access)
DROP INDEX index_name (DB2/Oracle)
ALTER TABLE table_name
DROP INDEX index_name (MySQL)
DROP TABLE DROP TABLE table_name
GROUP BY SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value
IN SELECT column_name(s)
FROM table_name
WHERE column_name
IN (value1,value2,..)
INSERT INTO INSERT INTO table_name
VALUES (value1, value2, value3,....)

or

INSERT INTO table_name
(column1, column2, column3,...)
VALUES (value1, value2, value3,....)

INNER JOIN SELECT column_name(s)
FROM table_name1
INNER JOIN table_name2
ON table_name1.column_name=table_name2.column_name
LEFT JOIN SELECT column_name(s)
FROM table_name1
LEFT JOIN table_name2
ON table_name1.column_name=table_name2.column_name
RIGHT JOIN SELECT column_name(s)
FROM table_name1
RIGHT JOIN table_name2
ON table_name1.column_name=table_name2.column_name
FULL JOIN SELECT column_name(s)
FROM table_name1
FULL JOIN table_name2
ON table_name1.column_name=table_name2.column_name
LIKE SELECT column_name(s)
FROM table_name
WHERE column_nameLIKE pattern
ORDER BY SELECT column_name(s)
FROM table_name
ORDER BY column_name [ASC|DESC]
SELECT SELECT column_name(s)
FROM table_name
SELECT * SELECT *
FROM table_name
SELECT DISTINCT SELECT DISTINCT column_name(s)
FROM table_name
SELECT INTO SELECT *
INTO new_table_name [IN externaldatabase]
FROM old_table_name

or

SELECT column_name(s)
INTO new_table_name [IN externaldatabase]
FROM old_table_name

SELECT TOP SELECT TOP number|percent column_name(s)
FROM table_name
TRUNCATE TABLE TRUNCATE TABLE table_name
UNION SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
UNION ALL SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2
UPDATE UPDATE table_name
SET column1=value, column2=value,...
WHERE some_column=some_value
WHERE SELECT column_name(s)
FROM table_name
WHERE column_name operator value


SQL 连接(Joins)


 SQL join 用于把来自两个或多个表的行结合起来。


SQL JOIN


 SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。

 简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上。

 最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN)。 SQL INNER JOIN 从多个表中返回满足 JOIN 条件的所有行。

 让我们看看选自 "Orders" 表的数据:

OrderIDCustomerIDOrderDate
1030821996-09-18
10309371996-09-19
10310771996-09-20

 然后,看看选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameCountry
1Alfreds FutterkisteMaria AndersGermany
2Ana Trujillo Emparedados y heladosAna TrujilloMexico
3Antonio Moreno TaqueríaAntonio MorenoMexico

 请注意,"Orders" 表中的 "CustomerID" 列指向 "Customers" 表中的客户。上面这两个表是通过 "CustomerID" 列联系起来的。

 然后,如果我们运行下面的 SQL 语句(包含 INNER JOIN):

实例

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;

 运行结果如下所示:

OrderIDCustomerNameOrderDate
10308Ana Trujillo Emparedados y helados1996-09-18

不同的 SQL JOIN


 在我们继续讲解实例之前,我们先列出您可以使用的不同的 SQL JOIN 类型:

  • INNER JOIN:如果表中有至少一个匹配,则返回行
  • LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN:只要其中一个表中存在匹配,则返回行
  • SELF JOIN:用于将表连接到自己,就好像该表是两个表一样,临时重命名了SQL语句中的至少一个表
  • CARTESIAN JOIN:从两个或多个连接表返回记录集的笛卡儿积 


SQL INNER JOIN 关键字(内部连接)


 内部链接INNER JOIN关键字选择两个表中具有匹配值的记录。

SQL INNER JOIN 语法

SELECT column_name(s)FROM table1INNER JOIN table2 ON table1.column_name = table2.column_name;

 注释:INNER JOIN 与 JOIN 是相同的。

SQL INNER JOIN


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
103093731996-09-191
103107781996-09-202

SQL INNER JOIN 实例


 以下SQL语句将返回所有下订单的客户:

实例

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
ORDER BY Customers.CustomerName;

注释:如果表中至少有一个匹配项,INNER JOIN 关键字将返回一行。如果 "Customers" 表中的行与"Orders" 不匹配,则不会列出行。


加入三张表


 以下SQL语句选择包含客户和货运单信息的所有订单:

 代码示例:

SELECT Orders.OrderID, Customers.CustomerName, Shippers.ShipperNameFROM ((OrdersINNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID)INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID);


SQL 左连接 LEFT JOIN 关键字


 SQL左链接LEFT JOIN关键字返回左表(表1)中的所有行,即使在右表(表2)中没有匹配。如果在正确的表中没有匹配,结果是NULL。

SQL LEFT JOIN 语法

SELECT column_name(s)                FROM table1                LEFT JOIN table2                ON table1.column_name=table2.column_name;       

 或:

SELECT column_name(s)                FROM table1                LEFT OUTER JOIN table2                ON table1.column_name=table2.column_name;      

注释:在一些数据库中,LEFT JOIN称为LEFT OUT ER JOIN。

SQL LEFT JOIN


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是 "Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
103093731996-09-191
103107781996-09-202

SQL LEFT JOIN 实例


 以下SQL语句将选择所有客户以及他们可能拥有的任何订单:

实例

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
ORDER BY Customers.CustomerName;

注释:LEFT JOIN 关键字返回左表(Customers)中的所有行,即使在右边表(Orders)中没有匹配。


SQL右连接 RIGHT JOIN 关键字


 SQL右链接 RIGHT JOIN 关键字返回右表(table2)的所有行,即使在左表(table1)上没有匹配。如果左表没有匹配,则结果为NULL。

SQL RIGHT JOIN 语法

SELECT column_name(s)FROM table1RIGHT JOIN table2 ON table1.column_name = table2.column_name;

注释:在一些数据库中,RIGHT JOIN 称为 RIGHT OUTER JOIN。

SQL RIGHT JOIN



演示数据库

 在本教程中,我们将使用着名的Northwind示例数据库。

 以下是"Orders"表中的一个选项:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
103093731996-09-191
103107781996-09-202

 并从"Employees" t表中选择:

EmployeeIDLastNameFirstNameBirthDatePhoto
1DavolioNancy12/8/1968EmpID1.pic
2FullerAndrew2/19/1952EmpID2.pic
3LeverlingJanet8/30/1963EmpID3.pic

SQL RIGHT JOIN 实例


 以下SQL语句将返回所有雇员以及他们可能已经放置的任何订单:

实例

SELECT Orders.OrderID, Employees.LastName, Employees.FirstName
FROM Orders
RIGHT JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID
ORDER BY Orders.OrderID;

注释:RIGHT JOIN 关键字返回右表(Employees)的所有行,即使在左表(Orders)中没有匹配。


SQL FULL OUTER JOIN 关键字


 当左(表1)或右(表2)表记录匹配时,FULL OUTER JOIN关键字将返回所有记录。

 注意: FULL OUTER JOIN可能会返回非常大的结果集!

SQL FULL OUTER JOIN 语法

SELECT column_name(s)FROM table1FULL OUTER JOIN table2 ON table1.column_name = table2.column_name;

SQL FULL OUTER JOIN


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
10308271996-09-183
10309331996-09-191
103107781996-09-202

SQL FULL OUTER JOIN 实例


 以下SQL语句选择所有客户和所有订单:

SELECT Customers.CustomerName, Orders.OrderIDFROM CustomersFULL OUTER JOIN Orders ON Customers.CustomerID=Orders.CustomerIDORDER BY Customers.CustomerName;

 从这套结果中选择的数据如下:

CustomerNameOrderID
Alfreds Futterkiste 
Ana Trujillo Emparedados y helados10308
Antonio Moreno Taquería10309
 10310

注意: FULL OUTER JOIN关键字返回左表(Customers)中的所有行,以及右表(Orders)中的所有行。如果 "Customers"中的行中没有"Orders"中的匹配项,或者"Orders"中的行中没有 "Customers"中的匹配项,那么这些行也会列出。


SQL自连接


 自联接是一种常规联接,但表本身是连接的。

Self JOIN语法

SELECT column_name(s)FROM table1 T1, table1 T2WHERE condition;

演示数据库


 在本教程中,我们将使用着名的Northwind示例数据库。

 以下是"Customers"表中的选择:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

SQL Self JOIN示例


 以下SQL语句匹配来自同一城市的客户:

代码示例

SELECT A.CustomerName AS CustomerName1, B.CustomerName AS CustomerName2, A.CityFROM Customers A, Customers BWHERE A.CustomerID <> B.CustomerIDAND A.City = B.City ORDER BY A.City;


SQL UNION 运算符


  UNION运算符用于组合两个或更多SELECT语句的结果集,而不返回任何重复的行。

  • UNION中的每个SELECT语句必须具有相同的列数
  • 这些列也必须具有相似的数据类型
  • 每个SELECT语句中的列也必须以相同的顺序排列
  • 每个SELECT语句必须有相同数目的列表达式
  • 但是每个SELECT语句的长度不必相同

SQL UNION 语法1

SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2;

注释:默认情况下,UNION 运算符选择一个不同的值。如果允许重复值,请使用 UNION ALL。

SQL UNION 语法2

SELECT column_name(s) FROM table1[WHERE condition]UNIONSELECT column_name(s) FROM table2[WHERE condition];

 给定的条件可以是基于您的需求的任何给定表达式。

SQL UNION ALL 语法1

 UNION All运算符用于组合两个SELECT语句(包括重复行)的结果。

 适用于UNION子句的相同规则将适用于UNION All操作符。

SELECT column_name(s) FROM table1UNION ALLSELECT column_name(s) FROM table2;

注释:UNION结果集中的列名总是等于UNION中第一个SELECT语句中的列名。

SQL UNION ALL 语法2

SELECT column_name(s) FROM table1[WHERE condition]UNION ALLSELECT column_name(s) FROM table2[WHERE condition];


演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1
Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Suppliers" 表的数据:

SupplierIDSupplierNameContactNameAddressCityPostalCodeCountry
1Exotic LiquidCharlotte Cooper49 Gilbert St.LondonaEC1 4SDUK
2New Orleans Cajun DelightsShelley BurkeP.O. Box 78934New Orleans70117USA
3Grandma Kelly's HomesteadRegina Murphy707 Oxford Rd.Ann Arbor48104USA


SQL UNION 实例

 下面的 SQL 语句从 "Customers" 和 "Suppliers" 表中选取所有不同的城市(只有不同的值):

实例

SELECT City FROM Customers
UNION
SELECT City FROM Suppliers
ORDER BY City;

注释:不能用 UNION 来列出两个表中的所有城市。如果一些客户和供应商来自同一个城市,每个城市将只被列入一个列表。UNION将只选择不同的值。请使用UNION ALL选择重复值!


SQL UNION ALL 实例


 以下SQL语句使用 UNION ALL 从 "Customers"和"Suppliers" 表中选择所有城市(也是重复的值):

实例

SELECT City FROM Customers
UNION ALL
SELECT City FROM Suppliers
ORDER BY City;

带有 WHERE 的 SQL UNION ALL


 以下SQL语句使用UNIONALL从"Customers"和 "Suppliers" 表中选择所有德国城市(也是重复数值):

实例

SELECT City, Country FROM Customers
WHERE Country='Germany'
UNION ALL
SELECT City, Country FROM Suppliers
WHERE Country='Germany'
ORDER BY City;

SQL UNION与WHERE


 以下SQL语句从“客户”和“供应商”中选择所有不同的德国城市(只有不同​​的值):

SELECT City, Country FROM CustomersWHERE Country='Germany'UNIONSELECT City, Country FROM SuppliersWHERE Country='Germany'ORDER BY City;

另一个UNION示例


 以下SQL语句列出了所有客户和供应商:

SELECT 'Customer' As Type, ContactName, City, CountryFROM CustomersUNIONSELECT 'Supplier', ContactName, City, CountryFROM Suppliers;

 还有另外两个子句(即运算符),它们类似于UNION子句:

  • SQL INTERSECT子句
    用于组合两个SELECT语句,但只返回与第二个SELECT语句中的一行相同的第一个SELECT语句中的行。
  • SQL EXCEPT子句
    用于组合两个SELECT语句,并返回第一个SELECT语句中没有由第二个SELECT语句返回的行。


章节小测


 现在,通过以下题目测测看您对“SQL UNION 运算符”内容的掌握程度吧!

 SQL UNION 操作符:在本部分测验中,您将练习使用 SQL UNION 操作符将多个表的数据合并为一个综合数据集。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL SELECT INTO 语句


 使用 SQL,您可以将信息从一个表中复制到另一个表中。

 SELECT INTO 语句从一个表中复制数据,然后将数据插入到另一个新表中。

SQL SELECT INTO 语法

 我们可以把所有的列都复制到新表中:

SELECT *INTO newtable [IN externaldb]FROM table1;

 或者只复制希望的列插入到新表中:

SELECT column_name(s)INTO newtable [IN externaldb]FROM table1;

lamp

提示:将使用SELECT语句中定义的列名和类型创建新表。您可以使用AS子句来应用一个新名称。


SQL SELECT INTO 实例


 创建 Customers 的备份复件:

SELECT *INTO CustomersBackup2013FROM Customers;

 请使用 IN 子句来复制表到另一个数据库中:

SELECT *INTO CustomersBackup2013 IN 'Backup.mdb'FROM Customers;

 只复制一些列插入到新表中:

SELECT CustomerName,ContactNameINTO CustomersBackup2013FROM Customers;

 只复制德国的客户插入到新表中:

SELECT *INTO CustomersBackup2013FROM CustomersWHERE Country='Germany';

 复制多个表中的数据插入到新表中:

SELECT Customers.CustomerName, Orders.OrderIDINTO CustomersOrderBackup2013FROM CustomersLEFT JOIN OrdersON Customers.CustomerID=Orders.CustomerID;

 提示:SELECT INTO 语句可以用于在另一种模式下创建一个新的空表。只需添加WHERE子句,使查询返回时没有数据:

SELECT *INTO newtableFROM table1WHERE 1=0;


SQL INSERT INTO SELECT 语句


 使用SQL,您可以将信息从一个表中复制到另一个表中。

 INSERT INTO SELECT 语句从表中复制数据,并将数据插入现有的表中。目标表中的任何现有行都不会受到影响。

SQL INSERT INTO SELECT 语法

 我们可以将所有列从一个表中复制到另一个已经存在的表中:

INSERT INTO table2              SELECT * FROM table1;    

 或者我们可以把想要的列复制到另一个现有的表中:

INSERT INTO table2               (column_name(s))              SELECT column_name(s)             FROM table1;   

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers"表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

 选自 "Suppliers" 表的数据:

SupplierIDSupplierNameContactNameAddressCityPostal CodeCountryPhone
1Exotic LiquidCharlotte Cooper49 Gilbert St.LondonaEC1 4SDUK(171) 555-2222
2New Orleans Cajun DelightsShelley BurkeP.O. Box 78934New Orleans70117USA(100) 555-4822
3Grandma Kelly's HomesteadRegina Murphy707 Oxford Rd.Ann Arbor48104USA(313) 555-5735

SQL INSERT INTO SELECT 实例


 把 "Suppliers" 一栏复制到 "Customers" 一栏:

实例

INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country FROM Suppliers;

 只将德国供应商的副本插入 "Customers" :

实例

INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country FROM Suppliers
WHERE Country='Germany';


SQL 撤销索引、撤销表以及撤销数据库


 通过使用 DROP 语句,可以轻松地删除索引、表和数据库。


DROP INDEX 语句


 DROP INDEX 语句用于删除表中的索引。

用于 MS Access 的 DROP INDEX 语法:

DROP INDEX index_name ON table_name      

用于 MS SQL Server 的 DROP INDEX 语法:

DROP INDEX table_name.index_name     

用于 DB2/Oracle 的 DROP INDEX 语法:

DROP INDEX index_name   

用于 MySQL 的 DROP INDEX 语法:

ALTER TABLE table_name DROP INDEX index_name       

DROP TABLE 语句


 DROP TABLE 语句用于删除表。

DROP TABLE table_name      

DROP DATABASE 语句


 DROP DATABASE 语句用于删除数据库。

DROP DATABASE database_name    

TRUNCATE TABLE 语句


 如果我们只需要删除表中的数据,而不删除表本身,那么我们该怎么做?

 使用TRUNCATE TABLE语句:

TRUNCATE TABLE table_name   


章节小测


 现在,通过以下题目测测看您对本章节内容的掌握程度吧!

 SQL DROP TABLE:在本部分测验中,您将练习使用 SQL 语句来删除表中的数据。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL CREATE DATABASE 语句


 CREATE DATABASE 语句用于创建数据库。

 在RDBMS中,数据库名称始终应该是唯一的。

SQL CREATE DATABASE 语法

CREATE DATABASE dbname;

 在创建任何数据库之前,请确保您拥有管理权限。


SQL CREATE DATABASE 实例


 下面的 SQL 语句创建一个名为 "my_db" 的数据库:

CREATE DATABASE my_db;

 数据库表可以通过 CREATE TABLE 语句来添加。

 创建数据库后,您可以在数据库列表中检查它。

 语句:

SHOW DATABASES;

SQL CREATE TABLE 语句


SQL CREATE TABLE 语句

 CREATE TABLE 语句用于创建数据库中的表。

 表由行和列组成,每个表都必须有个表名。

SQL CREATE TABLE 语法

CREATE TABLE table_name                (                column_name1 data_type(size),                column_name2 data_type(size),                column_name3 data_type(size),                ....                );       

 column_name 参数规定表中列的名称。

 data_type 参数规定列的数据类型(例如 varchar、integer、decimal、date 等等)。

 size 参数规定表中列的最大长度。

 提示:如需了解 MS Access、MySQL 和 SQL Server 中可用的数据类型,请访问我们完整的 数据类型参考手册


SQL CREATE TABLE 实例

 现在我们想要创建一个名为 "Persons" 的表,包含五列:PersonID、LastName、FirstName、Address 和 City。

 我们使用下面的 CREATE TABLE 语句:

实例

CREATE TABLE Persons
(
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);

 PersonID列数据类型为int,包含一个整数。

 LastName、FirstName、Address和City列具有包含字符的varchar数据类型,这些字段的最大长度为255个字符。

 空 "Persons" 表是这样的:

PersonIDLastNameFirstNameAddressCity
     

 提示:使用 INSERT INTO 语句将数据写入空表。


章节小测


 现在,通过以下题目测测看您对“SQL CREATE TABLE 语句”内容的掌握程度吧!

 SQL CREATE TABLE:在本部分测验中,您将练习使用 SQL CREATE TABLE 语句创建数据库中的表,创建时请注意语法。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费



SQL ALTER TABLE 语句


ALTER TABLE 语句

 ALTER TABLE 语句用于在现有表中添加、删除或修改列。

SQL ALTER TABLE 语法

 若要向表中添加列,请使用以下语法:

ALTER TABLE table_name                ADD column_name datatype      

 若要删除表中的列,请使用以下语法(请注意,一些数据库系统不允许这样删除数据库表中的列):

ALTER TABLE table_name                DROP COLUMN column_name      

 若要更改表中列的数据类型,请使用以下语法:

SQL Server / MS Access:

ALTER TABLE table_name                ALTER COLUMN column_name datatype       

My SQL / Oracle:

ALTER TABLE table_name                MODIFY COLUMN column_name datatype        


SQL ALTER TABLE 实例

 请看 "Persons" 表:

P_IdLastNameFirstNameAddressCity
1HansenOlaTimoteivn 10Sandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStorgt 20Stavanger

 现在,我们想在 "Persons" 表中添加一个名为 "DateOfBirth" 的列。

 我们使用下面的 SQL 语句:

ALTER TABLE Persons                ADD DateOfBirth date       

 请注意,新列 "DateOfBirth" 的类型是 date,可以存放日期。数据类型规定列中可以存放的数据的类型。如需了解 MS Access、MySQL 和 SQL Server 中可用的数据类型,请访问我们完整的 数据类型参考手册

 现在,"Persons" 表将如下所示:

P_IdLastNameFirstNameAddressCityDateOfBirth
1HansenOlaTimoteivn 10Sandnes 
2SvendsonToveBorgvn 23Sandnes 
3PettersenKariStorgt 20Stavanger 


改变数据类型实例

 现在,我们想要改变 "Persons" 表中 "DateOfBirth" 列的数据类型。

 我们使用下面的 SQL 语句:

ALTER TABLE Persons                ALTER COLUMN DateOfBirth year      

 请注意,现在 "DateOfBirth" 列的类型是 year,可以存放 2 位或 4 位格式的年份。


DROP COLUMN 实例

 接下来,我们想要删除 "Person" 表中的 "DateOfBirth" 列。

 我们使用下面的 SQL 语句:

ALTER TABLE Persons                DROP COLUMN DateOfBirth        

 现在,"Persons" 表将如下所示:

P_IdLastNameFirstNameAddressCity
1HansenOlaTimoteivn 10Sandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStorgt 20Stavanger

章节小测


 现在,通过以下题目测测看您对本章节内容的掌握程度吧!

 SQL ALTER TABLE:在本部分测验中,您将练习使用 SQL ALTER TABLE 语句在已有的表中添加、删除或修改列。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

SQL AUTO INCREMENT 字段


 Auto-increment 会在新记录插入表中时生成一个唯一的数字。


AUTO INCREMENT 字段


 我们通常希望在每次插入新记录时自动创建主键字段的值。

 我们可以在表中创建一个自动增量(auto-increment)字段。


用于 MySQL 的语法


 以下SQL语句将 "Persons" 表中的“ID”列定义为自动递增(auto-increment)主键字段:

CREATE TABLE Persons                (                ID int NOT NULL AUTO_INCREMENT,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                PRIMARY KEY (ID)                )

 MySQL使用AUTO_INCREMENT关键字来执行自动增量( auto-increment )任务。 

 默认情况下,AUTO_INCREMENT的起始值为1,每个新记录增加1。

 若要以其他值开始AUTO_INCREMENT序列,请使用以下SQL语法:

ALTER TABLE Persons AUTO_INCREMENT=100       

 要在 "Persons" 表中插入新记录,我们不需要为"ID"栏指定值(自动添加唯一值):

INSERT INTO Persons (FirstName,LastName)                VALUES ('Lars','Monsen')        

 上面的SQL语句在 "Persons" 表中插入一个新记录。“ID”栏将得到唯一值。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


用于 SQL Server 的语法


 以下SQL语句将 "Persons" 表中的“ID”列定义为自动递增( auto-increment )主键字段:

CREATE TABLE Persons                (                ID int IDENTITY(1,1) PRIMARY KEY,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )       

 MS SQL Server使用IDENTITY关键字执行自动增量( auto-increment )任务。

 在上面的示例中,IDENTITY的起始值为1,每个新记录增量为1。

 提示:指定“ID”列以10开头,并递增5,将标识( identity )更改为IDENTITY(10,5)。

 要在 "Persons" 表中插入新记录,我们不需要为"ID"栏指定值(自动添加唯一值):

INSERT INTO Persons (FirstName,LastName)                VALUES ('Lars','Monsen')        

 上面的 SQL 语句在 "Persons" 表中插入一个新记录。“ID”栏将得到唯一值。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


用于 Access 的语法


 以下 SQL 语句将 "Persons" 表中的“ID”列定义为自动递增( auto-increment )主键字段:

CREATE TABLE Persons                (                ID Integer PRIMARY KEY AUTOINCREMENT,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )       

 MS Access使用 AUTOINCREMENT 关键字执行自动增量( auto-increment )任务。

 默认情况下,AUTOINCREMENT的起始值为1,每个新记录递增 1。

 提示:指定“ID”栏以10开头,并递增5,将自动递增( autoincrement )更改为自动递增(105)( AUTOINCREMENT(10,5))。

 要在 "Persons" 表中插入新记录,我们不需要为"ID"栏指定值(自动添加唯一值):

INSERT INTO Persons (FirstName,LastName)                VALUES ('Lars','Monsen')        

 上面的 SQL 语句在 "Persons" 表中插入一个新记录。“ID”栏将得到唯一值。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


语法 for Oracle


 在 Oracle 中,代码有点复杂。

 您必须使用序列( sequence )对象(该对象生成数字序列)创建自动增量( auto-increment )字段。

 使用以下CREATSEQUENT语法:

CREATE SEQUENCE seq_person                MINVALUE 1                START WITH 1                INCREMENT BY 1                CACHE 10        

 上面的代码创建了一个名为seq_pean的序列( sequence) 对象,它以1开头,以1递增。此对象缓存10个值以提高性能。缓存选项指定要存储多少序列值以提高访问速度。

 要在"Persons" 表中插入新记录,我们必须使用nextval函数,该函数从seq_hor序列检索下一个值:

INSERT INTO Persons (ID,FirstName,LastName)                VALUES (seq_person.nextval,'Lars','Monsen')       

 上面的SQL语句在 "Persons" 表中插入一个新记录。"ID" 列从 seq_person 序列中分配下一个数字。"FirstName"栏设置为"Lars","LastName"栏设置为"Monsen"。


章节小测


 现在,通过以下题目测测看您对“SQL AUTO INCREMENT 字段”内容的掌握程度吧!

 SQL 自动递增(AUTO INCREMENT):在本部分测验中,您将练习使用 SQL 语句来在新记录插入表中时生成一个唯一的数字。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

SQL 视图(Views)


 视图是可视化的表。

 本章讲解如何创建、更新和删除视图。


SQL CREATE VIEW 语句


 在 SQL 中,视图是基于 SQL 语句的结果集的可视化表。

 视图包含行和列,就像真正的表一样。视图中的字段是一个或多个数据库中真实表中的字段。

 您可以添加 SQL 函数,在哪里添加,并将语句连接到视图,或者您可以呈现数据,就像数据来自单个表一样。


SQL CREATE VIEW 语法

CREATE VIEW view_name AS                SELECT column_name(s)                FROM table_name                WHERE condition      

 注释:视图总是显示最新数据!每当用户查询视图时,数据库引擎就使用视图的 SQL 语句重新构建数据。


SQL CREATE VIEW 实例


 示例数据库 Northwind 默认安装了一些视图。

 "Current Product List"(当前产品列表)视图从"Products"表中列出了所有正在使用的产品(未停产的产品)。这个视图使用下面的 SQL 创建:

CREATE VIEW [Current Product List] AS                SELECT ProductID,ProductName                FROM Products                WHERE Discontinued=No      

 我们可以像这样查询上面这个视图:

SELECT * FROM [Current Product List]        

 Northwind 样本数据库的另一个视图会选取 "Products" 表中所有单位价格高于平均单位价格的产品:

CREATE VIEW [Products Above Average Price] AS                SELECT ProductName,UnitPrice                FROM Products                WHERE UnitPrice>(SELECT AVG(UnitPrice) FROM Products)     

 我们可以像这样查询上面这个视图:

SELECT * FROM [Products Above Average Price]        

 Northwind 样本数据库的另一个视图会计算在 1997 年每个种类的销售总数。请注意,这个视图会从另一个名为 "Product Sales for 1997" 的视图那里选取数据:

CREATE VIEW [Category Sales For 1997] AS                SELECT DISTINCT CategoryName,Sum(ProductSales) AS CategorySales                FROM [Product Sales for 1997]                GROUP BY CategoryName       

 我们可以像这样查询上面这个视图:

SELECT * FROM [Category Sales For 1997]       

 我们也可以向查询添加条件。现在,我们仅仅需要查看 "Beverages" 类的销售总数:

SELECT * FROM [Category Sales For 1997]                WHERE CategoryName='Beverages'        

SQL 更新视图


 您可以使用下面的语法来更新视图:

SQL CREATE OR REPLACE VIEW 语法

CREATE OR REPLACE VIEW view_name AS                SELECT column_name(s)                FROM table_name                WHERE condition        

 现在,我们希望向 "Current Product List" 视图添加 "Category" 列。我们将通过下列 SQL 更新视图:

CREATE OR REPLACE VIEW [Current Product List] AS                SELECT ProductID,ProductName,Category                FROM Products                WHERE Discontinued=No        

SQL 撤销视图


 您可以通过 DROP VIEW 命令来删除视图。

SQL DROP VIEW 语法

DROP VIEW view_name     


SQL Date 函数


注意:当我们处理日期时,最困难的任务可能是确保插入日期的格式与数据库中日期列中的格式相匹配。

 只要您的数据仅包含日期的一部分,运行查询就不会成为问题。然而,当涉及到时间时,情况会稍微复杂一些。

 在讨论日期查询的复杂性之前,让我们看看最重要的内置日期处理程序。


MySQL Date 函数


 下表列出了 MySQL 中最重要的内置日期函数:

函数描述
NOW()返回当前的日期和时间
CURDATE()返回当前的日期
CURTIME()返回当前的时间
DATE()提取日期或日期/时间表达式的日期部分
EXTRACT()返回日期/时间的单独部分
DATE_ADD()向日期添加指定的时间间隔
DATE_SUB()从日期减去指定的时间间隔
DATEDIFF()返回两个日期之间的天数
DATE_FORMAT()用不同的格式显示日期/时间

SQL Server Date 函数


 下表列出了SQL 服务器中最重要的内置日期函数:

函数描述
GETDATE()返回当前的日期和时间
DATEPART()返回日期/时间的单独部分
DATEADD()在日期中添加或减去指定的时间间隔
DATEDIFF()返回两个日期之间的时间
CONVERT()用不同的格式显示日期/时间

SQL Date 数据类型


 MySQL 使用下列数据类型在数据库中存储日期或时间值:

  • DATE - 格式:YYYY-MM-DD
  • DATETIME - 格式:YYYY-MM-DD HH:MM:SS
  • TIMESTAMP - 格式:YYYY-MM-DD HH:MM:SS
  • YEAR - 格式:YYYY 或 YY

 SQL Server 使用下列数据类型在数据库中存储日期或时间值:

  • DATE - 格式:YYYY-MM-DD
  • DATETIME - 格式:YYYY-MM-DD HH:MM:SS
  • SMALLDATETIME - 格式:YYYY-MM-DD HH:MM:SS
  • TIMESTAMP - 格式:唯一的数字

 注释:在数据库中创建新表时,需要为该列选择数据类型!

 如需了解所有可用的数据类型,请访问我们完整的 数据类型参考手册


SQL 日期处理


 Note注意:如果您不涉及时间部分,那么我们可以轻松比较两个日期!

 假设我们有以下“订单”表:

OrderIdProductNameOrderDate
1Geitost2008-11-11
2Camembert Pierrot2008-11-09
3Mozzarella di Giovanni2008-11-11
4Mascarpone Fabioli2008-10-29

 现在,我们希望从上表中选取 OrderDate 为 "2008-11-11" 的记录。

 我们使用下面的 SELECT 语句:

SELECT * FROM Orders WHERE OrderDate='2008-11-11'   

 结果集如下所示:

OrderIdProductNameOrderDate
1Geitost2008-11-11
3Mozzarella di Giovanni2008-11-11

 现在,假设 "Orders" 表如下所示(请注意 "OrderDate" 列中的时间部分):

OrderIdProductNameOrderDate
1Geitost2008-11-11 13:23:44
2Camembert Pierrot2008-11-09 15:45:21
3Mozzarella di Giovanni2008-11-11 11:12:01
4Mascarpone Fabioli2008-10-29 14:56:59

 如果我们使用和上面一样的 SELECT 语句:

SELECT * FROM Orders WHERE OrderDate='2008-11-11'   

 这样我们就不会有结果了!这是因为查询的日期不包含时间部分。

提示:如果您想使查询更加简单和易于维护,请不要使用日期中的时间部分!

SQL NULL 值


 NULL 空值代表丢失的未知数据。

 默认情况下,表列可以保存 NULL 值。

 本章解释 IS NULL 和 IS NOT NULL 操作符。


SQL NULL 值


 如果表中的列是可选的,那么我们可以插入一个新记录或更新一个现有记录,而无需向列添加一个值。这意味着该字段将存储为 NULL 。

 NULL 值的处理与其他值不同。

 NULL 为未知或不适当值的占位符。

 Note注释:无法比较 NULL 和 0;它们是不等价的。


SQL 的 NULL 值处理


 请看下面的 "Persons" 表:

P_IdLastNameFirstNameAddressCity
1HansenOlaSandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStavanger

 如果 "Persons" 表 "Address" 一栏是可选的。这意味着,如果在 "Address" 列中插入一个没有值的记录,则 "Address" 列将用 NULL 值保存。

 那么如何测试null的值呢?

 您不能使用比较操作符测试 NULL 值,例如=、<或<>。

 我们必须使用 IS NULL 和 IS NOT NULL 操作符。


SQL IS NULL


 我们如何才能选择 "Address" 列中有 NULL 值的记录?

 我们必须使用 IS NULL 操作符:

SELECT LastName,FirstName,Address FROM PersonsWHERE Address IS NULL

 结果集如下所示:

LastNameFirstNameAddress
HansenOla
PettersenKari

 Note提示:总是使用 IS NULL 来查找 NULL 值。


SQL IS NOT NULL


 我们如何才能选择 "Address" 列中没有 NULL 值的记录?

 我们必须使用 IS NOT NULL 操作符:

SELECT LastName,FirstName,Address FROM PersonsWHERE Address IS NOT NULL

 结果集如下所示:

LastNameFirstNameAddress
SvendsonToveBorgvn 23

 在下一节中,我们将了解 ISNULL()、NVL()、IFNULL() 和 COALESCE() 函数。


SQL 别名(Aliases)


 通过使用 SQL,可以为表名称或列名称指定别名(Alias)。

  • SQL 别名用于为表或表中的列提供临时名称,数据库中的实际表名不会更改。
  • SQL 别名通常用于使列名更具可读性。
  • SQL 一个别名只存在于查询期间。
  • 表别名的使用是在特定SQL语句中重命名表。
  • 列别名用于为特定SQL查询重命名表的列。

列的 SQL Alias 语法

SELECT column_name AS alias_name
FROM table_name;
WHERE [condition];

表的 SQL Alias 语法

SELECT column_name(s)FROM table_name AS alias_name;WHERE [condition];

演示数据库


 在本教程中,我们将使用著名的Northwind示例数据库。

 以下是"Customers" 表中的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK

 下面是选自 "Orders" 表的数据:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
103545881996-11-143
10355461996-11-151
103568661996-11-182

列的 Alias 实例


 以下SQL语句创建两个别名,一个用于CustomerID列,另一个用于CustomerName列:

实例

SELECT CustomerID as ID, CustomerName AS Customer
FROM Customers;

 以下SQL语句创建两个别名,一个用于CustomerName列,一个用于ContactName列。注:如果别名包含空格,则需要双引号或方括号:

实例

SELECT CustomerName AS Customer, ContactName AS [Contact Person]
FROM Customers;

 以下SQL语句创建一个名为“Address”的别名,它包含四列(Address,PostalCode,City and Country):

SELECT CustomerName, Address + ', ' + PostalCode + ', ' + City + ', ' + Country AS AddressFROM Customers;

 注意:要使上面的SQL语句在MySQL中工作,请使用以下命令:

SELECT CustomerName, CONCAT(Address,', ',PostalCode,', ',City,', ',Country) AS AddressFROM Customers;

表的 Alias 实例


 以下SQL语句选择CustomerID = 4(“围绕角”)的所有订单。我们使用“Customers”和“Orders”表,给它们分别为“c”和“o”的表别名(这里我们使用别名来使SQL更短):

实例

SELECT o.OrderID, o.OrderDate, c.CustomerName
FROM Customers AS c, Orders AS o
WHERE c.CustomerName="Around the Horn" AND c.CustomerID=o.CustomerID;

 以下SQL语句与上述相同,但没有别名:

实例

SELECT Orders.OrderID, Orders.OrderDate, Customers.CustomerName
FROM Customers, Orders
WHERE Customers.CustomerName="Around the Horn" AND Customers.CustomerID=Orders.CustomerID;

 在下列情况下使用别名是有用的:

  • 查询涉及多个表

  • 用于查询函数

  • 需要把两个或更多的列放在一起

  • 列名长或可读性差


示例


 考虑下面两个数据表:

 (a)CUSTOMERS 表,如下:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)另一个是 ORDERS 表,如下所示:

+-----+---------------------+-------------+--------+|OID  | DATE                | CUSTOMER_ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 下面是表别名的用法:

SQL> SELECT C.ID, C.NAME, C.AGE, O.AMOUNT         FROM CUSTOMERS AS C, ORDERS AS O        WHERE  C.ID = O.CUSTOMER_ID;

 上面语句的运行结果如下所示:

+----+----------+-----+--------+| ID | NAME     | AGE | AMOUNT |+----+----------+-----+--------+|  3 | kaushik  |  23 |   3000 ||  3 | kaushik  |  23 |   1500 ||  2 | Khilan   |  25 |   1560 ||  4 | Chaitali |  25 |   2060 |+----+----------+-----+--------+

 下面是列别名的用法:

SQL> SELECT  ID AS CUSTOMER_ID, NAME AS CUSTOMER_NAME     FROM CUSTOMERS     WHERE SALARY IS NOT NULL;

 其运行结果如下所示:

+-------------+---------------+| CUSTOMER_ID | CUSTOMER_NAME |+-------------+---------------+|           1 | Ramesh        ||           2 | Khilan        ||           3 | kaushik       ||           4 | Chaitali      ||           5 | Hardik        ||           6 | Komal         ||           7 | Muffy         |+-------------+---------------+


 SQL约束用于指定表中数据的规则。

SQL 约束


 约束是作用于数据表中列上的规则,用于限制表中数据的类型。约束的存在保证了数据库中数据的精确性和可靠性。

 约束有列级和表级之分,列级约束作用于单一的列,而表级约束作用于整张数据表。

 下面是 SQL 中常用的约束,这些约束虽然已经在关系型数据库管理系统一章中讨论过了,但是仍然值得在这里回顾一遍。

 约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。


SQL创建约束


 当使用CREATE TABLE语句创建表时,或者在使用ALTER TABLE语句创建表之后,可以指定约束。

 语法

CREATE TABLE table_name (    column1 datatype constraint,    column2 datatype constraint,    column3 datatype constraint,    ....);

SQL CREATE TABLE + CONSTRAINT 语法

CREATE TABLE table_name                (                column_name1 data_type(size) constraint_name,                column_name2 data_type(size) constraint_name,                column_name3 data_type(size) constraint_name,                ....                );      

删除约束


 任何现有约束都可以通过在 ALTER TABLE 命令中指定 DROP CONSTRAINT 选项的方法删除掉。

 例如,要去除 EMPLOYEES 表中的主键约束,可以使用下述命令:

ALTER TABLE EMPLOYEES DROP CONSTRAINT EMPLOYEES_PK;

 一些数据库实现可能提供了删除特定约束的快捷方法。例如,要在 Oracle 中删除一张表的主键约束,可以使用如下命令:

ALTER TABLE EMPLOYEES DROP PRIMARY KEY;

 某些数据库实现允许禁用约束。这样与其从数据库中永久删除约束,你可以只是临时禁用掉它,过一段时间后再重新启用。


完整性约束


 完整性约束用于保证关系型数据库中数据的精确性和一致性。对于关系型数据库来说,数据完整性由参照完整性(referential integrity,RI)来保证。

 有很多种约束可以起到参照完整性的作用,这些约束包括主键约束(Primary Key)、外键约束(Foreign Key)、唯一性约束(Unique Constraint)以及上面提到的其他约束。


SQL NOT NULL 约束


 在默认的情况下,表的列接受 NULL 值。

 NOT NULL 约束强制列不接受 NULL 值。

 NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。

 下面的 SQL 强制 "P_Id" 列和 "LastName" 列不接受 NULL 值:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255))


SQL UNIQUE 约束


 UNIQUE 约束唯一标识数据库表中的每条记录。

 UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。

 PRIMARY KEY 约束拥有自动定义的 UNIQUE 约束。

 请注意,每个表可以有多个 UNIQUE 约束,但是每个表只能有一个 PRIMARY KEY 约束。


CREATE TABLE 时的 SQL UNIQUE 约束


 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 UNIQUE 约束:

 MySQL:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                UNIQUE (P_Id)                )        

 SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL UNIQUE,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )        

 如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)                )       

ALTER TABLE 时的 SQL UNIQUE 约束


 当表已被创建时,如需在 "P_Id" 列创建 UNIQUE 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD UNIQUE (P_Id)      

 如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)       

撤销 UNIQUE 约束


 如需撤销 UNIQUE 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE Persons                DROP INDEX uc_PersonID        

 SQL Server / Oracle / MS Access:

ALTER TABLE Persons                DROP CONSTRAINT uc_PersonID       


SQL PRIMARY KEY 约束


 PRIMARY KEY 约束唯一标识数据库表中的每条记录。

 主键必须包含唯一的值。

 主键列不能包含 NULL 值。

 每个表都应该有一个主键,并且每个表只能有一个主键。


CREATE TABLE 时的 SQL PRIMARY KEY 约束


 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 PRIMARY KEY 约束:

 MySQL:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                PRIMARY KEY (P_Id)                )        

 SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL PRIMARY KEY,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255)                )        

 如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons                (                P_Id int NOT NULL,                LastName varchar(255) NOT NULL,                FirstName varchar(255),                Address varchar(255),                City varchar(255),                CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)                )     

 注释:在上面的实例中,只有一个主键 PRIMARY KEY(pk_PersonID)。然而,pk_PersonID 的值是由两个列(P_Id 和 LastName)组成的。


ALTER TABLE 时的 SQL PRIMARY KEY 约束


 当表已被创建时,如需在 "P_Id" 列创建 PRIMARY KEY 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD PRIMARY KEY (P_Id)        

 如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons                ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)       

 注释:如果您使用 ALTER TABLE 语句添加主键,必须把主键列声明为不包含 NULL 值(在表首次创建时)。


撤销 PRIMARY KEY 约束


 如需撤销 PRIMARY KEY 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE Persons                DROP PRIMARY KEY      

 SQL Server / Oracle / MS Access:

ALTER TABLE Persons               DROP CONSTRAINT pk_PersonID


SQL FOREIGN KEY 约束


 一个表中的 FOREIGN KEY 指向另一个表中的 PRIMARY KEY。

 让我们通过一个实例来解释外键。请看下面两个表:

 "Persons" 表:

P_IdLastNameFirstNameAddressCity
1HansenOlaTimoteivn 10Sandnes
2SvendsonToveBorgvn 23Sandnes
3PettersenKariStorgt 20Stavanger

 "Orders" 表:

O_IdOrderNoP_Id
1778953
2446783
3224562
4245621

 请注意,"Orders" 表中的 "P_Id" 列指向 "Persons" 表中的 "P_Id" 列。

 "Persons" 表中的 "P_Id" 列是 "Persons" 表中的 PRIMARY KEY。

 "Orders" 表中的 "P_Id" 列是 "Orders" 表中的 FOREIGN KEY。

 FOREIGN KEY 约束用于预防破坏表之间连接的行为。

 FOREIGN KEY 约束也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。


CREATE TABLE 时的 SQL FOREIGN KEY 约束


 下面的 SQL 在 "Orders" 表创建时在 "P_Id" 列上创建 FOREIGN KEY 约束:

 MySQL:

CREATE TABLE Orders                (                O_Id int NOT NULL,                OrderNo int NOT NULL,                P_Id int,               PRIMARY KEY (O_Id),                FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)                )     

 SQL Server / Oracle / MS Access:

CREATE TABLE Orders                (                O_Id int NOT NULL PRIMARY KEY,                OrderNo int NOT NULL,                P_Id int FOREIGN KEY REFERENCES Persons(P_Id)                )      

 如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Orders                (                O_Id int NOT NULL,                OrderNo int NOT NULL,                P_Id int,                PRIMARY KEY (O_Id),                CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)                REFERENCES Persons(P_Id)                )      

ALTER TABLE 时的 SQL FOREIGN KEY 约束


 当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders                ADD FOREIGN KEY (P_Id)                REFERENCES Persons(P_Id)   

 如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders                ADD CONSTRAINT fk_PerOrders                FOREIGN KEY (P_Id)                REFERENCES Persons(P_Id)       

撤销 FOREIGN KEY 约束


 如需撤销 FOREIGN KEY 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE Orders                DROP FOREIGN KEY fk_PerOrders        

 SQL Server / Oracle / MS Access:

ALTER TABLE Orders                DROP CONSTRAINT fk_PerOrders     


SQL DEFAULT 约束


 DEFAULT 约束用于向列中插入默认值。

 如果没有规定其他的值,那么会将默认值添加到所有的新记录。


CREATE TABLE 时的 SQL DEFAULT 约束


 下面的 SQL 在 "Persons" 表创建时在 "City" 列上创建 DEFAULT 约束:

 My SQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255) DEFAULT 'Sandnes')

 通过使用类似 GETDATE() 这样的函数,DEFAULT 约束也可以用于插入系统值:

CREATE TABLE Orders(O_Id int NOT NULL,OrderNo int NOT NULL,P_Id int,OrderDate date DEFAULT GETDATE())

ALTER TABLE 时的 SQL DEFAULT 约束


 当表已被创建时,如需在 "City" 列创建 DEFAULT 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE PersonsALTER City SET DEFAULT 'SANDNES'

 SQL Server / MS Access:

ALTER TABLE Persons ADD CONSTRAINT DF_Persons_City DEFAULT('SANDNES') FOR City--注释--Persons 为表名--City 为列名--DF_Persons_City 为我们创建的默认约束的名称 约束名称一般为:约束类型简称_表名_列名

 Oracle:

ALTER TABLE PersonsMODIFY City DEFAULT 'SANDNES'

撤销 DEFAULT 约束


 如需撤销 DEFAULT 约束,请使用下面的 SQL:

 MySQL:

ALTER TABLE PersonsALTER City DROP DEFAULT

 SQL Server / Oracle / MS Access:

ALTER TABLE PersonsALTER COLUMN City DROP DEFAULT

SQL CHECK 约束


 CHECK 约束用于限制列中的值的范围。

 如果对单个列定义 CHECK 约束,那么该列只允许特定的值。

 如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制。


CREATE TABLE 时的 SQL CHECK 约束


 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 CHECK 约束。CHECK 约束规定 "P_Id" 列必须只包含大于 0 的整数。

 MySQL:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255),CHECK (P_Id>0))

 SQL Server / Oracle / MS Access:

CREATE TABLE Persons(P_Id int NOT NULL CHECK (P_Id>0),LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255))

 如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons(P_Id int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Address varchar(255),City varchar(255),CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes'))

ALTER TABLE 时的 SQL CHECK 约束


 当表已被创建时,如需在 "P_Id" 列创建 CHECK 约束,请使用下面的 SQL:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE PersonsADD CHECK (P_Id>0)

 如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法:

 MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE PersonsADD CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')

撤销 CHECK 约束


 如需撤销 CHECK 约束,请使用下面的 SQL:

 SQL Server / Oracle / MS Access:

ALTER TABLE PersonsDROP CONSTRAINT chk_Person

 MySQL:

ALTER TABLE PersonsDROP CHECK chk_Person

SQL JOIN 连接


 SQL 连接(JOIN) 子句用于将数据库中两个或者两个以上表中的记录组合起来。连接通过共有值将不同表中的字段组合在一起。

 我们来看看"Orders"表中的选择:

OrderIDCustomerIDOrderDate
1030821996-09-18
10309371996-09-19
10310771996-09-20

 然后,查看"Customers"表中的选择:

CustomerIDCustomerNameContactNameCountry
1Alfreds FutterkisteMaria AndersGermany
2Ana Trujillo Emparedados y heladosAna TrujilloMexico
3Antonio Moreno TaqueríaAntonio MorenoMexico

 请注意,"Orders"表中的“客户ID”列是指"CustomerID"表中的“客户ID”。上面两个表格之间的关系是“CustomerID”列。

 然后,我们可以创建下面的SQL语句(包含一个INNER JOIN),它选择两个表中具有匹配值的记录:

 代码示例:

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDateFROM OrdersINNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID;

 它会产生这样的东西:

OrderIDCustomerNameOrderDate
10308Ana Trujillo Emparedados y helados9/18/1996
10365Antonio Moreno Taquería11/27/1996
10383Around the Horn12/16/1996
10355Around the Horn11/15/1996
10278Berglunds snabbköp8/12/1996

 考虑下面两个表,(a)CUSTOMERS 表:

    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+

 (b)另一个表是 ORDERS 表:

    +-----+---------------------+-------------+--------+    |OID  | DATE                | CUSTOMER_ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我们用 SELECT 语句将这个两张表连接(JOIN)在一起:

    SQL> SELECT ID, NAME, AGE, AMOUNT            FROM CUSTOMERS, ORDERS            WHERE  CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句的运行结果如下所示:

    +----+----------+-----+--------+    | ID | NAME     | AGE | AMOUNT |    +----+----------+-----+--------+    |  3 | kaushik  |  23 |   3000 |    |  3 | kaushik  |  23 |   1500 |    |  2 | Khilan   |  25 |   1560 |    |  4 | Chaitali |  25 |   2060 |    +----+----------+-----+--------+

不同类型的SQL联接


 SQL 中有多种不同的连接:

  • 内连接(INNER JOIN):当两个表中都存在匹配时,才返回行。
  • 左连接(LEFT JOIN):返回左表中的所有行,即使右表中没有匹配的行。
  • 右连接(RIGHT JOIN):返回右表中的所有行,即使左表中没有匹配的行。
  • 全连接(FULL JOIN):只要某一个表存在匹配,就返回行。
  • 笛卡尔连接(CARTESIAN JOIN):返回两个或者更多的表中记录集的笛卡尔积。

SQL INNER JOIN    SQL左连接    SQL RIGHT JOIN    SQL全外连接

内连接

 最常用也最重要的连接形式是内连接,有时候也被称作“EQUIJOIN”(等值连接)。

 内连接根据连接谓词来组合两个表中的字段,以创建一个新的结果表。SQL 查询会比较逐个比较表 1 和表 2 中的每一条记录,来寻找满足连接谓词的所有记录对。当连接谓词得以满足时,所有满足条件的记录对的字段将会结合在一起构成结果表。

语法:

 内连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1INNER JOIN table2ON table1.common_field = table2.common_field;

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在,让我们用内连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     INNER JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+----+----------+--------+---------------------+| ID | NAME     | AMOUNT | DATE                |+----+----------+--------+---------------------+|  3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||  2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||  4 | Chaitali |   2060 | 2008-05-20 00:00:00 |+----+----------+--------+---------------------+

左连接

 左链接返回左表中的所有记录,即使右表中没有任何满足匹配条件的记录。这意味着,如果 ON 子句在右表中匹配到了 0 条记录,该连接仍然会返回至少一条记录,不过返回的记录中所有来自右表的字段都为 NULL。

 这就意味着,左连接会返回左表中的所有记录,加上右表中匹配到的记录,或者是 NULL (如果连接谓词无法匹配到任何记录的话)。

语法:

 左连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1LEFT JOIN table2ON table1.common_field = table2.common_field;

 这里,给出的条件可以是任何根据你的需要写出的条件。

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在,让我们用左连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     LEFT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+----+----------+--------+---------------------+| ID | NAME     | AMOUNT | DATE                |+----+----------+--------+---------------------+|  1 | Ramesh   |   NULL | NULL                ||  2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||  3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||  4 | Chaitali |   2060 | 2008-05-20 00:00:00 ||  5 | Hardik   |   NULL | NULL                ||  6 | Komal    |   NULL | NULL                ||  7 | Muffy    |   NULL | NULL                |+----+----------+--------+---------------------+

右连接

 右链接返回右表中的所有记录,即是左表中没有任何满足匹配条件的记录。这意味着,如果 ON 子句在左表中匹配到了 0 条记录,该连接仍然会返回至少一条记录,不过返回的记录中所有来自左表的字段都为 NULL。

 这就意味着,右连接会返回右表中的所有记录,加上左表中匹配到的记录,或者是 NULL (如果连接谓词无法匹配到任何记录的话)。

语法:

 右连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1RIGHT JOIN table2ON table1.common_field = table2.common_field;

 这里,给出的条件可以是任何根据你的需要写出的条件。

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在,让我们用右连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     RIGHT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+------+----------+--------+---------------------+| ID   | NAME     | AMOUNT | DATE                |+------+----------+--------+---------------------+|    3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||    3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||    2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |+------+----------+--------+---------------------+

全连接

 全连接将左连接和右连接的结果组合在一起。

语法:

 全连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM table1FULL JOIN table2ON table1.common_field = table2.common_field;

 这里,给出的条件可以是任何根据你的需要写出的条件。

示例:

 考虑如下两个表格,(a)CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 (b)ORDERS 表:

+-----+---------------------+-------------+--------+| OID | DATE                |          ID | AMOUNT |+-----+---------------------+-------------+--------+| 102 | 2009-10-08 00:00:00 |           3 |   3000 || 100 | 2009-10-08 00:00:00 |           3 |   1500 || 101 | 2009-11-20 00:00:00 |           2 |   1560 || 103 | 2008-05-20 00:00:00 |           4 |   2060 |+-----+---------------------+-------------+--------+

 现在让我们用全连接将两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     FULL JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 上述语句将会产生如下结果:

+------+----------+--------+---------------------+| ID   | NAME     | AMOUNT | DATE                |+------+----------+--------+---------------------+|    1 | Ramesh   |   NULL | NULL                ||    2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||    3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||    3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||    4 | Chaitali |   2060 | 2008-05-20 00:00:00 ||    5 | Hardik   |   NULL | NULL                ||    6 | Komal    |   NULL | NULL                ||    7 | Muffy    |   NULL | NULL                ||    3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||    3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||    2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |+------+----------+--------+---------------------+

 如果你所用的数据库不支持全连接,比如 MySQL,那么你可以使用 UNION ALL子句来将左连接和右连接结果组合在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     LEFT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_IDUNION ALL     SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     RIGHT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID

笛卡尔连接(交叉连接)

 笛卡尔连接或者交叉连接返回两个或者更多的连接表中记录的笛卡尔乘积。也就是说,它相当于连接谓词总是为真或者缺少连接谓词的内连接。

语法:

 笛卡尔连接或者说交叉连接的基本语法如下所示:

SELECT table1.column1, table2.column2...FROM  table1, table2 [, table3 ]

示例:

考虑如下两个表格,(a)CUSTOMERS 表:    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+(b)ORDERS 表:    +-----+---------------------+-------------+--------+    | OID | DATE                |          ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我用内连接将这两个表连接在一起:

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS, ORDERS;

 上述语句将会产生如下结果:

+----+----------+--------+---------------------+| ID | NAME     | AMOUNT | DATE                |+----+----------+--------+---------------------+|  1 | Ramesh   |   3000 | 2009-10-08 00:00:00 ||  1 | Ramesh   |   1500 | 2009-10-08 00:00:00 ||  1 | Ramesh   |   1560 | 2009-11-20 00:00:00 ||  1 | Ramesh   |   2060 | 2008-05-20 00:00:00 ||  2 | Khilan   |   3000 | 2009-10-08 00:00:00 ||  2 | Khilan   |   1500 | 2009-10-08 00:00:00 ||  2 | Khilan   |   1560 | 2009-11-20 00:00:00 ||  2 | Khilan   |   2060 | 2008-05-20 00:00:00 ||  3 | kaushik  |   3000 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1500 | 2009-10-08 00:00:00 ||  3 | kaushik  |   1560 | 2009-11-20 00:00:00 ||  3 | kaushik  |   2060 | 2008-05-20 00:00:00 ||  4 | Chaitali |   3000 | 2009-10-08 00:00:00 ||  4 | Chaitali |   1500 | 2009-10-08 00:00:00 ||  4 | Chaitali |   1560 | 2009-11-20 00:00:00 ||  4 | Chaitali |   2060 | 2008-05-

SQL UNION 子句


 SQL UNION 子句/运算符用于将两个或者更多的 SELECT 语句的运算结果组合起来。

 在使用 UNION 的时候,每个 SELECT 语句必须有相同数量的选中列、相同数量的列表达式、相同的数据类型,并且它们出现的次序要一致,不过长度不一定要相同。

语法

 UNION 子句的基本语法如下所示:

    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]    UNION    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]

 这里的条件可以是任何根据你的需要而设的条件。


示例


 考虑如下两张表,(a)CUSTOMERS 表:

    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+

 (b)另一张表是 ORDERS 表,如下所示:

    +-----+---------------------+-------------+--------+    |OID  | DATE                | CUSTOMER_ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我们用 SELECT 语句将这两张表连接起来:

    SQL> SELECT  ID, NAME, AMOUNT, DATE         FROM CUSTOMERS         LEFT JOIN ORDERS         ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID    UNION         SELECT  ID, NAME, AMOUNT, DATE         FROM CUSTOMERS         RIGHT JOIN ORDERS         ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 结果如下所示:

    +------+----------+--------+---------------------+    | ID   | NAME     | AMOUNT | DATE                |    +------+----------+--------+---------------------+    |    1 | Ramesh   |   NULL | NULL                |    |    2 | Khilan   |   1560 | 2009-11-20 00:00:00 |    |    3 | kaushik  |   3000 | 2009-10-08 00:00:00 |    |    3 | kaushik  |   1500 | 2009-10-08 00:00:00 |    |    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |    |    5 | Hardik   |   NULL | NULL                |    |    6 | Komal    |   NULL | NULL                |    |    7 | Muffy    |   NULL | NULL                |    +------+----------+--------+---------------------+

UNION ALL 子句:


 UNION ALL 运算符用于将两个 SELECT 语句的结果组合在一起,重复行也包含在内。

 UNION ALL 运算符所遵从的规则与 UNION 一致。

语法:

 UNION ALL的基本语法如下:

    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]    UNION ALL    SELECT column1 [, column2 ]    FROM table1 [, table2 ]    [WHERE condition]

示例:

 考虑如下两张表,(a)CUSTOMERS 表:

    +----+----------+-----+-----------+----------+    | ID | NAME     | AGE | ADDRESS   | SALARY   |    +----+----------+-----+-----------+----------+    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |    |  2 | Khilan   |  25 | Delhi     |  1500.00 |    |  3 | kaushik  |  23 | Kota      |  2000.00 |    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |    |  6 | Komal    |  22 | MP        |  4500.00 |    |  7 | Muffy    |  24 | Indore    | 10000.00 |    +----+----------+-----+-----------+----------+

 (b)另一张表是 ORDERS 表,如下所示:

    +-----+---------------------+-------------+--------+    |OID  | DATE                | CUSTOMER_ID | AMOUNT |    +-----+---------------------+-------------+--------+    | 102 | 2009-10-08 00:00:00 |           3 |   3000 |    | 100 | 2009-10-08 00:00:00 |           3 |   1500 |    | 101 | 2009-11-20 00:00:00 |           2 |   1560 |    | 103 | 2008-05-20 00:00:00 |           4 |   2060 |    +-----+---------------------+-------------+--------+

 现在,让我们用 SELECT 语句将这两张表连接起来

SQL> SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     LEFT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_IDUNION ALL     SELECT  ID, NAME, AMOUNT, DATE     FROM CUSTOMERS     RIGHT JOIN ORDERS     ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

 结果如下所示:

    +------+----------+--------+---------------------+    | ID   | NAME     | AMOUNT | DATE                |    +------+----------+--------+---------------------+    |    1 | Ramesh   |   NULL | NULL                |    |    2 | Khilan   |   1560 | 2009-11-20 00:00:00 |    |    3 | kaushik  |   3000 | 2009-10-08 00:00:00 |    |    3 | kaushik  |   1500 | 2009-10-08 00:00:00 |    |    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |    |    5 | Hardik   |   NULL | NULL                |    |    6 | Komal    |   NULL | NULL                |    |    7 | Muffy    |   NULL | NULL                |    |    3 | kaushik  |   3000 | 2009-10-08 00:00:00 |    |    3 | kaushik  |   1500 | 2009-10-08 00:00:00 |    |    2 | Khilan   |   1560 | 2009-11-20 00:00:00 |    |    4 | Chaitali |   2060 | 2008-05-20 00:00:00 |    +------+----------+--------+---------------------+

 另外,还有两个子句(亦即运算法)与 UNION 子句非常相像:

  • SQL INTERSECT 子句:用于组合两个 SELECT 语句,但是只返回两个 SELECT 语句的结果中都有的行。
  • SQL EXCEPT 子句:组合两个 SELECT 语句,并将第一个 SELECT 语句的结果中存在,但是第二个 SELECT 语句的结果中不存在的行返回。

SQL 克隆数据表


 有些情况下,你可能需要原样拷贝某张数据表。但是,CREATE TABLE 却不能满足你的需要,因为复制表必须和原表拥有一样的索引、默认值等等。

 如果你在使用 MySQL 关系型数据库管理系统的话,下面几个步骤可以帮你解决这个问题:

  • 使用 SHOW CREATE TABLE 命令来获取一条指定了原表的结构、索引等信息的 CREATE TABLE 语句。
  • 将语句中的表名修改为克隆表的名字,然后执行该语句。这样你就可以得到一张与原表完全相同的克隆表了。
  • 如果你还想要复制表中的数据的话,请执行 INSERT INTO ... SELECT 语句。

示例:


 请尝试下面的示例,为 TUTORIALS_TBL 创建一张克隆表,其结构如下所示:

步骤一:

 获取数据表的完整结构:

SQL> SHOW CREATE TABLE TUTORIALS_TBL G;*************************** 1. row ***************************       Table: TUTORIALS_TBLCreate Table: CREATE TABLE `TUTORIALS_TBL` (  `tutorial_id` int(11) NOT NULL auto_increment,  `tutorial_title` varchar(100) NOT NULL default '',  `tutorial_author` varchar(40) NOT NULL default '',  `submission_date` date default NULL,  PRIMARY KEY  (`tutorial_id`),  UNIQUE KEY `AUTHOR_INDEX` (`tutorial_author`)) TYPE=MyISAM1 row in set (0.00 sec)

步骤二:

 改变表名,创建新表:

SQL> CREATE TABLE `CLONE_TBL` (  -> `tutorial_id` int(11) NOT NULL auto_increment,  -> `tutorial_title` varchar(100) NOT NULL default '',  -> `tutorial_author` varchar(40) NOT NULL default '',  -> `submission_date` date default NULL,  -> PRIMARY KEY  (`tutorial_id`),  -> UNIQUE KEY `AUTHOR_INDEX` (`tutorial_author`)  -> ) TYPE=MyISAM;Query OK, 0 rows affected (1.80 sec)

步骤三:

 执行完步骤二之后,数据库就会有克隆表了。如果你还想要复制旧表中的数据的话,可以执行 INSERT INTO... SELECT 语句。

SQL> INSERT INTO CLONE_TBL (tutorial_id,    ->                        tutorial_title,    ->                        tutorial_author,    ->                        submission_date)    -> SELECT tutorial_id,tutorial_title,    ->        tutorial_author,submission_date,    -> FROM TUTORIALS_TBL;Query OK, 3 rows affected (0.07 sec)Records: 3  Duplicates: 0  Warnings: 0

 最终,你将如期拥有一张完全相同的克隆表。

SQL 索引


 索引是一种特殊的查询表,可以被数据库搜索引擎用来加速数据的检索。简单说来,索引就是指向表中数据的指针。数据库的索引同书籍后面的索引非常相像。

 例如,如果想要查阅一本书中与某个特定主题相关的所有页面,你会先去查询索引(索引按照字母表顺序列出了所有主题),然后从索引中找到一页或者多页与该主题相关的页面。

 索引能够提高 SELECT 查询和 WHERE 子句的速度,但是却降低了包含 UPDATE 语句或 INSERT 语句的数据输入过程的速度。索引的创建与删除不会对表中的数据产生影响。

 创建索引需要使用 CREATE INDEX 语句,该语句允许对索引命名,指定要创建索引的表以及对哪些列进行索引,还可以指定索引按照升序或者降序排列。

 同 UNIQUE 约束一样,索引可以是唯一的。这种情况下,索引会阻止列中(或者列的组合,其中某些列有索引)出现重复的条目。


CREATE INDEX 命令:


 CREATE INDEX命令的基本语法如下:

CREATE INDEX index_name ON table_name;

单列索引:

 单列索引基于单一的字段创建,其基本语法如下所示:

CREATE INDEX index_nameON table_name (column_name);

唯一索引:

 唯一索引不止用于提升查询性能,还用于保证数据完整性。唯一索引不允许向表中插入任何重复值。其基本语法如下所示:

CREATE UNIQUE INDEX index_nameon table_name (column_name);

聚簇索引:

 聚簇索引在表中两个或更多的列的基础上建立。其基本语法如下所示:

CREATE INDEX index_nameon table_name (column1, column2);

 创建单列索引还是聚簇索引,要看每次查询中,哪些列在作为过滤条件的 WHERE 子句中最常出现。

 如果只需要一列,那么就应当创建单列索引。如果作为过滤条件的 WHERE 子句用到了两个或者更多的列,那么聚簇索引就是最好的选择。

隐式索引:

 隐式索引由数据库服务器在创建某些对象的时候自动生成。例如,对于主键约束和唯一约束,数据库服务器就会自动创建索引。

DROP INDEX 命令:

 索引可以用 SQL DROP 命令删除。删除索引时应当特别小心,数据库的性能可能会因此而降低或者提高。

 其基本语法如下:

DROP INDEX table_name.index_name;

什么时候应当避免使用索引?


 尽管创建索引的目的是提升数据库的性能,但是还是有一些情况应当避免使用索引。下面几条指导原则给出了何时应当重新考虑是否使用索引:

  • 小的数据表不应当使用索引;
  • 需要频繁进行大批量的更新或者插入操作的表;
  • 如果列中包含大数或者 NULL 值,不宜创建索引;
  • 频繁操作的列不宜创建索引。

SQL 子查询


 子查询(Sub Query)或者说内查询(Inner Query),也可以称作嵌套查询(Nested Query),是一种嵌套在其他 SQL 查询的 WHERE 子句中的查询。

 子查询用于为主查询返回其所需数据,或者对检索数据进行进一步的限制。

 子查询可以在 SELECT、INSERT、UPDATE 和 DELETE 语句中,同 =、<、>、>=、<=、IN、BETWEEN 等运算符一起使用。

 使用子查询必须遵循以下几个规则:

  • 子查询必须括在圆括号中。
  • 子查询的 SELECT 子句中只能有一个列,除非主查询中有多个列,用于与子查询选中的列相比较。
  • 子查询不能使用 ORDER BY,不过主查询可以。在子查询中,GROUP BY 可以起到同 ORDER BY 相同的作用。
  • 返回多行数据的子查询只能同多值操作符一起使用,比如 IN 操作符。
  • SELECT 列表中不能包含任何对 BLOB、ARRAY、CLOB 或者 NCLOB 类型值的引用。
  • 子查询不能直接用在聚合函数中。
  • BETWEEN 操作符不能同子查询一起使用,但是 BETWEEN 操作符可以用在子查询中。

SELECT 语句中的子查询


 通常情况下子查询都与 SELECT 语句一起使用,其基本语法如下所示:

SELECT column_name [, column_name ]FROM   table1 [, table2 ]WHERE  column_name OPERATOR      (SELECT column_name [, column_name ]      FROM table1 [, table2 ]      [WHERE])

示例:


 考虑 CUSTOMERS 表,表中记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 现在,让我们试一下在 SELECT 语句中进行子查询:

SQL> SELECT *      FROM CUSTOMERS      WHERE ID IN (SELECT ID                   FROM CUSTOMERS                   WHERE SALARY > 4500) ;

 上述语句的执行结果如下所示:

+----+----------+-----+---------+----------+| ID | NAME     | AGE | ADDRESS | SALARY   |+----+----------+-----+---------+----------+|  4 | Chaitali |  25 | Mumbai  |  6500.00 ||  5 | Hardik   |  27 | Bhopal  |  8500.00 ||  7 | Muffy    |  24 | Indore  | 10000.00 |+----+----------+-----+---------+----------+

INSERT 语句中的子查询:


 子查询还可以用在 INSERT 语句中。INSERT 语句可以将子查询返回的数据插入到其他表中。子查询中选取的数据可以被任何字符、日期或者数值函数所修饰。

 其基本语法如下所示:

INSERT INTO table_name [ (column1 [, column2 ]) ]           SELECT [ *|column1 [, column2 ]           FROM table1 [, table2 ]           [ WHERE VALUE OPERATOR ]

示例:


 考虑与 CUSTOMERS 表拥有相似结构的 CUSTOMERS_BKP 表。现在要将 CUSTOMER 表中所有的数据复制到 CUSTOMERS_BKP 表中,代码如下:

SQL> INSERT INTO CUSTOMERS_BKP     SELECT * FROM CUSTOMERS      WHERE ID IN (SELECT ID                   FROM CUSTOMERS) ;

UPDATE 语句中的子查询:


 子查询可以用在 UPDATE 语句中。当子查询同 UPDATE 一起使用的时候,既可以更新单个列,也可更新多个列。

 其基本语法如下:

UPDATE tableSET column_name = new_value[ WHERE OPERATOR [ VALUE ]   (SELECT COLUMN_NAME   FROM TABLE_NAME)   [ WHERE) ]

示例:


 假设我们有一份 CUSTOMERS_BKP 表作为 CUSTOMERS 表的备份。

 下面的示例将 CUSTOMERS 表中所有 AGE 大于或者等于 27 的客户的 SALARY 字段都变为了原来的 0.25 倍:

SQL> UPDATE CUSTOMERS     SET SALARY = SALARY * 0.25     WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP                   WHERE AGE >= 27 );

 这将影响两行数据,随后 CUSTOMERS 表中的记录将如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |   125.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  2125.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

DELETE 语句中的子查询:


 如同前面提到的其他语句一样,子查询还可以同 DELETE 语句一起使用。

 其基本语法如下所示:

DELETE FROM TABLE_NAME[ WHERE OPERATOR [ VALUE ]   (SELECT COLUMN_NAME   FROM TABLE_NAME)   [ WHERE) ]

示例:


 假设我们有一份 CUSTOMERS_BKP 表作为 CUSTOMERS 表的备份。

 下面的示例将从 CUSTOMERS 表中删除所有 AGE 大于或者等于 27 的记录:

SQL> DELETE FROM CUSTOMERS     WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP                   WHERE AGE > 27 );

 这将影响两行数据,随后 CUSTOMERS 表中的记录将如下所示:

+----+----------+-----+---------+----------+| ID | NAME     | AGE | ADDRESS | SALARY   |+----+----------+-----+---------+----------+|  2 | Khilan   |  25 | Delhi   |  1500.00 ||  3 | kaushik  |  23 | Kota    |  2000.00 ||  4 | Chaitali |  25 | Mumbai  |  6500.00 ||  6 | Komal    |  22 | MP      |  4500.00 ||  7 | Muffy    |  24 | Indore  | 10000.00 |+----+----------+-----+---------+----------+


章节小测


 现在,通过以下题目测测看您对“SQL 子查询”的掌握程度吧!

 SQL 子查询:在本部分测验中,您将练习使用 SQL 子查询。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL ALTER TABLE 命令


 SQL ALTER TABLE 命令用于添加、删除或者更改现有数据表中的列。

 你还可以用 ALTER TABLE 命令来添加或者删除现有数据表上的约束。


语法:


 使用 ALTER TABLE 在现有的数据表中添加新列的基本语法如下:

ALTER TABLE table_name ADD column_name datatype;

 使用 ALTER TABLE 在现有的数据表中删除列的基本语法如下:

ALTER TABLE table_name DROP COLUMN column_name;

 使用 ALTER TABLE 更改现有的数据表中列的数据类型的基本语法如下:

ALTER TABLE table_name MODIFY COLUMN column_name datatype;

 使用 ALTER TABLE 给某列添加 NOT NULL 约束 的基本语法如下:

ALTER TABLE table_name MODIFY column_name datatype NOT NULL;

 使用 ALTER TABLE 给数据表添加 唯一约束 的基本语法如下:

ALTER TABLE table_name ADD CONSTRAINT MyUniqueConstraint UNIQUE(column1, column2...);

 使用 ALTER TABLE 给数据表添加 CHECK 约束 的基本语法如下:

ALTER TABLE table_name ADD CONSTRAINT MyUniqueConstraint CHECK (CONDITION);

 使用 ALTER TABLE 给数据表添加 主键约束 的基本语法如下:

ALTER TABLE table_name ADD CONSTRAINT MyPrimaryKey PRIMARY KEY (column1, column2...);

 使用 ALTER TABLE 从数据表中 删除约束 的基本语法如下:

ALTER TABLE table_name DROP CONSTRAINT MyUniqueConstraint;

 如果你在使用 MySQL,代码应当如下:

ALTER TABLE table_name DROP INDEX MyUniqueConstraint;

 使用 ALTER TABLE 从数据表中 删除主键约束 的基本语法如下:

ALTER TABLE table_name DROP CONSTRAINT MyPrimaryKey;

 如果你在使用 MySQL,代码应当如下:

ALTER TABLE table_name DROP PRIMARY KEY;

示例:


 考虑 CUSTOMERS 表,表中记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例展示了如何在现有的表中添加新的一列:

ALTER TABLE CUSTOMERS ADD SEX char(1);

 现在,CUSTOMERS 已经被更改了,SELECT 语句的输出应当如下所示:

+----+---------+-----+-----------+----------+------+| ID | NAME    | AGE | ADDRESS   | SALARY   | SEX  |+----+---------+-----+-----------+----------+------+|  1 | Ramesh  |  32 | Ahmedabad |  2000.00 | NULL ||  2 | Ramesh  |  25 | Delhi     |  1500.00 | NULL ||  3 | kaushik |  23 | Kota      |  2000.00 | NULL ||  4 | kaushik |  25 | Mumbai    |  6500.00 | NULL ||  5 | Hardik  |  27 | Bhopal    |  8500.00 | NULL ||  6 | Komal   |  22 | MP        |  4500.00 | NULL ||  7 | Muffy   |  24 | Indore    | 10000.00 | NULL |+----+---------+-----+-----------+----------+------+

 下面的示例展示了如何从 CUSTOMERS 表中删除 SEX 列:

ALTER TABLE CUSTOMERS DROP COLUMN SEX;

 现在,CUSTOMERS 已经被更改了,SELECT 语句的输出应当如下所示:

+----+---------+-----+-----------+----------+| ID | NAME    | AGE | ADDRESS   | SALARY   |+----+---------+-----+-----------+----------+|  1 | Ramesh  |  32 | Ahmedabad |  2000.00 ||  2 | Ramesh  |  25 | Delhi     |  1500.00 ||  3 | kaushik |  23 | Kota      |  2000.00 ||  4 | kaushik |  25 | Mumbai    |  6500.00 ||  5 | Hardik  |  27 | Bhopal    |  8500.00 ||  6 | Komal   |  22 | MP        |  4500.00 ||  7 | Muffy   |  24 | Indore    | 10000.00 |+----+---------+-----+-----------+----------+

SQL TRUNCATE TABLE 命令


 SQL TRUNCATE TABLE 命令用于删除现有数据表中的所有数据。

 你也可以使用 DROP TABLE 命令来删除整个数据表,不过 DROP TABLE 命令不但会删除表中所有数据,还会将整个表结构从数据库中移除。如果想要重新向表中存储数据的话,必须重建该数据表。


语法:


 TRUNCATE TABLE 的基本语法如下所示:

TRUNCATE TABLE  table_name;

示例:


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例展示了 TRUNCATE 命令的用法:

TRUNCATE TABLE CUSTOMERS;

 现在,CUSTOMERS 表已经被清空了,SELECT 语句的输出应当如下所示:

SQL> SELECT * FROM CUSTOMERS;Empty set (0.00 sec)

SQL 处理重复数据


 有时候,数据表中会存在相同的记录。在获取表中记录时,相较于取得重复记录来说,取得唯一的记录显然更有意义。

 我们之前讨论过的 SQL DISTINCT 关键字,与 SELECT 语句一起使用可以时,可以达到消除所有重复记录,只返回唯一记录的目的。


语法:


 利用 DISTINCT 关键字来消除重复记录的基本语法如下所示:

SELECT DISTINCT column1, column2,.....columnN FROM table_nameWHERE [condition]

示例:


 考虑 CUSTOMERS 表,表中记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 首先,让我们先看一下 SELECT 语句是如何返回重复的薪水记录的:

SQL> SELECT SALARY FROM CUSTOMERS     ORDER BY SALARY;

 运行上述语句将会得到以下结果,其中 SALARY 为 2000 的记录出现了两次,即来自原始数据表的重复记录:

+----------+| SALARY   |+----------+|  1500.00 ||  2000.00 ||  2000.00 ||  4500.00 ||  6500.00 ||  8500.00 || 10000.00 |+----------+

 现在,让我们在上面的 SELECT 查询中使用 DISTINCT 关键字,然后观察将会得到什么结果:

SQL> SELECT DISTINCT SALARY FROM CUSTOMERS     ORDER BY SALARY;

 上述语句将会产生如下结果,这一再没有任何重复的条目了:

+----------+| SALARY   |+----------+|  1500.00 ||  2000.00 ||  4500.00 ||  6500.00 ||  8500.00 || 10000.00 |+----------+

SQL 使用视图


 视图无非就是存储在数据库中并具有名字的 SQL 语句,或者说是以预定义的 SQL 查询的形式存在的数据表的成分。

 视图可以包含表中的所有列,或者仅包含选定的列。视图可以创建自一个或者多个表,这取决于创建该视图的 SQL 语句的写法。

 视图,一种虚拟的表,允许用户执行以下操作:

  • 以用户或者某些类型的用户感觉自然或者直观的方式来组织数据;
  • 限制对数据的访问,从而使得用户仅能够看到或者修改(某些情况下)他们需要的数据;
  • 从多个表中汇总数据,以产生报表。

创建视图


 在 SQL 中,视图是基于 SQL 语句的结果集的可视化表。

 数据库视图由 CREATE VIEW 语句创建。视图可以创建自单个表、多个表或者其他视图。

 视图中的字段是一个或多个数据库中真实表中的字段。

 在使用时视图可以被视为一个“虚拟表”。    

 要创建视图的话,用户必须有适当的系统权限。具体需要何种权限随数据库系统实现的不同而不同。

 CREATE VIEW 语句的基本语法如下所示:

CREATE VIEW view_name ASSELECT column1, column2.....FROM table_nameWHERE [condition];

 和普通的 SQL SELECT 查询一样,你可以在上面的 SELECT 语句中包含多个数据表。

注释:视图总是显示最新数据!每当用户查询视图时,数据库引擎就使用视图的 SQL 语句重新构建数据。


SQL CREATE VIEW 示例


示例一

 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面是由 CUSTOMERS 表创建视图的例子。该视图包含来自 CUSTOMERS 表的顾客的名字(name)和年龄(age):

SQL > CREATE VIEW CUSTOMERS_VIEW ASSELECT name, ageFROM  CUSTOMERS;

 现在,你就可以像查询普通的数据表一样查询 CUSTOMERS_VIEW 了:

SQL > SELECT * FROM CUSTOMERS_VIEW;

 上述语句将会产生如下运行结果:

+----------+-----+| name     | age |+----------+-----+| Ramesh   |  32 || Khilan   |  25 || kaushik  |  23 || Chaitali |  25 || Hardik   |  27 || Komal    |  22 || Muffy    |  24 |+----------+-----+

示例2

 下面是由 CUSTOMERS 表创建视图的例子。该视图包含来自 CUSTOMERS 表中年龄(age)为25的顾客的ADDRESS信息:

SQL > CREATE VIEW CUSTOMERS_ADDRESS ASSELECT ADDRESSFROM  CUSTOMERS;WHERE AGE=25;

 我们可以像这样查询上面这个 CUSTOMERS_ADDRESS 视图:

SQL > SELECT * FROM CUSTOMERS_ADDRESS;

 我们也可以向查询添加条件。现在,我们仅仅需要查看 "Delhi" 的数据:

SELECT * FROM CUSTOMERS_ADDRESSWHERE ADDRESS='Delhi';


WITH CHECK OPTION


 WITH CHECK OPTION 是 CREATE VIEW 语句的一个可选项。

 WITH CHECK OPTION 用于保证所有的 UPDATE 和 INSERT 语句都满足视图定义中的条件。

 如果不能满足这些条件,UPDATE 或 INSERT 就会返回错误。

 下面的例子创建的也是 CUSTOMERS_VIEW 视图,不过这次 WITH CHECK OPTION 是打开的:

CREATE VIEW CUSTOMERS_VIEW ASSELECT name, ageFROM  CUSTOMERSWHERE age IS NOT NULLWITH CHECK OPTION;

 这里 WITH CHECK OPTION 使得视图拒绝任何 AGE 字段为 NULL 的条目,因为视图的定义中,AGE 字段不能为空。


更新视图


 在SQL视图上也可以使用修改数据的DML语句,如 INSERT、UPDATE和DELETE。

 视图可以在特定的情况下更新:

  • SELECT 子句不能包含 DISTINCT 关键字
  • SELECT 子句不能包含任何汇总函数(summary functions)
  • SELECT 子句不能包含任何集合函数(set functions)
  • SELECT 子句不能包含任何集合运算符(set operators)
  • SELECT 子句不能包含 ORDER BY 子句
  • 视图不能包含连接操作符
  • 视图不能包含伪列或表达式
  • FROM 子句中不能有多个数据表
  • WHERE 子句不能包含子查询(subquery)
  • 查询语句中不能有 GROUP BY 或者 HAVING
  • 计算得出的列不能更新
  • 视图必须包含原始数据表中所有的 NOT NULL 列,从而使 INSERT 查询生效。

 如果视图满足以上所有的条件,该视图就可以被更新。下面的例子中,Ramesh 的年龄被更新了:

SQL > UPDATE CUSTOMERS_VIEW      SET AGE = 35      WHERE name='Ramesh';

 最终更新的还是原始数据表,只是其结果反应在了视图上。现在查询原始数据表,SELECT 语句将会产生以下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

向视图中插入新行


 可以向视图中插入新行,其规则同(使用 UPDATE 命令)更新视图所遵循的规则相同。

 这里我们不能向 CUSTOMERS_VIEW 视图中添加新行,因为该视图没有包含原始数据表中所有 NOT NULL 的列。否则的话,你就可以像在数据表中插入新行一样,向视图中插入新行。

 句法:

INSERT INTO view_nameVALUES (value1, value2, value3, ...);

删除视图中的行


 视图中的数据行可以被删除。删除数据行与更新视图和向视图中插入新行遵循相同的规则。

 下面的例子将删除 CUSTOMERS_VIEW 视图中 AGE=22 的数据行:

SQL > DELETE FROM CUSTOMERS_VIEW      WHERE age = 22;

 该语句最终会将原始数据表中对应的数据行删除,只不过其结果反应在了视图上。现在查询原始数据表,SELECT 语句将会产生以下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  35 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

删除视图


 很明显,当我们不再需要某个视图的时候,需要有一种方式可以让我们将其删除。删除视图的语法非常简单,如下所示:

DROP VIEW view_name;

 下面的例子展示了如何从 CUSTOMERS 表中删除 CUSTOMERS_VIEW 视图:

DROP VIEW CUSTOMERS_VIEW;


章节小测


 现在,通过以下题目测测看您对“SQL 使用视图”的掌握程度吧!

 SQL 视图:在本部分测验中,您将练习创建以及更新 SQL 视图。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL 注入


 如果你从网页中获取用户输入,并将其插入到 SQL 数据库中的话,那么你很可能已经暴露于一种被称作 SQL 注入的安全风险之下了。

 本节将会教你如何防止 SQL 注入,以及如何保护 Perl 这样的服务器端脚本中的程序和 SQL 语句。

 注入通常发生在获取用户输入的时候,例如预期得到用户的名字,但是得到的却是一段很可能会在你不知情的情况下运行的 SQL 语句。

 绝对不要相信用户提供的数据,处理这些数据之前必须进行验证;通常,验证工作由模式匹配来完成。

 下面的例子中,name 仅限由字母、数字和下划线组成,并且长度在 8 到 20 之间(你可以根据需要修改这些规则)。

if (preg_match("/^w{8,20}$/", $_GET['username'], $matches)){   $result = mysql_query("SELECT * FROM CUSTOMERS                           WHERE name=$matches[0]");}else {   echo "user name not accepted";}

 为了展示问题所在,请考虑下面这段代码:

// supposed input$name = "Qadir'; DELETE FROM CUSTOMERS;";mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");

 下面的函数调用本来是要从 CUSTOMERS 表中取得 name 字段与用户给定的输入相匹配的记录。通常情况下,$name 只包含字母和数字,或许还有空格,例如字符串 ilia。但是,这里通过在 $name 上附加一段全新的查询语句,将原有的函数调用变为了数据库的灾难:注入的 DELETE 语句将会删除表中所有的记录。

 幸运的是,如果你在使用 MySQL 的话,mysql_query() 函数不允许查询堆积(query stacking),或者说在一次函数调用中执行多次 SQL 查询。如果你试图进行堆积式查询的话,函数调用将会失败。

 然而,其他的 PHP 数据库扩展,例如 SQLite 和 PostgreSQL 会愉快地接受堆积式查询,执行字符串中所有的查询,并由此产生严重的安全问题。


阻止 SQL 注入


 你可以在 Perl 或者 PHP 等脚本语言中巧妙地处理所有的转义字符。PHP 的 MySQL 扩展提供了一个 mysql_real_escape_string() 函数,来转义那些对 MySQL 有特殊意义的字符。

if (get_magic_quotes_gpc()) {  $name = stripslashes($name);}$name = mysql_real_escape_string($name);mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");

LIKE 困境


 要破解 LIKE 困境,必须有一种专门的转义机制,将用户提供的 '%' 和 '_' 转换为字面值。为此你可以使用 addcslashes() 函数,该函数允许指定要进行转义的字符的范围。

$sub = addcslashes(mysql_real_escape_string("%str"), "%_");// $sub == \%str\_mysql_query("SELECT * FROM messages              WHERE subject LIKE '{$sub}%'");

SQL HAVING 子句


HAVING​ 子句使你能够指定过滤条件,从而控制查询结果中哪些组可以出现在最终结果里面。

WHERE ​子句对被选择的列施加条件,而 ​HAVING ​子句则对 ​GROUP BY​ 子句所产生的组施加条件。

语法  

下面可以看到 ​HAVING​ 子句在 ​SEL ECT ​查询中的位置:

SELECTFROMWHEREGROUP BYHAVINGORDER BY

在 ​SELECT​ 查询中,​HAVING​ 子句必须紧随 ​GROUP BY​ 子句,并出现在 ​ORDER BY​ 子句(如果有的话)之前。带有 ​HAVING​ 子句的 ​SELECT​ 语句的语法如下所示:

SELECT column1, column2   FROM table1, table2WHERE [ conditions ]GROUP BY column1, column2HAVING [ conditions ]ORDER BY column1, column2

示例


 考虑 ​CUSTOMERS​ 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面是一个有关 ​HAVING​ 子句使用的实例,该实例将会筛选出出现次数大于或等于 2 的所有记录。

SQL > SELECT ID, NAME, AGE, ADDRESS, SALARYFROM CUSTOMERSGROUP BY ageHAVING COUNT(age) >= 2;

 其执行结果如下所示:

+----+----------+-----+---------+---------+| ID | NAME     | AGE | ADDRESS | SALARY  |+----+----------+-----+---------+---------+|  2 | Khilan   |  25 | Delhi   | 1500.00 ||  4 | Chaitali |  25 | Mumbai  | 6500.00 |+----+----------+-----+---------+---------+

SQL HAVING 实例

现在我们想要查找总访问量大于 200 的网站。

我们使用下面的 SQL 语句:

实例

SELECT Websites.name, Websites.url, SUM(access_log.count) AS nums FROM (access_log INNER JOIN Websites ON access_log.site_id=Websites.id) GROUP BY Websites.name HAVING SUM(access_log.count) > 200;

执行以上 SQL 输出结果如下:

现在我们想要查找总访问量大于 200 的网站,并且 alexa 排名小于 200。

我们在 SQL 语句中增加一个普通的 WHERE 子句:

实例

SELECT Websites.name, SUM(access_log.count) AS nums FROM Websites INNER JOIN access_log ON Websites.id=access_log.site_id WHERE Websites.alexa < 200 GROUP BY Websites.name HAVING SUM(access_log.count) > 200;

执行以上 SQL 输出结果如下:



SQL 事务


 事务是在数据库上按照一定的逻辑顺序执行的任务序列,既可以由用户手动执行,也可以由某种数据库程序自动执行。

 事务实际上就是对数据库的一个或者多个更改。当你在某张表上创建更新或者删除记录的时,你就已经在使用事务了。控制事务以保证数据完整性,并对数据库错误做出处理,对数据库来说非常重要。

 实践中,通常会将很多 SQL 查询组合在一起,并将其作为某个事务一部分来执行。


事务的属性


 事务具有以下四个标准属性,通常用缩略词 ACID 来表示:

  • 原子性:保证任务中的所有操作都执行完毕;否则,事务会在出现错误时终止,并回滚之前所有操作到原始状态。
  • 一致性:如果事务成功执行,则数据库的状态得到了进行了正确的转变。
  • 隔离性:保证不同的事务相互独立、透明地执行。
  • 持久性:即使出现系统故障,之前成功执行的事务的结果也会持久存在。

事务控制


 有四个命令用于控制事务:

  • COMMIT:提交更改;
  • ROLLBACK:回滚更改;
  • SAVEPOINT:在事务内部创建一系列可以 ROLLBACK 的还原点;
  • SET TRANSACTION:命名事务;

COMMIT 命令


 COMMIT 命令用于保存事务对数据库所做的更改。

 COMMIT 命令会将自上次 COMMIT 命令或者 ROLLBACK 命令执行以来所有的事务都保存到数据库中。

 COMMIT 命令的语法如下所示:

COMMIT;

示例


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例将会删除表中 age=25 的记录,然后将更改提交(COMMIT)到数据库中。

SQL> DELETE FROM CUSTOMERS     WHERE AGE = 25;SQL> COMMIT;

 上述语句将会从表中删除两行记录,再执行 SELECT 语句将会得到如下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

ROLLBACK 命令


 ROLLBACK 命令用于撤销尚未保存到数据库中的事务。

 ROLLBACK 命令只能撤销自上次 COMMIT 命令或者 ROLLBACK 命令执行以来的事务。

 ROLLBACK 命令的语法如下所示:

ROLLBACK;

示例:


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例将会从表中删除所有 age=25 的记录,然后回滚(ROLLBACK)对数据库所做的更改。

SQL> DELETE FROM CUSTOMERS     WHERE AGE = 25;SQL> ROLLBACK;

 结果是删除操作并不会对数据库产生影响。现在,执行 SELECT 语句将会得到如下结果:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

SAVEPOINT 命令


 SAVEPOINT 是事务中的一个状态点,使得我们可以将事务回滚至特定的点,而不是将整个事务都撤销。

 SAVEPOINT 命令的记录如下所示:

SAVEPOINT SAVEPOINT_NAME;

 该命令只能在事务语句之间创建保存点(SAVEPOINT)。ROLLBACK 命令可以用于撤销一系列的事务。

 回滚至某一保存点的语法如下所示:

ROLLBACK TO SAVEPOINT_NAME;

 下面的示例中,你计划从 CUSTOMERS 表中删除三条不同的记录,并在每次删除之前创建一个保存点(SAVEPOINT),从而使得你可以在任何任何时候回滚到任意的保存点,以恢复数据至其原始状态。


示例


 考虑 CUSTOMERS 表,表中的记录如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 操作序列如下所示:

SQL> SAVEPOINT SP1;Savepoint created.SQL> DELETE FROM CUSTOMERS WHERE ID=1;1 row deleted.SQL> SAVEPOINT SP2;Savepoint created.SQL> DELETE FROM CUSTOMERS WHERE ID=2;1 row deleted.SQL> SAVEPOINT SP3;Savepoint created.SQL> DELETE FROM CUSTOMERS WHERE ID=3;1 row deleted.

 现在,三次删除操作已经生效了,如果此时你改变主意决定回滚至名字为 SP2 的保存点,由于 SP2 于第一次删除操作之后创建,所以后两次删除操作将会被撤销。

SQL> ROLLBACK TO SP2;Rollback complete.

 注意,由于你将数据库回滚至 SP2,所以只有第一次删除真正起效了:

SQL> SELECT * FROM CUSTOMERS;+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+6 rows selected.

RELEASE SAVEPOINT 命令


 RELEASE SAVEPOINT 命令用于删除先前创建的保存点。

 RELEASE SAVEPOINT 的语法如下所示:

RELEASE SAVEPOINT SAVEPOINT_NAME;

 保存点一旦被释放,你就不能够再用 ROLLBACK 命令来撤销该保存点之后的事务了。


SET TRANSACTION 命令


 SET TRANSACTION 命令可以用来初始化数据库事务,指定随后的事务的各种特征。

 例如,你可以将某个事务指定为只读或者读写。

 SET TRANSACTION 命令的语法如下所示:

SET TRANSACTION [ READ WRITE | READ ONLY ];

SQL 使用序列


 序列是根据需要产生的一组有序整数:1, 2, 3 ... 序列在数据库中经常用到,因为许多应用要求数据表中的的每一行都有一个唯一的值,序列为此提供了一种简单的方法。

 本节阐述在 MySQL 中如何使用序列。


使用 AUTO_INCREMENT 列


 在 MySQL 中使用序列最简单的方式是,把某列定义为 AUTO_INCREMENT,然后将剩下的事情交由 MySQL 处理:


示例


 试一下下面的例子,该例将会创建一张新表,然后再里面插入几条记录,添加记录时并不需要指定记录的 ID,因为该列的值由 MySQL 自动增加。

mysql> CREATE TABLE INSECT    -> (    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT,    -> PRIMARY KEY (id),    -> name VARCHAR(30) NOT NULL, # type of insect    -> date DATE NOT NULL, # date collected    -> origin VARCHAR(30) NOT NULL # where collected);Query OK, 0 rows affected (0.02 sec)mysql> INSERT INTO INSECT (id,name,date,origin) VALUES    -> (NULL,'housefly','2001-09-10','kitchen'),    -> (NULL,'millipede','2001-09-10','driveway'),    -> (NULL,'grasshopper','2001-09-10','front yard');Query OK, 3 rows affected (0.02 sec)Records: 3  Duplicates: 0  Warnings: 0mysql> SELECT * FROM INSECT ORDER BY id;+----+-------------+------------+------------+| id | name        | date       | origin     |+----+-------------+------------+------------+|  1 | housefly    | 2001-09-10 | kitchen    ||  2 | millipede   | 2001-09-10 | driveway   ||  3 | grasshopper | 2001-09-10 | front yard |+----+-------------+------------+------------+3 rows in set (0.00 sec)

获取 AUTO_INCREMENT 值


 LAST_INSERT_ID() 是一个 SQL 函数,可以用在任何能够执行 SQL 语句地方。另外,Perl 和 PHP 各自提供了其独有的函数,用于获得最后一条记录的 AUTO_INCREMENT 值。


Perl 示例


 使用 mysql_insertid 属性来获取 SQL 查询产生的 AUTO_INCREMENT 值。根据执行查询的方式不同,该属性可以通过数据库句柄或者语句句柄来访问。下面的示例通过数据库句柄取得自增值:

$dbh->do ("INSERT INTO INSECT (name,date,origin)VALUES('moth','2001-09-14','windowsill')");my $seq = $dbh->{mysql_insertid};

PHP 示例


 在执行完会产生自增值的查询后,可以通过调用 mysql_insert_id() 来获取此值:

mysql_query ("INSERT INTO INSECT (name,date,origin)VALUES('moth','2001-09-14','windowsill')", $conn_id);$seq = mysql_insert_id ($conn_id);

重新编号现有序列


 当你从表中删除了很多记录后,可能会想要对所有的记录重新定序。只要略施小计就能达到此目的,不过如果你的表与其他表之间存在连接的话,请千万小心。

 当你觉得不得不对 AUTO_INCREMENT 列重新定序时,从表中删除该列,然后再将其添加回来,就可以达到目的了。下面的示例展示了如何使用这种方法,为 INSECT 表中的 ID 值重新定序:

mysql> ALTER TABLE INSECT DROP id;mysql> ALTER TABLE insect    -> ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,    -> ADD PRIMARY KEY (id);

从特定值的序列


 默认情况下,MySQL 中序列的起始值为 1,不过你可以在创建数据表的时候,指定任意其他值。下面的示例中,MySQL 将序列的起始值设为 100:

mysql> CREATE TABLE INSECT    -> (    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT = 100,    -> PRIMARY KEY (id),    -> name VARCHAR(30) NOT NULL, # type of insect    -> date DATE NOT NULL, # date collected    -> origin VARCHAR(30) NOT NULL # where collected);

 或者,你也可以先创建数据表,然后使用 ALTER TABLE 来设置序列的起始值:

mysql> ALTER TABLE t AUTO_INCREMENT = 100;

SQL 通配符


 我们已经讨论过 SQL 的 LIKE 操作符了,它可以利用通配符来对两个相似的值作比较。

 SQL 支持以下两个通配符与 LIKE 操作符一起使用:

通配符描述
百分号(%)匹配一个或者多个字符。注意:MS Access 使用星号(*)作为匹配一个或者多个字符的通配符,而不是百分号(%)。
下划线(_)匹配一个字符。注意:MS Access 使用问号(?),而不是下划线,来匹配任一字符。

 百分号代表零个、一个或者多个字符。下划线代表单一的字符。这些符号可以组合在一起使用。


语法


 “%” 和 “_” 的基本语法如下所示:

SELECT FROM table_nameWHERE column LIKE 'XXXX%'or SELECT FROM table_nameWHERE column LIKE '%XXXX%'orSELECT FROM table_nameWHERE column LIKE 'XXXX_'orSELECT FROM table_nameWHERE column LIKE '_XXXX'orSELECT FROM table_nameWHERE column LIKE '_XXXX_'

 你可以用 AND 或 OR 操作符将多个条件合并在一起。这里,XXXX 可以为任何数值或者字符串。


示例


语句描述
WHERE SALARY LIKE '200%'找出任何以 200 开头的值。
WHERE SALARY LIKE '%200%'找出任何存在 200 的值。
WHERE SALARY LIKE '_00%'找出任何第二个位置和第三个位置为 0 的值。
WHERE SALARY LIKE '2_%_%'找出任何以 2 开始,并且长度至少为 3 的值。
WHERE SALARY LIKE '%2'找出任何以 2 结尾的值。
WHERE SALARY LIKE '_2%3'找出任何第二个位置为 2,并且以 3 结束的值。
WHERE SALARY LIKE '2___3'找出任何以 2 开始,以 3 结束的五位数。

 让我们来看一个真实的例子,考虑拥有如下记录的 CUSTOMERS 表:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  2 | Khilan   |  25 | Delhi     |  1500.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 ||  4 | Chaitali |  25 | Mumbai    |  6500.00 ||  5 | Hardik   |  27 | Bhopal    |  8500.00 ||  6 | Komal    |  22 | MP        |  4500.00 ||  7 | Muffy    |  24 | Indore    | 10000.00 |+----+----------+-----+-----------+----------+

 下面的示例将会找到 CUSTOMER 表中所有 SALARY 以 200 开头的记录,并显示出来:

SQL> SELECT * FROM CUSTOMERSWHERE SALARY LIKE '200%'; 

 结果如下所示:

+----+----------+-----+-----------+----------+| ID | NAME     | AGE | ADDRESS   | SALARY   |+----+----------+-----+-----------+----------+|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 ||  3 | kaushik  |  23 | Kota      |  2000.00 |+----+----------+-----+-----------+----------+

SQL 临时表


 某些关系型数据库管理系统支持临时表。临时表是一项很棒的特性,能够让你像操作普通的 SQL 数据表一样,使用 SELECT、UPDATE 和 JOIN 等功能来存储或者操作中间结果。

 临时表有时候对于保存临时数据非常有用。有关临时表你需要知道的最重要的一点是,它们会在当前的终端会话结束后被删除。

 临时表自 MySQL 3.23 起受到支持。如果你的 MySQL 版本比 3.23 还老,那么你就不能使用临时表了,不过你可以使用堆表(heap table)。

 如先前所言,临时表只在会话期间存在。如果你在 PHP 脚本中操作数据库,那么临时表将在脚本执行完毕时被自动销毁。如果你是通过 MySQL 的客户端程序连接到 MySQL 数据库服务器的,那么临时表将会存在到你关闭客户端或者手动将其删除。


示例


 下面的示例向你展示了如何使用临时表:

mysql> CREATE TEMPORARY TABLE SALESSUMMARY (    -> product_name VARCHAR(50) NOT NULL    -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00    -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00    -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0);Query OK, 0 rows affected (0.00 sec)mysql> INSERT INTO SALESSUMMARY    -> (product_name, total_sales, avg_unit_price, total_units_sold)    -> VALUES    -> ('cucumber', 100.25, 90, 2);mysql> SELECT * FROM SALESSUMMARY;+--------------+-------------+----------------+------------------+| product_name | total_sales | avg_unit_price | total_units_sold |+--------------+-------------+----------------+------------------+| cucumber     |      100.25 |          90.00 |                2 |+--------------+-------------+----------------+------------------+1 row in set (0.00 sec)

 当你下达 SHOW TABLES 命令的时候,临时表是不会出现在结果列表当中的。现在,如果你退出 MySQL 会话,然后再执行 SELECT 命令的话,你将不能从数据库中取回任何数据,你的临时表也已经不复存在了。


删除临时表


 默认情况下,所有的临时表都由 MySQL 在数据库连接关闭时删除。不过,有时候你还是会想要在会话期间将其删除,此时你需要使用 DROP TABLE 命令来达到目的。

 下面是删除临时表的示例:

mysql> CREATE TEMPORARY TABLE SALESSUMMARY (    -> product_name VARCHAR(50) NOT NULL    -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00    -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00    -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0);Query OK, 0 rows affected (0.00 sec)mysql> INSERT INTO SALESSUMMARY    -> (product_name, total_sales, avg_unit_price, total_units_sold)    -> VALUES    -> ('cucumber', 100.25, 90, 2);mysql> SELECT * FROM SALESSUMMARY;+--------------+-------------+----------------+------------------+| product_name | total_sales | avg_unit_price | total_units_sold |+--------------+-------------+----------------+------------------+| cucumber     |      100.25 |          90.00 |                2 |+--------------+-------------+----------------+------------------+1 row in set (0.00 sec)mysql> DROP TABLE SALESSUMMARY;mysql>  SELECT * FROM SALESSUMMARY;ERROR 1146: Table 'TUTORIALS.SALESSUMMARY' doesn't exist

SQL 用于各种数据库的数据类型


 Microsoft Access、MySQL 和 SQL Server 所使用的数据类型和范围。


Microsoft Access 数据类型


数据类型描述存储
Text用于文本或文本与数字的组合。最多 255 个字符。
MemoMemo 用于更大数量的文本。最多存储 65,536 个字符。注释:无法对 memo 字段进行排序。不过它们是可搜索的。
Byte允许 0 到 255 的数字。1 字节
Integer允许介于 -32,768 与 32,767 之间的全部数字。2 字节
Long允许介于 -2,147,483,648 与 2,147,483,647 之间的全部数字。4 字节
Single单精度浮点。处理大多数小数。4 字节
Double双精度浮点。处理大多数小数。8 字节
Currency用于货币。支持 15 位的元,外加 4 位小数。提示:您可以选择使用哪个国家的货币。8 字节
AutoNumberAutoNumber 字段自动为每条记录分配数字,通常从 1 开始。4 字节
Date/Time用于日期和时间8 字节
Yes/No逻辑字段,可以显示为 Yes/No、True/False 或 On/Off。在代码中,使用常量 True 和 False (等价于 1 和 0)。注释:Yes/No 字段中不允许 Null 值1 比特
Ole Object可以存储图片、音频、视频或其他 BLOBs(Binary Large OBjects)。最多 1GB
Hyperlink包含指向其他文件的链接,包括网页。
Lookup Wizard允许您创建一个可从下拉列表中进行选择的选项列表。4 字节

MySQL 数据类型


 在 MySQL 中,有三种主要的类型:Text(文本)、Number(数字)和 Date/Time(日期/时间)类型。

 Text 类型:

数据类型描述
CHAR(size)保存固定长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的长度。最多 255 个字符。
VARCHAR(size)保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。注释:如果值的长度大于 255,则被转换为 TEXT 类型。
TINYTEXT存放最大长度为 255 个字符的字符串。
TEXT存放最大长度为 65,535 个字符的字符串。
BLOB用于 BLOBs(Binary Large OBjects)。存放最多 65,535 字节的数据。
MEDIUMTEXT存放最大长度为 16,777,215 个字符的字符串。
MEDIUMBLOB用于 BLOBs(Binary Large OBjects)。存放最多 16,777,215 字节的数据。
LONGTEXT存放最大长度为 4,294,967,295 个字符的字符串。
LONGBLOB用于 BLOBs (Binary Large OBjects)。存放最多 4,294,967,295 字节的数据。
ENUM(x,y,z,etc.)允许您输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。

注释:这些值是按照您输入的顺序排序的。

可以按照此格式输入可能的值: ENUM('X','Y','Z')

SET与 ENUM 类似,不同的是,SET 最多只能包含 64 个列表项且 SET 可存储一个以上的选择。

 

 Number 类型:

数据类型描述
TINYINT(size)-128 到 127 常规。0 到 255 无符号*。在括号中规定最大位数。
SMALLINT(size)-32768 到 32767 常规。0 到 65535 无符号*。在括号中规定最大位数。
MEDIUMINT(size)-8388608 到 8388607 普通。0 to 16777215 无符号*。在括号中规定最大位数。
INT(size)-2147483648 到 2147483647 常规。0 到 4294967295 无符号*。在括号中规定最大位数。
BIGINT(size)-9223372036854775808 到 9223372036854775807 常规。0 到 18446744073709551615 无符号*。在括号中规定最大位数。
FLOAT(size,d)带有浮动小数点的小数字。在 size 参数中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
DOUBLE(size,d)带有浮动小数点的大数字。在 size 参数中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
DECIMAL(size,d)作为字符串存储的 DOUBLE 类型,允许固定的小数点。在 size 参数中规定最大位数。在 d 参数中规定小数点右侧的最大位数。

注意:这些整数类型拥有额外的选项 UNSIGNED。通常,整数可以是负数或正数。如果添加 UNSIGNED 属性,那么范围将从 0 开始,而不是某个负数。


 Date 类型:

数据类型描述
DATE()日期。格式:YYYY-MM-DD

注释:支持的范围是从 '1000-01-01' 到 '9999-12-31'

DATETIME()*日期和时间的组合。格式:YYYY-MM-DD HH:MM:SS

注释:支持的范围是从 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'

TIMESTAMP()*时间戳。TIMESTAMP 值使用 Unix 纪元('1970-01-01 00:00:00' UTC) 至今的秒数来存储。格式:YYYY-MM-DD HH:MM:SS

注释:支持的范围是从 '1970-01-01 00:00:01' UTC 到 '2038-01-09 03:14:07' UTC

TIME()时间。格式:HH:MM:SS

注释:支持的范围是从 '-838:59:59' 到 '838:59:59'

YEAR()2 位或 4 位格式的年。

注释:4 位格式所允许的值:1901 到 2155。2 位格式所允许的值:70 到 69,表示从 1970 到 2069。

注意:即便 DATETIME 和 TIMESTAMP 返回相同的格式,它们的工作方式很不同。在 INSERT 或 UPDATE 查询中,TIMESTAMP 自动把自身设置为当前的日期和时间。TIMESTAMP 也接受不同的格式,比如 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD。


SQL Server 数据类型


 String 类型:

数据类型描述存储
char(n)固定长度的字符串。最多 8,000 个字符。Defined width
varchar(n)可变长度的字符串。最多 8,000 个字符。2 bytes + number of chars
varchar(max)可变长度的字符串。最多 1,073,741,824 个字符。2 bytes + number of chars
text可变长度的字符串。最多 2GB 文本数据。4 bytes + number of chars
nchar固定长度的 Unicode 字符串。最多 4,000 个字符。Defined width x 2
nvarchar可变长度的 Unicode 字符串。最多 4,000 个字符。
nvarchar(max)可变长度的 Unicode 字符串。最多 536,870,912 个字符。
ntext可变长度的 Unicode 字符串。最多 2GB 文本数据。
bit允许 0、1 或 NULL
binary(n)固定长度的二进制字符串。最多 8,000 字节。
varbinary可变长度的二进制字符串。最多 8,000 字节。
varbinary(max)可变长度的二进制字符串。最多 2GB。
image可变长度的二进制字符串。最多 2GB。


 Number 类型:

数据类型描述存储
tinyint允许从 0 到 255 的所有数字。1 字节
smallint允许介于 -32,768 与 32,767 的所有数字。2 字节
int允许介于 -2,147,483,648 与 2,147,483,647 的所有数字。4 字节
bigint允许介于 -9,223,372,036,854,775,808 与 9,223,372,036,854,775,807 之间的所有数字。8 字节
decimal(p,s)固定精度和比例的数字。

允许从 -10^38 +1 到 10^38 -1 之间的数字。

p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。

s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。

5-17 字节
numeric(p,s)固定精度和比例的数字。

允许从 -10^38 +1 到 10^38 -1 之间的数字。

p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。

s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。

5-17 字节
smallmoney介于 -214,748.3648 与 214,748.3647 之间的货币数据。4 字节
money介于 -922,337,203,685,477.5808 与 922,337,203,685,477.5807 之间的货币数据。8 字节
float(n)从 -1.79E + 308 到 1.79E + 308 的浮动精度数字数据。

n 参数指示该字段保存 4 字节还是 8 字节。float(24) 保存 4 字节,而 float(53) 保存 8 字节。n 的默认值是 53。

4 或 8 字节
real从 -3.40E + 38 到 3.40E + 38 的浮动精度数字数据。4 字节


 Date 类型:

数据类型描述存储
datetime从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 3.33 毫秒。8 字节
datetime2从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 100 纳秒。6-8 字节
smalldatetime从 1900 年 1 月 1 日 到 2079 年 6 月 6 日,精度为 1 分钟。4 字节
date仅存储日期。从 0001 年 1 月 1 日 到 9999 年 12 月 31 日。3 bytes
time仅存储时间。精度为 100 纳秒。3-5 字节
datetimeoffset与 datetime2 相同,外加时区偏移。8-10 字节
timestamp存储唯一的数字,每当创建或修改某行时,该数字会更新。timestamp 值基于内部时钟,不对应真实时间。每个表只能有一个 timestamp 变量。 


 其他数据类型:

数据类型描述
sql_variant存储最多 8,000 字节不同数据类型的数据,除了 text、ntext 以及 timestamp。
uniqueidentifier存储全局唯一标识符 (GUID)。
xml存储 XML 格式化数据。最多 2GB。
cursor存储对用于数据库操作的指针的引用。
table存储结果集,供稍后处理。


SQL 函数


 SQL 拥有很多可用于计数和计算的内建函数。


SQL Aggregate 函数


 SQL Aggregate 函数计算从列中取得的值,返回一个单一的值。

 有用的 Aggregate 函数:

  • AVG() - 返回平均值
  • COUNT() - 返回行数
  • FIRST() - 返回第一个记录的值
  • LAST() - 返回最后一个记录的值
  • MAX() - 返回最大值
  • MIN() - 返回最小值
  • SUM() - 返回总和

SQL Scalar 函数


 SQL Scalar 函数基于输入值,返回一个单一的值。

 有用的 Scalar 函数:

  • UCASE() - 将某个字段转换为大写
  • LCASE() - 将某个字段转换为小写
  • MID() - 从某个文本字段提取字符
  • LEN() - 返回某个文本字段的长度
  • ROUND() - 对某个数值字段进行指定小数位数的四舍五入
  • NOW() - 返回当前的系统日期和时间
  • FORMAT() - 格式化某个字段的显示方式

提示:在下面的章节,我们会详细讲解 Aggregate 函数和 Scalar 函数。


章节小测


 现在,通过以下题目测测看您对“SQL 函数”的掌握程度吧!

 SQL 函数:在本部分测验中,您将练习使用 SQL 函数。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费



SQL MAX() 函数


MAX() 函数

 MAX() 函数返回所选列的最大值。

SQL MAX() 语法

SELECT MAX(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars22
5Chef Anton's Gumbo Mix2236 boxes21.35

SQL MAX() 实例


 以下SQL语句查找最昂贵的产品的价格:

实例

SELECT MAX(Price) AS LargestPriceFROM Products;

结果集类似这样:

LargestPrice22


SQL MIN() Function


MIN() 函数

 MIN() 函数返回所选列的最小值。

SQL MIN() 语法

SELECT MIN(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars22
5Chef Anton's Gumbo Mix2236 boxes21.35

SQL MIN() 实例


 以下SQL语句查找最便宜的产品的价格:

实例

SELECT MIN(Price) AS SmallestPrice
FROM Products;


章节小测


 现在,通过以下题目测测看您对“SQL MIN() 函数”的掌握程度吧!

 SQL MIN() 函数:在本部分测验中,您将练习使用 SQL MIN() 函数完成从指定表中选择相应的语句,并按照条件进行筛选。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费

COUNT() 函数返回匹配指定条件的行数。

SQL COUNT(column_name) 语法

COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):

SELECT COUNT(column_name) FROM table_name;

SQL COUNT(*) 语法

COUNT(*) 函数返回表中的记录数:

SELECT COUNT(*) FROM table_name;

SQL COUNT(DISTINCT column_name) 语法

COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:

SELECT COUNT(DISTINCT column_name) FROM table_name;

注释:COUNT(DISTINCT) 适用于 ORACLE 和 Microsoft SQL Server,但是无法用于 Microsoft Access。

演示数据库

在本教程中,我们将使用 RUNOOB 样本数据库。

下面是选自 "access_log" 表的数据:

+-----+---------+-------+------------+
| aid | site_id | count | date       |
+-----+---------+-------+------------+
|   1 |       1 |   45 | 2016-05-10 |
|   2 |       3 |   100 | 2016-05-13 |
|   3 |       1 |   230 | 2016-05-14 |
|   4 |       2 |   10 | 2016-05-14 |
|   5 |       5 |   205 | 2016-05-14 |
|   6 |       4 |   13 | 2016-05-15 |
|   7 |       3 |   220 | 2016-05-15 |
|   8 |       5 |   545 | 2016-05-16 |
|   9 |       3 |   201 | 2016-05-17 |
+-----+---------+-------+------------+

SQL COUNT(column_name) 实例

下面的 SQL 语句计算 "access_log" 表中 "site_id"=3 的总访问量:

实例

SELECT COUNT(count) AS nums FROM access_logWHERE site_id=3;

SQL COUNT(*) 实例

下面的 SQL 语句计算 "access_log" 表中总记录数:

实例

SELECT COUNT(*) AS nums FROM access_log;

执行以上 SQL 输出结果如下:

img

SQL COUNT(DISTINCT column_name) 实例

下面的 SQL 语句计算 "access_log" 表中不同 site_id 的记录数:

实例

SELECT COUNT(DISTINCT site_id) AS nums FROM access_log;

执行以上 SQL 输出结果如下:

count2


SQL AVG() 函数


AVG() 函数

 AVG() 函数返回数字列的平均值。

SQL AVG() 语法

SELECT AVG(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用著名的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars22
5Chef Anton's Gumbo Mix2236 boxes21.35

SQL AVG() 实例


 以下SQL语句查找所有产品的平均价格:

实例

SELECT AVG(Price)
FROM Products;

 下面的 SQL 语句选择价格高于平均价格的 "ProductName" 和 "Price" 记录:

实例

SELECT ProductName, Price FROM Products
WHERE Price>(SELECT AVG(Price) FROM Products);


SQL SUM() 函数


 SUM() 函数返回数字列的总和。

SQL SUM() 语法

SELECT SUM(column_name)FROM table_nameWHERE condition;

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "OrderDetails" 表的数据:

OrderDetailIDOrderIDProductIDQuantity
1102481112
2102484210
310248725
410249149
5102495140

SQL SUM() 实例


 下面的 SQL 语句查找 "OrderDetails" 表的 "Quantity" 字段的总数:

实例

SELECT SUM(Quantity)
FROM OrderDetails;


章节小测


 现在,通过以下题目测测看您对“SQL SUM() 函数”的掌握程度吧!

 SQL SUM() 函数:在本部分测验中,您将练习使用 SQL SUM() 函数。

 点击此处进行测试>>

注:以上测试为付费测试,高级VIP免费


SQL 日期函数


 下面的列表中是 SQL 中所有与日期和时间相关的重要函数。你所用的 RDBMS 可能会支持更多其他的函数。下面的列表基于 MySQL 关系型数据库管理系统。

名称描述
ADDDATE()增加日期
ADDTIME()增加时间
CONVERT_TZ()将当前时区更改为另一时区
CURDATE()返回当前日期
CURRENT_DATE(), CURRENT_DATECURDATE() 的别名
CURRENT_TIME(), CURRENT_TIMECURTIME() 的别名
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMPNOW() 的别名
CURTIME()返回当前时间
DATE_ADD()将两个日期相加
DATE_FORMAT()按照指定格式格式化日期
DATE_SUB()将两个日期相减
DATE()从 date 或者 datetime 表达式中提取出日期部分
DATEDIFF()将两个日期相减
DAY()DAYOFMONTH() 的别名
DAYNAME()返回某天在用星期中的名称
DAYOFMONTH()返回某天是当月的第几天 (1-31)
DAYOFWEEK()返回某天是该星期的第几天
DAYOFYEAR()返回某天是一年中的第几天(1-366)
EXTRACT提取日期中的某一部分
FROM_DAYS()将天数转换为日期
FROM_UNIXTIME()将某个日期格式化为 UNIX 时间戳
HOUR()提取小时
LAST_DAY返回参数日期所在月份的最后一天
LOCALTIME(), LOCALTIMENOW() 的别名
LOCALTIMESTAMP, LOCALTIMESTAMP()NOW() 的别名
MAKEDATE()利用年份和某天在该年所处的天数来创建日期
MAKETIMEMAKETIME()
MICROSECOND()由参数返回微秒
MINUTE()由参数返回分钟
MONTH()返回日期参数的月份
MONTHNAME()返回月份的名字
NOW()返回当前日期和时间
PERIOD_ADD()向年月格式的日期数据之间添加一段时间
PERIOD_DIFF()返回两个年月格式的日期数据之间的月份数
QUARTER()返回日期参数所在的季度
SEC_TO_TIME()将秒数转换为 'HH:MM:SS' 格式
SECOND()返回参数中的秒数 (0-59)
STR_TO_DATE()将字符串转换为日期数据
SUBDATE()以三个参数调用的时候是 DATE_SUB() 的同义词
SUBTIME()减去时间
SYSDATE()返回函数执行的时的时刻
TIME_FORMAT()格式化时间
TIME_TO_SEC()将时间参数转换为秒数
TIME()返回参数表达式中的时间部分
TIMEDIFF()将两个时间相减
TIMESTAMP()只有一个参数时,该函数返回 date 或者 datetime 表达式。当有两个参数时,将两个参数相加。
TIMESTAMPADD()在 datetime 表达式上加上一段时间
TIMESTAMPDIFF()在 datetime 表达式上减去一段时间
TO_DAYS()将日期参数转换为天数
UNIX_TIMESTAMP()返回 UNIX 时间戳
UTC_DATE()返回当前 UTC 日期
UTC_TIME()返回当前 UTC 时间
UTC_TIMESTAMP()返回当前 UTC 日期和时间
WEEK()返回参数的星期数
WEEKDAY()返回日期参数时一个星期中的第几天
WEEKOFYEAR()返回日期参数是日历上的第几周 (1-53)
YEAR()返回日期参数中的年份
YEARWEEK()返回年份和星期

ADDDATE(date, INTERVAL expr unit), ADDDATE(expr, days)


 如果调用时第二个参数为 INTERVAL 形式的话,ADDDATE() 就是 DATE_ADD() 的同义词。同样的情况下,SUBDATE() 是 DATE_SUB() 的同义词。有关 INTERVAL 单位参数的信息,见有关 DATE_ADD() 的讨论。

mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| DATE_ADD('1998-01-02', INTERVAL 31 DAY)                 |+---------------------------------------------------------+| 1998-02-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| ADDDATE('1998-01-02', INTERVAL 31 DAY)                  |+---------------------------------------------------------+| 1998-02-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

 如果调用时第二个参数为天数形式的话,则 MySQL 会将其作为整数加到 expr 上。

mysql> SELECT ADDDATE('1998-01-02', 31);+---------------------------------------------------------+| DATE_ADD('1998-01-02', INTERVAL 31 DAY)                 |+---------------------------------------------------------+| 1998-02-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

ADDTIME(expr1,expr2)


 ADDTIME() 将 expr2 加到 expr1 上,并返回结果。expr1 为 time 或者 datetime 表达式,expr2 为 time 表达式。

mysql> SELECT ADDTIME('1997-12-31 23:59:59.999999','1 1:1:1.000002');+---------------------------------------------------------+| DATE_ADD('1997-12-31 23:59:59.999999','1 1:1:1.000002') |+---------------------------------------------------------+| 1998-01-02 01:01:01.000001                              |+---------------------------------------------------------+1 row in set (0.00 sec)

CONVERT_TZ(dt,from_tz,to_tz)


 该函数将 datetime 类型的值 dt 的时区从 from_dt 转换为 to_dt,并返回结果。如果参数无效,则函数返回 NULL。

mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');+---------------------------------------------------------+| CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')           |+---------------------------------------------------------+| 2004-01-01 13:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');+---------------------------------------------------------+| CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00')     |+---------------------------------------------------------+| 2004-01-01 22:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

CURDATE()


 以 'YYYY-MM-DD'(字符串) 或者 YYYYMMDD(数值) 的形式返回当前日期, 具体形式取决于函数处于字符串还是数值型的上下文环境中。

mysql> SELECT CURDATE();+---------------------------------------------------------+| CURDATE()                                               |+---------------------------------------------------------+| 1997-12-15                                              |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT CURDATE() + 0;+---------------------------------------------------------+| CURDATE() + 0                                           |+---------------------------------------------------------+| 19971215                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

CURRENT_DATE and CURRENT_DATE()


 CURRENT_DATE 和 CURRENT_DATE() 是 CURDATE() 的别名。


CURTIME()


 以 'HH:MM:SS'(字符串) 或者 HHMMSS(数值) 的形式返回当前时间, 具体形式取决于函数处于字符串还是数值型的上下文环境中。该函数按照当前时区来表示返回值。

mysql> SELECT CURTIME();+---------------------------------------------------------+| CURTIME()                                               |+---------------------------------------------------------+| 23:50:26                                                |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT CURTIME() + 0;+---------------------------------------------------------+| CURTIME() + 0                                           |+---------------------------------------------------------+| 235026                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

CURRENT_TIME and CURRENT_TIME()


 CURRENT_TIME 和 CURRENT_TIME() 是 CURTIME() 的别名。


CURRENT_TIMESTAMP and CURRENT_TIMESTAMP()


 CURRENT_TIMESTAMP 和 CURRENT_TIMESTAMP() 是 NOW() 的别名。


DATE(expr)


 提取 date 表达式或者 datetime 表达式中的日期部分。

mysql> SELECT DATE('2003-12-31 01:02:03');+---------------------------------------------------------+| DATE('2003-12-31 01:02:03')                             |+---------------------------------------------------------+|  2003-12-31                                             |+---------------------------------------------------------+1 row in set (0.00 sec)

DATEDIFF(expr1,expr2)


 DATEDIFF() 返回 expr1 和 expr2 的差,以天数的形式表示。expr1 和 expr2 应为 date 或者 datetime 表达式。只有参数的日期部分参与了计算。

mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');+---------------------------------------------------------+| DATEDIFF('1997-12-31 23:59:59','1997-12-30')            |+---------------------------------------------------------+| 1                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

DATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)


 这些函数进行有关日期的算术运算。date 是一个 DATETIME 或者 DATE 类型的值,指明了起始时间。expr 表达式则是 date 要增加或者减去的时间间隔。expr 是一个字符串,可以以 '-' 开始来表示负时间区间。 unit 是一个关键词,指明了expr 的单位。

 INTERVAL 关键字和 unit(单位)指示符不区分大小写。

 下表列出了对于每种单位,expr 应有的形式。

unit 值expr 应有的格式
MICROSECOND微秒
SECOND
MINUTE分钟
HOUR小时
DAY
WEEK星期
MONTH
QUARTER季度
YEAR
SECOND_MICROSECOND'秒.微秒'
MINUTE_MICROSECOND'分.微秒'
MINUTE_SECOND'分:秒'
HOUR_MICROSECOND'小时.微秒'
HOUR_SECOND'时:分:秒'
HOUR_MINUTE'时:分'
DAY_MICROSECOND'天.微秒'
DAY_SECOND'天 时:分:秒'
DAY_MINUTE'天 时:分'
DAY_HOUR'天 时'
YEAR_MONTH'年-月'

 QUARTER 和 WEEK 自 MySQL 5.0.0 起受到支持。

mysql> SELECT DATE_ADD('1997-12-31 23:59:59',     -> INTERVAL '1:1' MINUTE_SECOND);+---------------------------------------------------------+| DATE_ADD('1997-12-31 23:59:59', INTERVAL...             |+---------------------------------------------------------+| 1998-01-01 00:01:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);+---------------------------------------------------------+| DATE_ADD('1999-01-01', INTERVAL 1 HOUR)                 |+---------------------------------------------------------+| 1999-01-01 01:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

DATE_FORMAT(date,format)


 根据格式字符串对日期值进行格式化。

 下面这些占位符可以用在格式字符串中,'%' 必须出现在特定的格式字符之前。

占位符描述
%a简写的星期名称(Sun..Sat)
%b简写的月份名称 (Jan..Dec)
%c月份,以数值形式表示(0..12)
%D月份中的日期,带有英文后缀(0th,1st,2nd,3rd 等等)
%d月份中的日期,以数值表示 (00..31)
%e月份中的日期,以数值表示 (0..31)
%f微秒(000000..999999)
%H小时(00..23)
%h小时(01..12)
%I小时(01..12)
%i分钟,以数值表示(00..59)
%j一年中的第几天(001..366)
%k小时(0..23)
%l小时(1..12)
%M月份的名称(January..December)
%m月份,以数值形式表示(00..12)
%pAM 或者 PM
%r时间,12 小时制(hh:mm:ss followed by AM or PM)
%S秒(00..59)
%s秒(00..59)
%T时间,24小时制(hh:mm:ss)
%U星期(00..53),此处星期日为一周的第一天
%u星期(00..53),此处星期一为一周的第一天
%V星期(01..53),此处星期日为一周的第一天;与 %X 一起使用。
%v星期(01..53),此处星期一为一周的第一天;与 %x 一起使用。
%W一周中日期的名称(Sunday..Saturday)
%w一周中的第几天(0=Sunday..6=Saturday)
%X以星期日为第一天的周所处的年份,四位数字表示;同 %V 一起使用。
%x以星期一为第一天的周所处的年份,四位数字表示;同 %v 一起使用。
%Y年份,四位数字表示。
%y年份,两位数字表示。
%%% 字面值
%xx,针对任何以上没有列出的情况。
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');+---------------------------------------------------------+| DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y')          |+---------------------------------------------------------+| Saturday October 1997                                   |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00'    -> '%H %k %I %r %T %S %w');+---------------------------------------------------------+| DATE_FORMAT('1997-10-04 22:23:00.......                 |+---------------------------------------------------------+|  22 22 10 10:23:00 PM 22:23:00 00 6                     |+---------------------------------------------------------+1 row in set (0.00 sec)

DATE_SUB(date,INTERVAL expr unit)


 同 DATE_ADD() 函数相似。


DAY(date)


 DAY() 是 DAYOFMONTH() 的别名。


DAYNAME(date)


 返回 date 在星期中的名称。

mysql> SELECT DAYNAME('1998-02-05');+---------------------------------------------------------+| DAYNAME('1998-02-05')                                   |+---------------------------------------------------------+| Thursday                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

DAYOFMONTH(date)


 返回 date 是当月的第几天,范围为 0 到 31。

mysql> SELECT DAYOFMONTH('1998-02-03');+---------------------------------------------------------+| DAYOFMONTH('1998-02-03')                                |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

DAYOFWEEK(date)


 返回 date 是其所在星期的第几天(1 = Sunday, 2 = Monday,.., 7 = Saturday),这里一星期中日期的名称与数字的对应关系符合 ODBC 标准。

mysql> SELECT DAYOFWEEK('1998-02-03');+---------------------------------------------------------+|DAYOFWEEK('1998-02-03')                                  |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

DAYOFYEAR(date)


 返回 date 是当年的第几天,范围为 1 到 366。

mysql> SELECT DAYOFYEAR('1998-02-03');+---------------------------------------------------------+| DAYOFYEAR('1998-02-03')                                 |+---------------------------------------------------------+| 34                                                      |+---------------------------------------------------------+1 row in set (0.00 sec)

EXTRACT(unit FROM date)


 EXTRACT() 与 DATE_ADD() 和 DATE_SUB() 使用相同的表示单位的占位符,其作用是提取日期值中相应的组成部分,而不是进行日期运算。

mysql> SELECT EXTRACT(YEAR FROM '1999-07-02');+---------------------------------------------------------+| EXTRACT(YEAR FROM '1999-07-02')                         |+---------------------------------------------------------+| 1999                                                    |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03');+---------------------------------------------------------+| EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03')          |+---------------------------------------------------------+| 199907                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

FROM_DAYS(N)


 给出天数 N,返回 DATE 值。

mysql> SELECT FROM_DAYS(729669);+---------------------------------------------------------+| FROM_DAYS(729669)                                       |+---------------------------------------------------------+| 1997-10-07                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

 在使用 FROM_DAYS() 处理比较老的日期的时候应当特别小心,该函数不适用于格里高利历诞生(1582)之前的日期。


FROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)


 返回 UNIX 时间戳对应的日期值,根据函数所处的上下文环境不同,返回值得格式也不同,字符串上下文返回格式为 'YYYY-MM-DD HH:MM:SS',数值型上下文返回格式则为 YYYYMMDDHHMMSS。返回值的时区为系统当前时区。UNIX 时间戳是一种系统内部时间表示,例如 UNIX_TIMESTAMP() 的返回值。

 如果给定格式的话,返回结果将会根据格式字符串进行格式化,其规则同 DATE_FORMAT() 函数。

mysql> SELECT FROM_UNIXTIME(875996580);+---------------------------------------------------------+| FROM_UNIXTIME(875996580)                                |+---------------------------------------------------------+| 1997-10-04 22:23:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

HOUR(time)


 返回时间值的小时部分。对于一天中的时间来说,返回值的范围为 0 到 23。不过,TIME 类型的值可以大得多,所以 HOUR 函数可以返回比 23 大的值。

mysql> SELECT HOUR('10:05:03');+---------------------------------------------------------+| HOUR('10:05:03')                                        |+---------------------------------------------------------+| 10                                                      |+---------------------------------------------------------+1 row in set (0.00 sec)

LAST_DAY(date)


 返回 date 或者 datetime 值所在月份的最后一天。如果参数无效的话,返回 NULL。

mysql> SELECT LAST_DAY('2003-02-05');+---------------------------------------------------------+| LAST_DAY('2003-02-05')                                  |+---------------------------------------------------------+| 2003-02-28                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

LOCALTIME and LOCALTIME()


 LOCALTIME 和 LOCALTIME() 是 NOW() 的别名。


LOCALTIMESTAMP and LOCALTIMESTAMP()


 LOCALTIMESTAMP 和 LOCALTIMESTAMP() 是 NOW() 的别名。


MAKEDATE(year,dayofyear)


 给定年份和(某天在一年中)的天数,返回对应的日期值。天数必须大于 0,否则返回值为 NULL。

mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);+---------------------------------------------------------+| MAKEDATE(2001,31), MAKEDATE(2001,32)                    |+---------------------------------------------------------+| '2001-01-31', '2001-02-01'                              |+---------------------------------------------------------+1 row in set (0.00 sec)

MAKETIME(hour,minute,second)


 根据参数给出的时、分、秒,返回对应的时间值。

mysql> SELECT MAKETIME(12,15,30);+---------------------------------------------------------+| MAKETIME(12,15,30)                                      |+---------------------------------------------------------+| '12:15:30'                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

MICROSECOND(expr)


 根据 time 或者 datetime 表达式 expr,返回微秒数,结果在 0 到 999999 之间。

mysql> SELECT MICROSECOND('12:00:00.123456');+---------------------------------------------------------+| MICROSECOND('12:00:00.123456')                          |+---------------------------------------------------------+| 123456                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

MINUTE(time)


 返回时间型值中的分钟部分,范围为 0 到 59。

mysql> SELECT MINUTE('98-02-03 10:05:03');+---------------------------------------------------------+| MINUTE('98-02-03 10:05:03')                             |+---------------------------------------------------------+| 5                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

MONTH(date)


 返回日期型值中的月份,范围为 0 到 12。

mysql> SELECT MONTH('1998-02-03')+---------------------------------------------------------+| MONTH('1998-02-03')                                     |+---------------------------------------------------------+| 2                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

MONTHNAME(date)


 返回日期型值所处月份的全名。

mysql> SELECT MONTHNAME('1998-02-05');+---------------------------------------------------------+| MONTHNAME('1998-02-05')                                 |+---------------------------------------------------------+| February                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

NOW()


 返回当前的日期和时间,结果的格式为 'YYYY-MM-DD HH:MM:SS' 或者 YYYYMMDDHHMMSS,如果函数上下文环境为字符型,则返回前者,否则如果函数处于数值型的上下文环境,则返回后者。返回值的时区为系统当前时区。

mysql> SELECT NOW();+---------------------------------------------------------+| NOW()                                                   |+---------------------------------------------------------+| 1997-12-15 23:50:26                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

PERIOD_ADD(P,N)


 在时间 P(格式为 YYMM 或者 YYYYMM)上加上 N 个月,结果格式为 YYYYMM。注意,时间参数 P 并不是日期型值。

mysql> SELECT PERIOD_ADD(9801,2);+---------------------------------------------------------+| PERIOD_ADD(9801,2)                                      |+---------------------------------------------------------+| 199803                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

PERIOD_DIFF(P1,P2)


 返回时间 P1 和 P2 之间相差的月份。 P1 和 P2 的格式应为 YYMM 或者 YYYYMM。注意I,P1 和 P2 不是日期型值。

mysql> SELECT PERIOD_DIFF(9802,199703);+---------------------------------------------------------+| PERIOD_DIFF(9802,199703)                                |+---------------------------------------------------------+| 11                                                      |+---------------------------------------------------------+1 row in set (0.00 sec)

QUARTER(date)


 返回日期型值 date 所处的季度值,范围为 1 到 4。

mysql> SELECT QUARTER('98-04-01');+---------------------------------------------------------+| QUARTER('98-04-01')                                     |+---------------------------------------------------------+| 2                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

SECOND(time)


 返回时间型值中秒的部分,范围为 0 到 59。

mysql> SELECT SECOND('10:05:03');+---------------------------------------------------------+| SECOND('10:05:03')                                      |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

SEC_TO_TIME(seconds)


 将参数中的秒数转换为时分秒的格式 'HH:MM:SS' 或者 HHMMSS,如果函数所处的上下文为字符串型,则返回前者,否则如果上下文环境为数值型,则返回后者。


STR_TO_DATE(str,format)


 这是 DATE_FORMATE() 函数的逆函数,其参数为表示时间和日期的字符串 str 和一个格式字符串 format。如果格式字符串中既有日期又有时间,则 STR_TO_DATE() 返回 DATETIME() 型的值,否则返回日期型(DATE)或者时间型(TIME)的值。

mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y');+---------------------------------------------------------+| STR_TO_DATE('04/31/2004', '%m/%d/%Y')                   |+---------------------------------------------------------+| 2004-04-31                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

SUBDATE(date,INTERVAL expr unit) and SUBDATE(expr,days)


 当第二个参数为 INTERVAL 形式时,SUBDATE() 就是 DATE_SUB() 的别名。INTERVAL 参数中单位的信息,请见有关 DATE_ADD() 的讨论。

mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| DATE_SUB('1998-01-02', INTERVAL 31 DAY)                 |+---------------------------------------------------------+| 1997-12-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);+---------------------------------------------------------+| SUBDATE('1998-01-02', INTERVAL 31 DAY)                  |+---------------------------------------------------------+| 1997-12-02                                              |+---------------------------------------------------------+1 row in set (0.00 sec)

SUBTIME(expr1,expr2)


 SUBTIME() 返回 expr1-expr2,结果的格式与 expr1 相同。expr1 是一个时间型(time)或者 datetime 型的表达式,expr2 是时间型值。


SYSDATE()


 返回当前的日期和时间,格式为 'YYYY-MM-DD HH:MM:SS' 或 YYYYMMDDHHMMSS,如果函数所处的上下文环境为字符串,则返回前者,否则如果上下文环境为数值型,则返回后者。

mysql> SELECT SYSDATE();+---------------------------------------------------------+| SYSDATE()                                               |+---------------------------------------------------------+| 2006-04-12 13:47:44                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

TIME(expr)


 提取时间型或者 datetime 型表达式 expr 中的时间部分,返回结果为字符串。

mysql> SELECT TIME('2003-12-31 01:02:03');+---------------------------------------------------------+| TIME('2003-12-31 01:02:03')                             |+---------------------------------------------------------+| 01:02:03                                                |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMEDIFF(expr1,expr2)


 TIMEDIFF() 返回 expr1-expr2,结果为时间型值。expr1 和 expr2 可以为时间型或者 datetime 型表达式,不过二者必须为相同类型。

mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001',    -> '1997-12-30 01:01:01.000002');+---------------------------------------------------------+| TIMEDIFF('1997-12-31 23:59:59.000001'.....              |+---------------------------------------------------------+|  46:58:57.999999                                        |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMESTAMP(expr), TIMESTAMP(expr1,expr2)


 只有一个参数的时候,该函数由日期型或者 datetime 型表达式返回一个 datetime 型值。有两个参数的时候,该函数将 expr2 加到日期型或 datetime 型值 expr1 上,并返回 datetime 型的结果。

mysql> SELECT TIMESTAMP('2003-12-31');+---------------------------------------------------------+| TIMESTAMP('2003-12-31')                                 |+---------------------------------------------------------+| 2003-12-31 00:00:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMESTAMPADD(unit,interval,datetime_expr)


 将整数型的表达式 interval 加到日期型或者 datetime 型表达式 datetime_expr 上。单位由 unit 参数给出,其取值应为以下几种中的一种:FRAC_SECOND、SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER 或者 YEAR。

 单位 unit 可以为上述关键字中的一个,也可以添加一个 SQLTSI 前缀,例如 DAY 和 SQL_TSI_DAY 都是合法的。

mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');+---------------------------------------------------------+| TIMESTAMPADD(MINUTE,1,'2003-01-02')                     |+---------------------------------------------------------+| 2003-01-02 00:01:00                                     |+---------------------------------------------------------+1 row in set (0.00 sec)

TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)


 返回日期型或者 datetime 型表达式 datetime_expr1 和 datetime_expr2 的差。结果的单位由 unit 参数给出,unit 的取值规定同 TIMESTAMPADD() 函数。

mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');+---------------------------------------------------------+| TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01')          |+---------------------------------------------------------+| 3                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

TIME_FORMAT(time,format)


 该函数使用起来类似 DATE_FORMAT() 函数,但是格式字符串 format 中只能有与小时、分钟和秒有关的那些占位符。

 如果时间型值的小时部分大于 23,则 %H 和 %k 格式占位符将会产生一个大于通常的 0-23 的值,其他与小时有关的占位符则会返回小时值除以 12 后的余数(modulo 12)。

mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');+---------------------------------------------------------+| TIME_FORMAT('100:00:00', '%H %k %h %I %l')              |+---------------------------------------------------------+| 100 100 04 04 4                                         |+---------------------------------------------------------+1 row in set (0.00 sec)

TIME_TO_SEC(time)


 将时间型值转换为秒。

mysql> SELECT TIME_TO_SEC('22:23:00');+---------------------------------------------------------+| TIME_TO_SEC('22:23:00')                                 |+---------------------------------------------------------+| 80580                                                   |+---------------------------------------------------------+1 row in set (0.00 sec)、

TO_DAYS(date)


 给定日期型值 date,返回天数(自公元 0 年以来的天数)。

mysql> SELECT TO_DAYS(950501);+---------------------------------------------------------+| TO_DAYS(950501)                                         |+---------------------------------------------------------+| 728779                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)


 不带任何参数时,该函数返回一个 unsigned integer 型的 UNIX 时间戳(自 '1970-01-01 00:00:00' UTC 以来的秒数)。如果有一个参数 date 的话,该函数返回自 '1970-01-01 00:00:00' UTC 至 date 的秒数。date 可以是日期型的字符串、DATETIME 型的字符串、时间戳或者 YYMMDD 或 YYYYMMDD 格式的数字。

mysql> SELECT UNIX_TIMESTAMP();+---------------------------------------------------------+| UNIX_TIMESTAMP()                                        |+---------------------------------------------------------+| 882226357                                               |+---------------------------------------------------------+1 row in set (0.00 sec)mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');+---------------------------------------------------------+| UNIX_TIMESTAMP('1997-10-04 22:23:00')                   |+---------------------------------------------------------+| 875996580                                               |+---------------------------------------------------------+1 row in set (0.00 sec)

UTC_DATE, UTC_DATE()


 返回当前 UTC 日期,格式为 'YYYY-MM-DD' 或者 YYYYMMDD,如果函数所处的上下文环境为字符串,则返回前者,否则如果上下文环境为数值型的,则返回后者。

mysql> SELECT UTC_DATE(), UTC_DATE() + 0;+---------------------------------------------------------+| UTC_DATE(), UTC_DATE() + 0                              |+---------------------------------------------------------+| 2003-08-14, 20030814                                    |+---------------------------------------------------------+1 row in set (0.00 sec)

UTC_TIME, UTC_TIME()


 返回当前 UTC 时间,格式为 'HH:MM:SS' 或者 HHMMSS,如果函数所处的上下文环境为字符串,则返回前者,否则如果上下文环境为数值型的,则返回后者。

mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;+---------------------------------------------------------+| UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0                    |+---------------------------------------------------------+| 2003-08-14 18:08:04, 20030814180804                     |+---------------------------------------------------------+1 row in set (0.00 sec)

WEEK(date[,mode])


 该函数将返回 date 所在的周是当年的第几周。两个参数的 WEEK() 函数的使你能够指明一周起始于周日还是周一,以及返回值的范围应该是 0 到 53,还是 1 到 53。如果 mode 参数被忽略,则将使用 default_week_format 系统变量。

Mode一周的第一天范围周 1 是第一周
0Sunday0-53该年包括一个星期天
1Monday0-53该年包含超过 3 天
2Sunday1-53该年包括一个星期天
3Monday1-53该年包含超过 3 天
4Sunday0-53该年包含超过 3 天
5Monday0-53该年包括一个星期一
6Sunday1-53该年包含超过 3 天
7Monday1-53该年包括一个星期一
mysql> SELECT WEEK('1998-02-20');+---------------------------------------------------------+| WEEK('1998-02-20')                                      |+---------------------------------------------------------+| 7                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

WEEKDAY(date)


 返回 date 是其所在星期的第几天 (0 = Monday, 1 = Tuesday, . 6 = Sunday)。

mysql> SELECT WEEKDAY('1998-02-03 22:23:00');+---------------------------------------------------------+| WEEKDAY('1998-02-03 22:23:00')                          |+---------------------------------------------------------+| 1                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

WEEKOFYEAR(date)


 返回 date 所在的周是当年的第几周,范围从 1 到 53. WEEKOFYEAR() 是一个兼容性函数,其功能同 WEEK(date, 3)相同。

mysql> SELECT WEEKOFYEAR('1998-02-20');+---------------------------------------------------------+| WEEKOFYEAR('1998-02-20')                                |+---------------------------------------------------------+| 8                                                       |+---------------------------------------------------------+1 row in set (0.00 sec)

YEAR(date)


 返回 date 的年份部分,范围为 1000 到 9999,对于日期 0 则返回 0。

mysql> SELECT YEAR('98-02-03');+---------------------------------------------------------+| YEAR('98-02-03')                                        |+---------------------------------------------------------+| 1998                                                    |+---------------------------------------------------------+1 row in set (0.00 sec)

YEARWEEK(date), YEARWEEK(date,mode)


 返回 date 所在的年份和周数。mode 参数意义与 WEEK() 函数的完全一样。对于一年中的第一周和最后一周来说,结果中的年份可能会和 date 参数中的年份不同。

mysql> SELECT YEARWEEK('1987-01-01');+---------------------------------------------------------+| YEAR('98-02-03')YEARWEEK('1987-01-01')                  |+---------------------------------------------------------+| 198653                                                  |+---------------------------------------------------------+1 row in set (0.00 sec)

注意,这里的周数同 WEEK() 返回的不同,因为 WEEK() 函数的返回值在给定年份的的上下文环境中得出。


SQL FIELD()函数


 SQL FIELD()函数实例代码教程 

 FIELD()函数返回的索引(从1开始的位置)的str在str1,str2,str3,...列表中。如果str没有找到,则返回0。

 就是用第一个参数str,跟后面的N个字符串参数中寻找,如果寻找到一模一样的字符串,则返回其索引位置

FIELD(str,str1,str2,str3,...)


 返回的索引(从1开始的位置)的str在str1,str2,str3,...列表中。如果str没有找到,则返回0。

例子

 在第2个位置找到了字符串“ej”

SQL> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');+---------------------------------------------------------+| FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo')          |+---------------------------------------------------------+| 2                                                       |+---------------------------------------------------------+1 row in set (0.00 sec) 


SQL FIRST() 函数


 FIRST() 函数返回指定的列中第一个记录的值。

SQL FIRST() 语法

SELECT FIRST(column_name) FROM table_name;      

注释:只有 MS Access 支持 FIRST() 函数。


SQL Server、MySQL 和 Oracle 中的 SQL FIRST() 工作区


SQL Server 语法

SELECT TOP 1 column_nameFROM table_nameORDER BY column_name ASC;  

实例

SELECT TOP 1 CustomerName FROM Customers                ORDER BY CustomerID ASC;      

MySQL 语法

SELECT column_name FROM table_name                ORDER BY column_name ASC                LIMIT 1; 

实例

SELECT CustomerName FROM Customers               ORDER BY CustomerID ASC                LIMIT 1;   

Oracle 语法

SELECT column_name FROM table_name                ORDER BY column_name ASC               WHERE ROWNUM <=1;                     

实例

SELECT CustomerName FROM Customers                ORDER BY CustomerID ASC                WHERE ROWNUM <=1;       

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL FIRST() 实例


 下面的 SQL 语句选取 "Customers" 表的 "CustomerName" 列中第一个记录的值:

实例

SELECT FIRST(CustomerName) AS FirstCustomer FROM Customers;


SQL LAST() 函数


 LAST() 函数返回指定的列中最后一个记录的值。

SQL LAST() 语法

SELECT LAST(column_name) FROM table_name;    

注释:只有 MS Access 支持 LAST() 函数。


SQL Server、MySQL 和 Oracle 中的 SQL LAST() 工作区


SQL Server 语法

SELECT TOP 1 column_nameFROM table_nameORDER BY column_name DESC;        

实例

SELECT TOP 1 CustomerName FROM Customers               ORDER BY CustomerID DESC;        

MySQL 语法

SELECT column_name FROM table_name                ORDER BY column_name DESC                LIMIT 1;        

实例

SELECT CustomerName FROM Customers                ORDER BY CustomerID DESC                LIMIT 1;     

Oracle 语法

SELECT column_name FROM table_name               ORDER BY column_name DESC                WHERE ROWNUM <=1;       

实例

SELECT CustomerName FROM Customers                ORDER BY CustomerID DESC                WHERE ROWNUM <=1;       

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LAST() Example


 下面的 SQL 语句选取 "Customers" 表的 "CustomerName" 列中最后一个记录的值:

实例

SELECT LAST(CustomerName) AS LastCustomer FROM Customers;


SQL GROUP BY 语句


 Aggregate 函数常常需要添加 GROUP BY 语句。

 GROUP BY语句通常与集合函数(COUNT,MAX,MIN,SUM,AVG)一起使用,以按一个或多个列对结果集进行分组。


GROUP BY 语句


 GROUP BY 语句用于结合 Aggregate 函数,根据一个或多个列对结果集进行分组。

SQL GROUP BY 语法

SELECT column_name(s)FROM table_nameWHERE conditionGROUP BY column_name(s)ORDER BY column_name(s);

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers"表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL GROUP BY示例


 以下SQL语句列出了每个国家/地区的客户数量:

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY Country;

 以下SQL语句列出每个国家的客户数量,从高到低排序:

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY CountryORDER BY COUNT(CustomerID) DESC;

演示数据库


 以下是罗斯文示例数据库中“订单”表的一个选择:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
102489051996-07-043
102498161996-07-051
102503441996-07-082

 并从“Shippers”表中选择:

ShipperIDShipperName
1Speedy Express
2United Package
3Federal Shipping

GROUP BY使用JOIN示例


 以下SQL语句列出了每个发货人发送的订单数量:

SELECT Shippers.ShipperName, COUNT(Orders.OrderID) AS NumberOfOrders FROM OrdersLEFT JOIN Shippers ON Orders.ShipperID = Shippers.ShipperIDGROUP BY ShipperName;

SQL HAVING 子句


 在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与 Aggregate 函数一起使用。

 HAVING子句已添加到SQL中,因为WHERE关键字不能用于聚合函数。

SQL HAVING 语法

SELECT column_name(s)FROM table_nameWHERE conditionGROUP BY column_name(s)HAVING conditionORDER BY column_name(s);

演示数据库


 以下是罗斯文示例数据库中"Customers"表的选择:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL HAVING示例


 以下SQL语句列出了每个国家/地区的客户数量。只包括超过5位客户的国家/地区:

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY CountryHAVING COUNT(CustomerID) > 5;

 以下SQL语句列出每个国家的客户数量,从高到低排序(仅包括拥有超过5名客户的国家/地区):

SELECT COUNT(CustomerID), CountryFROM CustomersGROUP BY CountryHAVING COUNT(CustomerID) > 5ORDER BY COUNT(CustomerID) DESC;


演示数据库


 以下是罗斯文示例数据库中"Orders"表的一个选择:

OrderIDCustomerIDEmployeeIDOrderDateShipperID
102489051996-07-043
102498161996-07-051
102503441996-07-082

并从"Employees"表中选择:

EmployeeIDLastNameFirstNameBirthDatePhotoNotes
1DavolioNancy1968-12-08EmpID1.picEducation includes a BA....
2FullerAndrew1952-02-19EmpID2.picAndrew received his BTS....
3LeverlingJanet1963-08-30EmpID3.picJanet has a BS degree....

更多HAVING示例


 以下SQL语句列出已注册超过10个订单的员工:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrdersFROM OrdersINNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeIDGROUP BY LastNameHAVING COUNT(Orders.OrderID) > 10;

 以下SQL语句列出员工“Davolio”或“Fuller”是否已注册超过25个订单:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrdersFROM OrdersINNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeIDWHERE LastName = 'Davolio' OR LastName = 'Fuller'GROUP BY LastNameHAVING COUNT(Orders.OrderID) > 25;


SQL 字母大小写转换函数UPPER(s)、UCASE(s)、LOWER(s)和LCASE(s)


1、LOWER(s)函数和LCASE(s)函数

 LOWER(s)或者LCASE(s)函数可以将字符串s中的字母字符全部转换成小写字母。

 实例:

 使用LOWER函数或者LCASE函数将字符串中所有字母字符转换为小写。SQL语句如下:

SELECT LOWER('WWW.W3Cschool.cn'),LCASE('W3CSCHOOL.CN');
 执行结果如下:

2、UPPER(s)函数和UCASE(s)函数

 UPPER(s)或UCASE(s)函数可以将字符串s中的字母字符全部转换成大写字母。
 实例:
 使用UPPER函数或者UCASE函数将字符串中的所有字母字符转换为大写。SQL语句如下:
SELECT UPPER('www.51coolma.cn'),UCASE('W3Cschool');
 执行结果如下:


不论是使用哪个函数都可以达到目的,区别不大,你可以根据需要选择一个函数进行使用


SQL UPPER()函数


 SQL upper()函数字母大小写转换函数,将字母转成大写 - 返回字符串str,根据当前字符集映射的所有字符更改为大写。

UPPER(str)

 返回字符串str,根据当前字符集映射的所有字符更改为大写。

SQL> SELECT UPPER('Allah-hus-51coolma');+---------------------------------------------------------+| UPPER('Allah-hus-51coolma')                                |+---------------------------------------------------------+| ALLAH-HUS-W3CSCHOOL                                         |+---------------------------------------------------------+1 row in set (0.00 sec)

 另外还可以参考UCASE()函数 ,它是把字段的值转换为大写。


SQL LOWER()函数


 SQL lower()字母大小写转换函数,将字母转成小写 - 返回根据当前字符集映射所有字符改变为小写,即返回小写的字符串。

LOWER(str)

 返回根据当前字符集映射所有字符改变为小写,即返回小写的字符串。

SQL> SELECT LOWER('W3CSCHOOL');+---------------------------------------------------------+| LOWER('W3CSCHOOL')                                  |+---------------------------------------------------------+| 51coolma                                           |+---------------------------------------------------------+1 row in set (0.00 sec) 

 另外还可以参考LCASE()函数,它是把字段的值转换为小写。

SQL UCASE() 函数


 UCASE() 函数把字段的值转换为大写。

SQL UCASE() 语法

SELECT UCASE(column_name) FROM table_name;      

用于 SQL Server 的语法

SELECT UPPER(column_name) FROM table_name;      

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL UCASE() 实例


 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "City" 列,并把 "CustomerName" 列的值转换为大写:

实例

SELECT UCASE(CustomerName) AS Customer, City
FROM Customers;

SQL LCASE() 函数


 LCASE() 函数把字段的值转换为小写。

SQL LCASE() 语法

SELECT LCASE(column_name) FROM table_name;     

用于 SQL Server 的语法

SELECT LOWER(column_name) FROM table_name;     

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LCASE() 实例


 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "City" 列,并把 "CustomerName" 列的值转换为小写:

实例

SELECT LCASE(CustomerName) AS Customer, City
FROM Customers;

SQL MID() 函数


 MID() 函数用于从文本字段中提取字符。

SQL MID() 语法

SELECT MID(column_name,start[,length]) FROM table_name;       

参数描述
column_name必需。要提取字符的字段。
start必需。规定开始位置(起始值是 1)。
length可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL MID() 实例


 下面的 SQL 语句从 "Customers" 表的 "City" 列中提取前 4 个字符:

实例

SELECT MID(City,1,4) AS ShortCity
FROM Customers;

SQL LEN() 函数


 LEN() 函数返回文本字段中值的长度。

SQL LEN() 语法

SELECT LEN(column_name) FROM table_name;    

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Customers" 表的数据:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany
2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico
3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico
4

Around the HornThomas Hardy120 Hanover Sq.LondonWA1 1DPUK
5Berglunds snabbköpChristina BerglundBerguvsvägen 8LuleåS-958 22Sweden

SQL LEN() 实例


 下面的 SQL 语句从 "Customers" 表中选取 "CustomerName" 和 "Address" 列中值的长度:

实例

SELECT CustomerName,LEN(Address) as LengthOfAddress
FROM Customers;

SQL ROUND() 函数


 ROUND() 函数用于把数值字段舍入为指定的小数位数。

SQL ROUND() 语法

SELECT ROUND(column_name,decimals) FROM table_name;        

参数描述
column_name必需。要舍入的字段。
decimals必需。规定要返回的小数位数。

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars21.35
5Chef Anton's Gumbo Mix2236 boxes25

SQL ROUND() 实例


 下面的 SQL 语句从 "Products" 表中选取产品名称和价格舍入为最接近的整数:。提取前 4 个字符:

实例

SELECT ProductName, ROUND(Price,0) AS RoundedPrice
FROM Products;

SQL NOW() 函数


 NOW() 函数返回当前系统的日期和时间。

SQL NOW() 语法

SELECT NOW() FROM table_name;        

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars21.35
5Chef Anton's Gumbo Mix2236 boxes25


SQL NOW() 实例

 下面的 SQL 语句从 "Products" 表中选取产品名称以及当天的价格:

实例

SELECT ProductName, Price, Now() AS PerDate
FROM Products;

SQL FORMAT() 函数


 FORMAT() 函数用于对字段的显示进行格式化。

SQL FORMAT() 语法

SELECT FORMAT(column_name,format) FROM table_name;        

参数描述
column_name必需。要格式化的字段。
format必需。规定格式。

演示数据库


 在本教程中,我们将使用众所周知的 Northwind 样本数据库。

 下面是选自 "Products" 表的数据:

ProductIDProductNameSupplierIDCategoryIDUnitPrice
1Chais1110 boxes x 20 bags18
2Chang1124 - 12 oz bottles19
3Aniseed Syrup1212 - 550 ml bottles10
4Chef Anton's Cajun Seasoning2248 - 6 oz jars21.35
5Chef Anton's Gumbo Mix2236 boxes25

SQL FORMAT() 实例


 下面的 SQL 语句从 "Products" 表中选取产品名称以及当天(格式化为 YYYY-MM-DD)的价格:

实例

SELECT ProductName, Price, FORMAT(Now(),'YYYY-MM-DD') AS PerDate
FROM Products;

SQL SQRT 函数


 SQRT 函数用于计算得出任何数值的平方根。你可以像下面这样使用 SELECT 语句计算任何数值的平方根:

    SQL>  select SQRT(16);    +----------+    | SQRT(16) |    +----------+    | 4.000000 |    +----------+    1 row in set (0.00 sec)

 你在这里看到的是浮点数,因为 SQL 以浮点数类型来进行平方根的计算。

 你还可以使用 SQRT 函数来计算表中记录的平方根。要获得对 SQRT 函数更深入的了解,请考虑 employee_tbl 表,表中记录如下所示:

    SQL> SELECT * FROM employee_tbl;    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    1 | John | 2007-01-24 |                250 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    3 | Jack | 2007-04-06 |                100 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-06-06 |                300 |    |    5 | Zara | 2007-02-06 |                350 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

 现在,假设你想要获取每个记录中 daily_typing_pages 的平方根,那么你可以用如下命令来达到目的:

    SQL> SELECT name, SQRT(daily_typing_pages)        -> FROM employee_tbl;    +------+--------------------------+    | name | SQRT(daily_typing_pages) |    +------+--------------------------+    | John |                15.811388 |    | Ram  |                14.832397 |    | Jack |                13.038405 |    | Jack |                10.000000 |    | Jill |                14.832397 |    | Zara |                17.320508 |    | Zara |                18.708287 |    +------+--------------------------+    7 rows in set (0.00 sec)

SQL RAND 函数


 SQL 有一个 RAND 函数,用于产生 0 至 1 之间的随机数:

    SQL>  SELECT RAND( ), RAND( ), RAND( );    +------------------+-----------------+------------------+    | RAND( )          | RAND( )         | RAND( )          |    +------------------+-----------------+------------------+    | 0.45464584925645 | 0.1824410643265 | 0.54826780459682 |    +------------------+-----------------+------------------+    1 row in set (0.00 sec)

 当以某个整数值作为参数来调用的时候,RAND() 会将该值作为随机数发生器的种子。对于每一个给定的种子,RAND() 函数都会产生一列可以复现的数字:

    SQL>  SELECT RAND(1), RAND( ), RAND( );    +------------------+------------------+------------------+    | RAND(1 )         | RAND( )          | RAND( )          |    +------------------+------------------+------------------+    | 0.18109050223705 | 0.75023211143001 | 0.20788908117254 |    +------------------+------------------+------------------+    1 row in set (0.00 sec)

 你可以使用 ORDER BY RAND() 来对一组记录进行随机化排列,如下所示:

    SQL> SELECT * FROM employee_tbl;    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    1 | John | 2007-01-24 |                250 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    3 | Jack | 2007-04-06 |                100 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-06-06 |                300 |    |    5 | Zara | 2007-02-06 |                350 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

 现在,试试下面的命令:

    SQL> SELECT * FROM employee_tbl ORDER BY RAND();    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    5 | Zara | 2007-06-06 |                300 |    |    3 | Jack | 2007-04-06 |                100 |    |    3 | Jack | 2007-05-06 |                170 |    |    2 | Ram  | 2007-05-27 |                220 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-02-06 |                350 |    |    1 | John | 2007-01-24 |                250 |    +------+------+------------+--------------------+    7 rows in set (0.01 sec)    SQL> SELECT * FROM employee_tbl ORDER BY RAND();    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    5 | Zara | 2007-02-06 |                350 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-04-06 |                100 |    |    1 | John | 2007-01-24 |                250 |    |    4 | Jill | 2007-04-06 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    5 | Zara | 2007-06-06 |                300 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

SQL CONCAT 函数


 CONCAT 函数用于将两个字符串连接为一个字符串,试一下下面这个例子:

    SQL> SELECT CONCAT('FIRST ', 'SECOND');    +----------------------------+    | CONCAT('FIRST ', 'SECOND') |    +----------------------------+    | FIRST SECOND               |    +----------------------------+    1 row in set (0.00 sec)

 要对 CONCAT 函数有更为深入的了解,请考虑 employee_tbl 表,表中记录如下所示:

    SQL> SELECT * FROM employee_tbl;    +------+------+------------+--------------------+    | id   | name | work_date  | daily_typing_pages |    +------+------+------------+--------------------+    |    1 | John | 2007-01-24 |                250 |    |    2 | Ram  | 2007-05-27 |                220 |    |    3 | Jack | 2007-05-06 |                170 |    |    3 | Jack | 2007-04-06 |                100 |    |    4 | Jill | 2007-04-06 |                220 |    |    5 | Zara | 2007-06-06 |                300 |    |    5 | Zara | 2007-02-06 |                350 |    +------+------+------------+--------------------+    7 rows in set (0.00 sec)

 现在,假设你想要将上表中所有的姓名(name)、id和工作日(work_date)连接在一起,那么可以通过如下的命令来达到目的:

    SQL> SELECT CONCAT(id, name, work_date)        -> FROM employee_tbl;    +-----------------------------+    | CONCAT(id, name, work_date) |    +-----------------------------+    | 1John2007-01-24             |    | 2Ram2007-05-27              |    | 3Jack2007-05-06             |    | 3Jack2007-04-06             |    | 4Jill2007-04-06             |    | 5Zara2007-06-06             |    | 5Zara2007-02-06             |    +-----------------------------+    7 rows in set (0.00 sec)

SQL NULL 函数


SQL ISNULL()、NVL()、IFNULL() 和 COALESCE() 函数

 请看下面的 "Products" 表:

P_IdProductNameUnitPriceUnitsInStockUnitsOnOrder
1Jarlsberg10.451615
2Mascarpone32.5623
3Gorgonzola15.67920

 假如 "UnitsOnOrder" 是可选的,而且可以包含 NULL 值。

 我们使用下面的 SELECT 语句:

SELECT ProductName,UnitPrice*(UnitsInStock+UnitsOnOrder)                FROM Products        

 在上面的实例中,如果有 "UnitsOnOrder" 值是 NULL,那么结果是 NULL。

 微软的 ISNULL() 函数用于规定如何处理 NULL 值。

 NVL()、IFNULL() 和 COALESCE() 函数也可以达到相同的结果。

 在这里,我们希望 NULL 值为 0。

 下面,如果 "UnitsOnOrder" 是 NULL,则不会影响计算,因为如果值是 NULL 则 ISNULL() 返回 0:

SQL Server / MS Access

SELECT ProductName,UnitPrice*(UnitsInStock+ISNULL(UnitsOnOrder,0))                FROM Products       

Oracle

 Oracle 没有 ISNULL() 函数。不过,我们可以使用 NVL() 函数达到相同的结果:

SELECT ProductName,UnitPrice*(UnitsInStock+NVL(UnitsOnOrder,0))                FROM Products        

MySQL

 MySQL 也拥有类似 ISNULL() 的函数。不过它的工作方式与微软的 ISNULL() 函数有点不同。

 在 MySQL 中,我们可以使用 IFNULL() 函数,如下所示:

SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0))                FROM Products        

 或者我们可以使用 COALESCE() 函数,如下所示:

SELECT ProductName,UnitPrice*(UnitsInStock+COALESCE(UnitsOnOrder,0))               FROM Products       

SQL REPLACE()字符串替换函数


实例

 把数据库表article中的所有title字段里的51coolma字符串替换成hello。
update `article` set title=replace(title,'51coolma','hello');

replace函数定义

replace(original-string,search-string,replace-string)

参数

  • original-string: 被搜索的字符串。可为任意长度。 
  • search-string: 要搜索并被 replace-string 替换的字符串。该字符串的长度不应超过 255 个字节。如果 search-string 是空字符串,则按原样返回原始字符串。 
  • replace-string: 该字符串用于替换 search-string。可为任意长度。如果 replace-string 是空字符串,则删除出现的所有 search-string。 

说明

 用字符串表达式3替换字符串表达式1中出现的所有字符串表达式2的匹配项。返回新的字符串。
 如果有某个参数为 NULL,此函数返回 NULL。

SQL TRIM()函数去除字符串头尾空格


 SQL 中的 TRIM 函数是用来移除掉一个字串中的字头或字尾。最常见的用途是移除字首或字尾的空白。这个函数在不同的资料库中有不同的名称:

  • MySQL: TRIM( ), RTRIM( ), LTRIM( )
  • Oracle: RTRIM( ), LTRIM( )
  • SQL Server: RTRIM( ), LTRIM( )

 各种 trim 函数的语法如下:

  • TRIM ( [ [位置] [要移除的字串] FROM ] 字串): [位置] 的可能值为 LEADING (起头), TRAILING (结尾), or BOTH (起头及结尾)。 这个函数将把 [要移除的字串] 从字串的起头、结尾,或是起头及结尾移除。如果我们没有列出 [要移除的字串] 是什么的话,那空白就会被移除。
  • LTRIM(字串): 将所有字串起头的空白移除。
  • RTRIM(字串): 将所有字串结尾的空白移除。

例1 TRIM()

SELECT TRIM('   Sample   ');

 结果:

'Sample'

例2 LTRIM()

SELECT LTRIM('   Sample   ');

 结果:

'Sample   '

例3 RTRIM()

SELECT RTRIM('   Sample   ');

 结果:

'   Sample'

SQL 主机


 如果您想要您的网站存储数据在数据库并从数据库显示数据,您的 Web 服务器必须能使用 SQL 语言访问数据库系统。

 如果您的 Web 服务器托管在互联网服务提供商(ISP,全称 Internet Service Provider),您必须寻找 SQL 主机计划。

 最常见的 SQL 主机数据库是 MySQL、MS SQL Server 和 MS Access。

 您可以在 Windows 和 Linux/UNIX 操作系统上运行 SQL 主机数据库。

 下面是操作系统上对应运行的数据库系统的概览。

  • MS SQL Server
    只在 Windows OS 上运行。
  • MySQL
    在 Windows, Mac OS X 和 Linux/UNIX 操作系统上运行。
  • MS Access(只建议用于小型网站)
    只在 Windows OS 上运行。

 如需学习有关 Web 主机的知识,请访问我们的 主机教程

我们已经学习了 SQL,下一步学习什么呢?


SQL 总结

 本 SQL 教程已经向您讲解了用来访问和处理数据库系统的标准计算机语言。

 我们已经学习了如何使用 SQL 在数据库中执行查询、获取数据、插入新的记录、删除记录以及更新记录。

 我们已经学习了如何通过 SQL 创建数据库、表、索引,以及如何撤销它们。

 我们已经学习了 SQL 中最重要的 Aggregate 函数。

 SQL 是一种与数据库系统协同工作的标准语言,这些数据库系统包括 MS SQL Server、IBM DB2、Oracle、MySQL 和 MS Access 等等。


我们已经学习了 SQL,下一步学习什么呢?


 我们建议接下来学习 ADO 或 PHP MySQL。

 如果您想要学习有关 ADO 的知识,请访问我们的 ADO 教程

 如果您想要学习有关 MySQL 的知识,请访问我们的 PHP 教程

您可以通过 W3Cschool 的测验程序来测试您的 SQL 技能。

关于本测验


 本测验包含 20 道题,每道题的最长答题时间是 20 分钟(这是由于每个 session 的默认有效时间是 20 钟)。

 本测验是非官方的测试,它仅仅提供了一个了解您对 SQL 的掌握程度的工具。


测验会被记分


 每道题的分值是 1 分。在您完成全部的20道题之后,系统会为您的测验打分,并提供您做错的题目的正确答案。其中,绿色为正确答案,而红色为错误答案。

 现在就开始测验!祝您好运。


详尽的SQL语句大全分类整理


Structured Query Language 即结构化查询语言,简称 SQL。SQL 是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。SQL 语句的种类还和数量都很多,其中的很多语句也是经常要用到的,下面就把常用的 SQL 语句分类整理一下,并且还可以打包下载,希望能对你有所帮助。


一、基础篇


 1、说明:创建数据库

CREATE DATABASE database-name

2、说明:删除数据库

drop database dbname

3、说明:备份sql server

 --- 创建 备份数据的 device

USE masterEXEC sp_addumpdevice 'disk', 'testBack', 'c:mssql7backupMyNwind_1.dat'


 --- 开始 备份

BACKUP DATABASE pubs TO testBack

4、说明:创建新表

create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)

 根据已有的表创建新表: 
 Acreate table tab_new like tab_old (使用旧表创建新表)
 B
create table tab_new as select col1,col2… from tab_old definition only

5、说明:删除新表

drop table tabname

6、说明:增加一个列

Alter table tabname add column col type

注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。

7、说明:添加主键

Alter table tabname add primary key(col)

 删除主键:

Alter table tabname drop primary key(col)

8、说明:创建索引

create [unique] index idxname on tabname(col….)

 删除索引:

drop index idxname

注:索引是不可更改的,想更改必须删除重新建。

9、说明:创建视图

create view viewname as select statement

 删除视图:

drop view viewname

10、说明:几个简单的基本的sql语句

  • 选择:

  • select * from table1 where 范围
  • 插入:
    insert into table1(field1,field2) values(value1,value2)
  • 删除:
    delete from table1 where 范围
  • 更新:
    update table1 set field1=value1 where 范围
  • 查找:
    select * from table1 where field1 like ’%value1%’ 
    ---like的语法很精妙,请查资料!
  • 排序:
    select * from table1 order by field1,field2 [desc]
  • 总数:
    select count as totalcount from table1
  • 求和:
    select sum(field1) as sumvalue from table1
  • 平均:
    select avg(field1) as avgvalue from table1
  • 最大:
    select max(field1) as maxvalue from table1
  • 最小:
    select min(field1) as minvalue from table1

11、说明:几个高级查询运算词

 A: UNION 运算符 
 UNION 运算符通过组合其他两个结果表(例如  TABLE1  TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL  UNION一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自  TABLE2


 B EXCEPT 运算符 
 EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL  EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。


 C INTERSECT 运算符
 INTERSECT 运算符通过只包括  TABLE1  TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL  INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。

注:使用运算词的几个查询结果行必须是一致的。

12、说明:使用外连接

 Aleft outer join 
 左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。
 
 SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c


 Bright outer join: 
 右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。


 Cfull/cross outer join 
 全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。

13、分组:Group by:

 一张表,一旦分组 完成后,查询后只能得到组相关的信息。
 组相关的信息:(统计信息) count,sum,max,min,avg 分组的标准)
 在SQLServer中分组时:不能以 text,ntext,image类型的字段作为分组依据
 在selecte统计函数中的字段,不能和普通的字段放在一起;

14、对数据库进行操作

 分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后接表明,附加需要完整的路径名

15、如何修改数据库的名称

sp_renamedb 'old_name', 'new_name'



二、提升篇


1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)

 方法一:(仅用于SQlServer) 

select * into b from a where 1<>1

 方法二:

select top 0 * into b from a

2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)

insert into b(a, b, c) select d,e,f from a;

3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)

insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件 

 例子:

..from b in '"&Server.MapPath(".")&"data.mdb" &"' where..

4、说明:子查询(表名1:a 表名2:b)

select a,b,c from a where a IN (select d from b ) 

 或者: 

select a,b,c from a where a IN (1,2,3)

5、说明:显示文章、提交人和最后回复时间

select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b

6、说明:外连接查询(表名1:a 表名2:b)

select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c

7、说明:在线视图查询(表名1:a )

select * from (SELECT a,b,c FROM a) T where t.a > 1;

8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括

select * from table1 where time between time1 and time2 
select a,b,c, from table1 where a not between 数值1 and 数值2

9、说明:in 的使用方法

select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)

10、说明:两张关联表,删除主表中已经在副表中没有的信息

delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )

11、说明:四表联查问题

select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where ......

12、说明:日程安排提前五分钟提醒

select * from 日程安排 where datediff('minute',f开始时间,getdate())>5

13、说明:一条sql 语句搞定数据库分页

select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段


 具体实现:
 关于数据库分页:

declare @start int,@end int@sql nvarchar(600)set @sql=’select top’+str(@end-@start+1)+’+from T where rid not in(select top’+str(@str-1)+’Rid from T where Rid>-1)’exec sp_executesql @sql

注意:在top后不能直接跟一个变量,所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列,如果top后还有具体的字段,这样做是非常有好处的。因为这样可以避免 top的字段如果是逻辑索引的,查询的结果后实际表中的不一致(逻辑索引中的数据有可能和数据表中的不一致,而查询时如果处在索引则首先查询索引)

14、说明:前10条记录

select top 10 * form table1 where 范围

15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)

select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)

16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表

(select a from tableA ) except (select a from tableB) except (select a from tableC)

17、说明:随机取出10条数据

select top 10 * from tablename order by newid()

18、说明:随机选择记录

select newid()

19、说明:删除重复记录

 1、

delete from tablename where id not in (select max(id) from tablename group by col1,col2,...) 

 2、

select distinct * into temp from tablename delete from tablename insert into tablename select * from temp

评价: 这种操作牵连大量的数据的移动,这种做法不适合大容量但数据操作

3、例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段

alter table tablename --添加一个自增列 add column_b int identity(1,1) delete from tablename where column_b not in( select max(column_b) from tablename group by column1,column2,...) alter table tablename drop column column_b

20、说明:列出数据库里所有的表名

select name from sysobjects where type='U' // U代表用户

21、说明:列出表里的所有的列名

select name from syscolumns where id=object_id('TableName') 

22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。

select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type 

 显示结果:

type vender pcs电脑 A 1 电脑 A 1 光盘 B 2 光盘 A 2 手机 B 3 手机 C 3

23、说明:初始化表table1

TRUNCATE TABLE table1

24、说明:选择从10到15的记录

select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc


三、技巧篇


11=11=2的使用,在SQL语句组合时用的较多

 “where 1=1” 是表示选择全部 “where 1=2”全部不选,
 如:

if @strWhere !='' beginset @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere endelse beginset @strSQL = 'select count(*) as Total from [' + @tblName + ']' end

 我们可以直接写成:

错误!未找到目录项。set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定'+ @strWhere

2、收缩数据库

--重建索引DBCC REINDEXDBCC INDEXDEFRAG--收缩数据和日志DBCC SHRINKDBDBCC SHRINKFILE

3、压缩数据库

dbcc shrinkdatabase(dbname)

4、转移数据库给新用户以已存在用户权限

exec sp_change_users_login 'update_one','newname','oldname'go

5、检查备份集

RESTORE VERIFYONLY from disk='E:dvbbs.bak'

6、修复数据库

ALTER DATABASE [dvbbs] SET SINGLE_USERGODBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCKGOALTER DATABASE [dvbbs] SET MULTI_USERGO

7、日志清除

SET NOCOUNT ONDECLARE @LogicalFileName sysname,@MaxMinutes INT,@NewSize INT


USE tablename -- 要操作的数据库名SELECT @LogicalFileName = 'tablename_log', -- 日志文件名 @MaxMinutes = 10, -- Limit on time allowed to wrap log.@NewSize = 1 -- 你想设定的日志文件的大小(M)Setup / initializeDECLARE @OriginalSize intSELECT @OriginalSize = size FROM sysfilesWHERE name = @LogicalFileNameSELECT 'Original Size of ' + db_name() + ' LOG is ' + CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'FROM sysfilesWHERE name = @LogicalFileNameCREATE TABLE DummyTrans(DummyColumn char (8000) not null)


DECLARE @Counter INT,@StartTime DATETIME,@TruncLog VARCHAR(255)SELECT @StartTime = GETDATE(),@TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'DBCC SHRINKFILE (@LogicalFileName, @NewSize)EXEC (@TruncLog)-- Wrap the log if necessary.WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expiredAND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName) AND (@OriginalSize * 8 /1024) > @NewSize BEGIN -- Outer loop.SELECT @Counter = 0WHILE ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))BEGIN -- updateINSERT DummyTrans VALUES ('Fill Log') DELETE DummyTransSELECT @Counter = @Counter + 1ENDEXEC (@TruncLog) ENDSELECT 'Final Size of ' + db_name() + ' LOG is ' +CONVERT(VARCHAR(30),size) + ' 8K pages or ' + CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'FROM sysfiles WHERE name = @LogicalFileNameDROP TABLE DummyTransSET NOCOUNT OFF

8、说明:更改某个表

exec sp_changeobjectowner 'tablename','dbo' 

9、存储更改全部表 

CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch@OldOwner as NVARCHAR(128),@NewOwner as NVARCHAR(128)ASDECLARE @Name as NVARCHAR(128)DECLARE @Owner as NVARCHAR(128)DECLARE @OwnerName as NVARCHAR(128)DECLARE curObject CURSOR FOR select 'Name' = name,'Owner' = user_name(uid)from sysobjectswhere user_name(uid)=@OldOwnerorder by nameOPEN curObjectFETCH NEXT FROM curObject INTO @Name, @OwnerWHILE(@@FETCH_STATUS=0)BEGIN if @Owner=@OldOwner beginset @OwnerName = @OldOwner + '.' + rtrim(@Name)exec sp_changeobjectowner @OwnerName, @NewOwnerend-- select @name,@NewOwner,@OldOwnerFETCH NEXT FROM curObject INTO @Name, @OwnerENDclose curObjectdeallocate curObjectGO

10SQL SERVER中直接循环写入数据

declare @i intset @i=1while @i<30begininsert into test (userid) values(@i)set @i=@i+1end

 案例

 有如下表,要求就裱中所有沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:

Name scoreZhangshan 80Lishi 59Wangwu 50Songquan 69while((select min(score) from tb_table)<60) begin update tb_table set score =score*1.01 where score<60 if (select min(score) from tb_table)>60 break else continue end


四、数据开发篇


1.按姓氏笔画排序

Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as //从少到多

2.数据库加密

select encrypt('原始密码') select pwdencrypt('原始密码') select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同 encrypt('原始密码') select pwdencrypt('原始密码') select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同

3.取回表中字段

declare @list varchar(1000), @sql nvarchar(1000)  select @list=@list+','+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name='表A' set @sql='select '+right(@list,len(@list)-1)+' from 表A'  exec (@sql)

4.查看硬盘分区

EXEC master..xp_fixeddrives

5.比较A,B表是否相等

if (select checksum_agg(binary_checksum(*)) from A) = (select checksum_agg(binary_checksum(*)) from B) print '相等' else print '不相等'

6.杀掉所有的事件探察器进程

DECLARE hcforeach CURSOR GLOBAL FOR SELECT 'kill '+RTRIM(spid) FROM master.dbo.sysprocesses WHERE program_name IN('SQL profiler',N'SQL 事件探查器') EXEC sp_msforeach_worker '?'

7.记录搜索

 开头到N条记录

Select Top N * From 表 


 N到M条记录(要有主索引ID)

Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID Desc 


 N到结尾记录

Select Top N * From 表 Order by ID Desc


 案例

 示例1:一张表有一万多条记录,表的第一个字段 RecID 是自增长字段, 写一个SQL语句, 找出表的第31到第40个记录。

select top 10 recid from A where recid not in(select top 30 recid from A)

 分析:如果这样写会产生某些问题,如果recid在表中存在逻辑索引。

 select top 10 recid from A where……是从索引中查找,而后面的select top 30 recid from A则在数据表中查找,这样由于索引中的顺序有可能和数据表中的不一致,这样就导致查询到的不是本来的欲得到的数据。


 解决方案

 1, 用order by select top 30 recid from A order by ricid 如果该字段不是自增长,就会出现问题

 2, 在那个子查询中也加条件:select top 30 recid from A where recid>-1

 

 示例2:查询表中的最后以条记录,并不知道这个表共有多少数据,以及表结构。

set @s = 'select top 1 * from T where pid not in (select top ' + str(@count-1) + ' pid from T)'print @s exec sp_executesql @s

9:获取当前数据库中的所有用户表

select Name from sysobjects where xtype='u' and status>=0

10:获取某一个表的所有字段

select name from syscolumns where id=object_id('表名')
select name from syscolumns where id in (select id from sysobjects where type = 'u' and name = '表名')

注:以上两种方式的效果相同

11:查看与某一个表相关的视图、存储过程、函数

select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'

12:查看当前数据库中所有存储过程

select name as 存储过程名称 from sysobjects where xtype='P'

13:查询用户创建的所有数据库

select * from master..sysdatabases D where sid not in(select sid from master..syslogins where name='sa')

 或者:

select dbid, name AS DB_NAME from master..sysdatabases where sid <> 0x01

14:查询某一个表的字段和数据类型

select column_name,data_type from information_schema.columns where table_name = '表名'

15:不同服务器数据库之间的数据操作

 --创建链接服务器

exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 'exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用户名 ', '密码 '

 

 --查询示例

select * from ITSV.数据库名.dbo.表名


 --导入示例

select * into 表 from ITSV.数据库名.dbo.表名


 --以后不再使用时删除链接服务器

exec sp_dropserver 'ITSV ', 'droplogins '


 --连接远程/局域网数据(openrowset/openquery/opendatasource) 

 --1、openrowset

 --查询示例:

select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)

 --生成本地表:

select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)

 --把本地表导入远程表:

insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)select *from 本地表

 --更新本地表:

update bset b.列A=a.列Afrom openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 bon a.column1=b.column1

 --openquery用法需要创建一个连接

 --首先创建一个连接创建链接服务器

exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 '

 --查询

select *FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')

 --把本地表导入远程表

insert openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')select * from 本地表

 --更新本地表

update bset b.列B=a.列BFROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') as ainner join 本地表 b on a.列A=b.列A

 --3、opendatasource/openrowset

SELECT *FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码' ).test.dbo.roy_ta

 --把本地表导入远程表

insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名select * from 本地表

全面解析SQL存储过程


 存储过程(Stored Procedure),是一组为了完成特定功能的SQL 语句,类似一门程序设计语言,也包括了数据类型、流程控制、输入和输出和它自己的函数库。存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。不过SQL存储过程对于一些初学者来说还是比较抽象难理解的,因此本文将由浅至深地剖析SQL存储过程,帮助你学习它。


存储过程的优点


  1. 存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度,效率要比T-SQL语句高。
  2. 当对数据库进行复杂操作时,可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
  3. 一个存储过程在程序在网络中交互时可以替代大堆的T-SQL语句,所以也能降低网络的通信量,提高通信速率。
  4. 存储过程可以重复使用,可减少数据库开发人员的工作量。
  5. 安全性高,可设定只有某些用户才具有对指定存储过程的使用权


存储过程基本语法


--------------创建存储过程-----------------CREATE PROC [ EDURE ] procedure_name [ ; number ]    [ { @parameter data_type }        [ VARYING ] [ = default ] [ OUTPUT ]    ] [ ,...n ][ WITH    { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ][ FOR REPLICATION ]AS sql_statement [ ...n ]--------------调用存储过程-----------------EXECUTE Procedure_name '' --存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value--------------删除存储过程-----------------drop procedure procedure_name    --在存储过程中能调用另外一个存储过程,而不能删除另外一个存储过程

创建存储过程的参数


  1. procedure_name :存储过程的名称,在前面加#为局部临时存储过程,加##为全局临时存储过程。
  2. number:是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。 
  3. @parameter:存储过程的参数。可以有一个或多个。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2100 个参数。
    使用 @ 符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。有关更多信息,请参见 EXECUTE。 
  4. data_type:参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。有关 SQL Server 提供的数据类型及其语法的更多信息,请参见数据类型。
    说明对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。 
  5. VARYING:指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。 
  6. default: 参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。
  7. OUTPUT:表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。 
  8. RECOMPILE: 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。
  9. ENCRYPTION: 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。 说明在升级过程中,SQL Server 利用存储在 syscomments 中的加密注释来重新创建加密过程。 
  10. FOR REPLICATION:指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。 
  11. AS:指定过程要执行的操作。
  12. sql_statement:过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。


实例操作学习


 下面通过表Student来具体了解一下存储过程,因为是要了解存储过程的简单用法,所以例子很简单。


Student


无参数存储过程

 选出Student表中的所有信息

create proc StuProcas      //此处 as 不可以省略不写begin   //begin 和 end 是一对,不可以只写其中一个,但可以都不写select S#,Sname,Sage,Ssex from studentendgo

有参数存储过程

 全局变量

 全局变量也称为外部变量,是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。

 选出指定姓名的学生信息:

create proc StuProc@sname varchar(100)   as beginselect S#,Sname,Sage,Ssex from student where sname=@snameendgoexec StuProc '赵雷'   //执行语句

 上面是在外部给变量赋值,也可以在内部直接给变量设置默认值

create proc StuProc@sname varchar(100)='赵雷'as beginselect S#,Sname,Sage,Ssex from student where sname=@snameendgoexec StuProc

 也可以把变量的内容输出,使用output

create proc StuProc@sname varchar(100),@IsRight int  output //传出参数as if exists (select S#,Sname,Sage,Ssex from student where sname=@sname)set @IsRight =1elseset @IsRight=0godeclare @IsRight int exec StuProc '赵雷' , @IsRight outputselect @IsRight
 以上是全局变量,下面来了解局部变量

 局部变量

 局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内部,离开该函数后再使用这种变量是非法的。

 局部变量的定义

 必须先用Declare命令定以后才可以使用,declare{@变量名 数据类型}

 局部变量的赋值方法

 set{@变量名=表达式}或者select{@变量名=表达式}

 局部变量的显示

create proc StuProcas declare @sname varchar(100)set @sname='赵雷'select S#,Sname,Sage,Ssex from student where sname=@snamegoexec StuProc

 那如果是要把局部变量的数据显示出来怎么办呢?

create proc StuProcas declare @sname varchar(100)set @sname=(select Sname from student where S#=01)select @snamegoexec StuProc


更详细的实例操作学习


 比如,在SQL Server查询编辑器窗口中用CREATE PROCEDURE语句创建存储过程PROC_InsertEmployee,用于实现向员工信息表(tb_Employee)中添加信息,同时生成自动编号。其SQL语句如下:
IF EXISTS (SELECT name     FROM   sysobjects     WHERE  name = 'Proc_InsertEmployee'     AND          type = 'P') DROP PROCEDURE Proc_InsertEmployee GO CREATE PROCEDURE Proc_InsertEmployee @PName nvarchar(50), @PSex nvarchar(4), @PAge int, @PWage money AS begin    declare @PID nvarchar(50)    select @PID=Max(员工编号) from tb_Employee    if(@PID is null)        set @PID='P1001'    else        set @PID='P'+cast(cast(substring(@PID,2,4) as int)+1 as nvarchar(50))    begin        insert into tb_Employee values(@PID,@PName,@PSex,@PAge,@PWage)    end end go 

存储过程的修改

 创建完存储过程之后,如果需要重新修改存储过程的功能及参数,可以在SQL Server 2005中通过以下两种方法进行修改:一种是用Microsoft SQL Server Mangement修改存储过程;另外一种是用T-SQL语句修改存储过程。

 使用Microsoft SQL Server Mangement修改存储过程,步骤如下:
    
 (1)在SQL Server Management Studio的“对象资源管理器”中,选择要修改存储过程所在的数据库(如:db_18),然后在该数据库下,选择“可编程性”。
 (2)打开“存储过程”文件夹,右键单击要修改的存储过程(如:PROC_SEINFO),在弹出的快捷菜单中选择“修改”命令,将会出现查询编辑器窗口。用户可以在此窗口中编辑T-SQL代码,完成编辑后,单击工具栏中的“执行(X)”按钮,执行修改代码。用户可以在查询编辑器下方的Message窗口中看到执行结果信息。

 使用Transact-SQL修改存储过程: 
 使用ALTER PROCEDURE语句修改存储过程,它不会影响存储过程的权限设定,也不会更改存储过程的名称。

 语法:
ALTER PROC [ EDURE ] procedure_name [ ; number ]     [ { @parameter data_type }           [ VARYING ] [ = default ] [ OUTPUT ]     ] [ ,...n ]  [ WITH     { RECOMPILE | ENCRYPTION         | RECOMPILE , ENCRYPTION   }  ] [ FOR REPLICATION ]  AS     sql_statement [ ...n ]

参数说明

 procedure_name:是要更改的存储过程的名称。

 交叉链接:关于ALTER PROCEDURE语句的其他参数与CREATE PROCEDURE语句相同,可参见上面的“创建存储过程的参数”。

 例如,修改存储过程PROC_SEINFO,用于查询年龄大于35的员工信息。SQL语句如下:

ALTER PROCEDURE [dbo].[PROC_SEINFO] AS BEGIN SELECT * FROM tb_Employee where 员工年龄>35 END

存储过程的删除

 使用Microsoft SQL Server Mangement删除存储过程,步骤如下:

 (1)在SQL Server Management Studio的“对象资源管理器”中,选择要删除存储过程所在的数据库(如:db_student),然后在该数据库下选择“可编程性”。  

 (2)打开“存储过程”文件夹,右键单击要删除的存储过程(如:PROC_SEINFO),在弹出的快捷菜单中选择“删除”命令。

 (3)单击“确定”按钮,即可删除所选定的存储过程。  

注意:删除数据表后,并不会删除相关联的存储过程,只是其存储过程无法执行。


 使用T-SQL删除存储过程:

 DROP PROCEDURE语句用于从当前数据库中删除一个或多个存储过程或过程组。 

 语法:

DROP PROCEDURE { procedure } [ ,...n ]

 参数说明:   

  • Procedure:是要删除的存储过程或存储过程组的名称。过程名称必须符合标识符规则。可以选择是否指定过程所有者名称,但不能指定服务器名称和数据库名称。   
  • n:是表示可以指定多个过程的占位符。

    

 例如删除PROC_SEINFO存储过程的SQL语句如下。

DROP PROCEDURE PROC_SEINFO
 例如,删除多个存储过程proc10、proc20和proc30。
DROP PROCEDURE proc10, proc20, proc30
  例如,删除存储过程组procs(其中包含存储过程proc1、proc2、proc3)。
DROP PROCEDURE procs

注意:SQL语句DROP不能删除存储过程组中的单个存储过程。

应用存储过程验证用户登录身份:

 目前,验证用户登录身份的方法有多种,而通过调用存储过程来实现用户身份验证是目前最好的解决方案之一。因为存储过程在创建时即在服务器上进行编译,所以执行起来比单个SQL语句要快得多。

 本例是通过调用存储过程来验证用户登录的用户名和密码是否正确。运行本实例,在“用户名”和“密码”文本框中输入相应的用户名和密码,单击“登录”按钮即可。

 程序开发步骤:

 (1)新建一个网站,将其命名为"index",默认主页名为Default.aspx。    

 (2)Default.aspx页面涉及到的控件如表1所示。


Default.aspx页面涉及到的控件


 (3)主要程序代码如下。
 打开SQL Server Management Studio,并连接到SQL Server2005中的数据库。单击工具栏中“ ”按钮,新建查询编辑器。在该查询编辑器中,创建验证登录用户身份的存储过程PROC_EXISTS,具体的SQL语句如下:

CREATE PROC PROC_EXISTS ( @UserName NVARCHAR(20), @PassWord NVARCHAR(20), @ReturnValue int OUTPUT ) AS IF EXISTS(select * from tb_member where userName=@UserName AND passWord=@PassWord)        set @ReturnValue= 100 ELSE        set @ReturnValue= -100 GO

 在"登录"按钮的Click事件下,执行验证登录用户身份的存储过程,如果输入的用户名和密码正确,则弹出对话框提示用户登录成功,代码如下:

protected void btnLogin_Click(object sender, EventArgs e)     {         //连接数据库         myConn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"].ToString());         myCmd = new SqlCommand("PROC_EXISTS", myConn);   //调用存储过程,判断用户是否存在        myCmd.CommandType = CommandType.StoredProcedure;         //为存储过程的参数赋值         SqlParameter userName=new SqlParameter("@UserName", SqlDbType.NVarChar, 20);         userName.Value=this.txtName.Text.Trim();         myCmd.Parameters.Add(userName);         SqlParameter passWord=new SqlParameter("@PassWord", SqlDbType.NVarChar, 20);         passWord.Value = this.txtPassword.Text.Trim();         myCmd.Parameters.Add(passWord);         //指出该参数是存储过程的OUTPUT参数         SqlParameter ReturnValue = new SqlParameter("@ReturnValue",SqlDbType.Int ,4);         ReturnValue.Direction = ParameterDirection.Output;         myCmd.Parameters.Add(ReturnValue);         try         {             myConn.Open();             myCmd.ExecuteNonQuery();             if (int.Parse(ReturnValue.Value.ToString()) == 100)             {                 Response.Write("<script>alert('您是合法用户,登录成功!')</script>");                 return;             }             else             {                 Response.Write("<script>alert('您输入的用户名和密码不正确,请重新输入!')</script>");                 return;             }         }         catch(Exception ex)         {             Response.Write(ex.Message.ToString());         }         finally         {             myConn.Close();             myConn.Dispose();             myCmd.Dispose();         }}