目录
一、
下面的语句在 Products 表的产品名列上创建一个简单的索引。事务处理中可以使用这些语句,但进行回退时,这些操作也不撤销。但这些好处是有代价的。这两个术语多半是可以交替使用的,但从技术上说,行才是正确的术语。
提示:可以回退哪些语句?
事务处理用来管理 INSERT、如果第一条 UPDATE 起作用,但第二条失败,则 UPDATE 不会提交。LIKE指示 DBMS,后跟的搜索模式利用通配符匹配而不是简单的相等匹配进行比较。下面的例子对 OrderItems 表施加了检查约束,它保证所有物品的数量大于 0。你可能还想使 DBMS 保证每个社会安全号也是唯一的(保证输入错误不会导致使用他人号码)。游标控制(Cursor Control)1、存储过程其实就是编译好等待调用的函数。一旦声明,就必须打开游标以供使用。数据库基础概念
数据库(database):
- 保存有组织的数据的容器(通常是一个文件或一组文件)。但此术语一般指 SELECT 语句。
假如想把另一表中的顾客列合并到 Customers 表中。操作存储过程
四、
-- count统计行数,COUNT(*)统计该表所有行数,即使某些行的某列值是NULL-- 返回 Customers 表中顾客的总数SELECT COUNT(*) -- 14行FROM products; SELECT COUNT(prod_price) -- 13行,因为有一个price为NULLFROM products;-- 统计拥有邮箱的顾客有多少个?SELECT COUNT(cust_email)FROM customers;
MAX()返回指定列中的最大值。每个产品有唯一的 ID(prod_id 列),并且借助 vend_id(供应商的唯一 ID)与供应商相关联。HAVING 非常类似于 WHERE。例如,如果想搜索住在某个州的客户,怎么办?因为表数据并未按州排序,DBMS必须读出表中所有行(从第一行开始),看其是否匹配。
可以在索引中定义多个列(例如,州加上城市)。环境准备1、
- 使用 SELECT 检索表数据,必须至少给出两条信息——想选择什么,以及从什么地方选择。顾客 ID 为 Customers 表的主键,每个顾客都有唯一的ID。更新数据
-- UPDATE语法UPDATE [表名]SET [列名] = [新值] -- 多个列之间用,分隔。
# 检索products表中所有列SELECT *FROM products;
- 检索单个列不同值:使用 DISTINCT 关键字,顾名思义,它指示数据库只返回不同的值。这些函数一般主要用于代数、
# “distinct” 主要取“不同的;有区别的”这个意思,用于筛选出独一无二的数据# 在products表中检索不同的vend_idSELECT DISTINCT vend_id FROM products;
- 限制结果:LIMIT限制行数,OFFSET指定从第几行开始(0是第一行)
# 限制第6行起步的5行数据,OFFSET指定跳过前几行SELECT prod_nameFROM productsLIMIT 5 OFFSET 5;# 简化的语句,逗号之前的值对应 OFFSET,逗号之后的值对应 LIMIT。这样,如果需要回退,可以回退到某个占位符。
你可能听到用户在提到行时称其为数据库记录(record)。-- 各家DBMS的日期和时间格式各不相同,具体看各家的情况-- 返回2005年的订单-- MySQL 具有各种日期处理函数,但没有 DATEPART()。
数据库管理系统(DBMS):
- 人们通常用数据库这个术语来代表他们使用的数据库软件,确切地说,数据库软件应称为数据库管理系统(DBMS)。类似地,DISTINCT 必须使用列名,不能用于计算或表达式。
3、DISTINCT 不能用于 COUNT(*)。
DECLARE XX INT;:声明一个局部变量 XX,类型为 INT,可指定默认值;DECLARE用于声明变量,SET XX = 用于变量赋值END //:存储过程的结束。订单物品用 order_num 列(关联到 Orders 表中订单的唯一 ID)与其相应的订单相关联。使索引有用的因素是什么?很简单,就是恰当的排序。大多数 DBMS 提供了可用来确定索引效率的实用程序,应该经常使用这些实用程序。
例如前面描述的添加订单的过程就是一个事务。列等;
DML(Data Manipulation Language):数据操作语言,用来对数据库记录(数据)操作;DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别;TLC(Transaction Control Language):事务控制语言,用来管理数据库事务。说明:MySQL 支持
如果使用 MySQL,应该知道对子查询的支持是从 4.1 版本引入的。
UPDATE employeesSET salary = salary + ( SELECT adjustment_amount FROM salary_adjustments sa WHERE sa.employee_id = employees.employee_id)WHERE EXISTS ( -- 可以使用尝试IN SELECT 1 -- 1只是习惯,EXISTS过滤掉那些没有返回行的数据 FROM salary_adjustments sa WHERE sa.employee_id = employees.employee_id);
4、
Orders 表中顾客 ID 列的值不一定是唯一的。没有主键,要安全地 UPDATE 或 DELETE 特定行而不影响其他行会非常困难。修改和删除的性能。
-- 表别名,与列或者计算字段别名不同,在FROM中进行-- 联结多个表,查找20005号订单的各个产品名、SQL语言简述1、参数可有多个,类型可为IN, OUT, INOUT中的一个
BEGIN:存储过程的开始。 %m:代表月份,范围是 01 - 12。database_name.table_name
(表示某个数据库的某个表)等。ON用于指定联结的条件,是在联结之前进行,WHERE只起到过滤的作用,在联结之后进行联结多个表,查找20005号订单的各个产品名、SELECT prod_name, prod_priceFROM productsWHERE prod_name LIKE '%'; -- 在针对邮箱应用场景十分实用SELECT cust_name,cust_emailFROM customersWHERE cust_email LIKE '%@coyote.com'; _通配符:只匹配单个字符,而不是多个字符。DCL(Data Control Language):数据控制语言
1、使用MYSQL存储过程
(1)存储过程的创建
(2)定义存储过程
(3)执行存储过程
3、
没有严格的规则要求什么应该索引,何时索引。
数据类型:所允许的数据的类型。
-- WHERE方式SELECT cust_name, cust_contact, cust_emailFROM customersWHERE cust_state IN ('MI', 'IN', 'OH') OR cust_name = 'Wascals'ORDER BY cust_name; -- UNION方式,UNION默认自带DISTINCT,想要显示所有结果加上ALL-- 并集时默认去掉重复行SELECT cust_name, cust_contact, cust_emailFROM customersWHERE cust_state IN ('MI', 'IN', 'OH')UNION -- ALLSELECT cust_name, cust_contact, cust_emailFROM customersWHERE cust_name = 'Wascals';ORDER BY cust_name;
使用UNION的规则:
CREATE INDEX prod_name_ind ON Products (prod_name);
索引必须唯一命名。如果没有错误发生,整组语句提交给(写到)数据库表;如果发生错误,则进行回退(撤销),将数据库恢复到某个已知且安全的状态
关于事务处理的几个术语:
事务(transaction)指一组 SQL 语句;
回退(rollback)指撤销指定 SQL 语句的过程;
提交(commit)指将未存储的 SQL 语句结果写入数据库表;
保留点(savepoint)指事务处理中设置的临时占位符(placeholder),可以对它发布回退(与回退整个事务处理不同)。
-- STR_TO_DATE(str,format)函数可将字符串转换为日期格式,从而利用between关键字依旧可以实现相应功能/* %Y:代表 4 位年份,例如 2025。UPDATE
(更新数据)、不需要依赖于客户端应用程序或用户来保证正确获取它,DBMS 本身将会拒绝任何无效的数据。更新数据4、Default、用户账户管理
(1)创建用户
(2)修改用户密码
(3)查看用户权限
(4)删除用户
六、
以下是完整的存储过程代码:
DELIMITER // CREATE PROCEDURE UseCursor()BEGIN DECLARE done INT DEFAULT FALSE; DECLARE email VARCHAR(255); -- 假设你要获取的变量类型是VARCHAR,根据实际表结构调整 DECLARE CustCursor CURSOR FOR SELECT cust_email -- 这里只选择你需要的列,避免使用SELECT * FROM Customers WHERE cust_email IS NOT NULL; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 打开游标 OPEN CustCursor; read_loop: LOOP -- FETCH 语句检索一行并保存值到这些变量中 FETCH CustCursor INTO email; IF done THEN LEAVE read_loop; END IF; -- 在这里可以进行相应的处理,例如打印或者存储到其他表中 SELECT email; -- 输出处理后的数据 END LOOP; -- 关闭游标 CLOSE CustCursor;END // DELIMITER ; CALL UseCursor();
九、权限管理基础
(1)授予权限(GRANT)
(2)撤销权限(REVOKE)
2、通配符搜索只能用于文本字段(字符串)
谓词(predicate)
- 从技术上说,LIKE是谓词而不是操作符。虽然最终的结果是相同的,但许多 DBMS 处理联结远比处理子查询快得多。
字段基本与列相同,经常互换使用
创建由两列组成的标题。
在事务处理块中,提交不会隐式进行。调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是很有好处的。通配符或两者组合构成的搜索条件。不需要每次读取一行再将它用 INSERT 插入,可以如下进行:(先将原来的customers表复制一份结构取名为CustNew)
-- INSERT + SELECT:将检索的数据插入表--插入多行INSERT INTO CustNew(cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) SELECT cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country FROM customers;
提示:INSERT SELECT 中的列名填充顺序
为简单起见,这个例子在INSERT和SELECT语句中使用了相同的列名。 每 个 订 单 唯 一 编 号(order_num 列)。
SELECT MIN(prod_price) AS min_price FROM Products; 其中 MIN()返回 Products 表中最便宜物品的价格。/*从 products 表中检索prod_name, prod_price但不返回所有行,只返回prod_price 值为 10 的行*/SELECT prod_name, prod_priceFROM productsWHERE prod_price = 10; -- SQL语句中没有赋值的概念,大胆使用=符号
- WHERE子句操作符

-- 列出所有价格小于 10 美元的产品。用户账户管理(1)创建用户
语法:CREATE USER 'username'@'host' IDENTIFIED BY 'password';
- 创建一个名为
new_user
的用户,允许从本地连接,密码为 123456
。CREATE TABLE OrderItems ( order_num INTEGER NOT NULL, order_item INTEGER NOT NULL, prod_id CHAR(10) NOT NULL, quantity INTEGER NOT NULL CHECK (quantity > 0), item_price MONEY NOT NULL );
利用这个约束,任何插入(或更新)的行都会被检查,保证 quantity大于 0。
(1)SELECT检索数据
# 检索products表中的prod_name单列SELECT prod_name FROM products;
# 检索products表prod_id, prod_name, prod_price多列SELECT prod_id, prod_name, prod_priceFROM products;
- 检索所有列: 在实际列名的位置使用星号(*)通配符可以做到这点,如下所示。
列(column):表中的一个字段。
2、这个过程实际上没有检索数据,它只是定义要使用的 SELECT 语句和游标选项。计算或格式化过的数据,计算字段是运行时在 SELECT 语句内创建的。学过的这些有关 WHERE 的所有技术和选项都适用于 HAVING。
- 应用程序一般不使用日期和时间的存储格式(可能直接使用的字符串),因此日期和时间函数总是用来读取、
与存储过程不一样(存储过程只是简单的存储 SQL 语句),触发器与单个的表相关联。如果发生错误,只需要返回到添加 Orders 行之前即可。这样的索引仅在以州加城市的顺序排序时有用。换句话说,表中的一列(或多个列)的值唯一标识表中的每一行。简单说,联结是一种机制,用来在一条 SELECT 语句中关联表,因此称为联结。什么是事务处理
使用事务处理(transaction processing),通过确保成批的 SQL 操作要么完全执行,要么完全不执行,来维护数据库的完整性。
- 数据库是一个以某种有组织的方式存储的数据集合。这是一个重要的区别,WHERE 排除的行不包括在分组中。也就是自己指定检索出的列名。
- 计算计算列的值或更新时间戳。 如果数据存储在多个表中,怎样用一条 SELECT 语句就检索出数据呢?
答案是使用联结。对于检索出来的数据进行查询操作。
具有讽刺意味的是,在主要 DBMS 的函数中,数值函数是最一致、删除数据-- DELETE语法DELETE FROM [表名]WHERE [过滤条件];
-- DELETE 删除表中的行数据,尽量加上FROM,保持可移植性DELETE FROM Customers WHERE cust_id = '10006';
DELETE不指定过滤条件就会删除所有行
TRUNCATE 其实属于 DDL 语句,因为它是先 DROP TABLE,再 CREATE TABLE。
- 更糟的是,如果系统在添加 OrderItems 行之时出现故障,怎么办?结果是数据库中存在不完整的订单,而你还不知道。DBMS 搜索排过序的索引,找出匹配的位置,然后检索这些行。
-- 唯一约束ALTER TABLE XXXADD CONSTRAINT UNIQUE (XXX);-- 删除唯一约束,唯一约束是以索引方式创建的ALTER TABLE XXXDROP INDEX XXX;
(4)检查约束
检查约束用来保证一列(或一组列)中的数据满足一组指定的条件。
- 任意两行的主键值都不相同。在 MySQL中需要使用CONCAT函数。
-- 求所有产品平均价格SELECT AVG(prod_price) AS avg_priceFROM products; -- 求供应商是1002的所有产品均价,获取多列的平均值必须使用多个avg函数SELECT AVG(prod_price) AS avg_price, MAX(prod_id) AS max_idFROM productsWHERE vend_id = 1002; -- WHERE子句仅过滤出vend_id为1002的行
COUNT()函数进行计数。 %s:代表秒,范围是 00 - 59。一般通过对一个表使用通配符(SELECT *),而对其他表的列使用明确的子集来完成。控制事务处理:
(1)事务的开始和结束
(2)回滚事务
(3)使用COMMIT
(4)使用保留点 SAVEPOINT
(5)结合存储过程的完整事务例子(存储过程后面介绍)
七、
- 并非所有数据都适合做索引。
-- 自然联结,想要消除内联结导致重复的列,系统无法做到,只能人工完成-- 需要列出订购物品号 ANV01 的所有顾客的信息,包括订单信息,但不重复列SELECT C.*, O.order_num, O.order_date, OI.order_item, OI.prod_id, OI.item_price, OI.quantityFROM orders AS O INNER JOIN orderitems AS OI INNER JOIN customers AS CON OI.prod_id = 'ANV01' AND OI.order_num = O.order_num AND O.cust_id = C.cust_id;-- 把ON换成WHERE效果是一样的,但是进行联结的时候不一样哦-- WHERE是对联结的结果进行过滤,ON是在联结前设置条件
-- 使用 BETWEEN 操作符,它检索价格在 5 美元和 10 美元之间的所有产品。这里的索引名 prod_name_ind 在关键字 CREATE INDEX 之后定义。user
:要撤销权限的用户,格式与 GRANT
中的 user
相同。为此,必须基于完整的分组而不是个别的行进行过滤。这个过程用前面定义的 SELECT语句把数据实际检索出来。collation_name:新的排序规则,例如 utf8mb4_unicode_ci。进行明确的提交,使用 COMMIT 语句。例如,防止 0 个物品的订单(即使 0 是合法的数)。
(3)Customers 表
Customers 表存储所有顾客信息。
解决方法是使用索引。KEY、
因为使用了 GROUP BY,就不必指定要计算和估值的每个组了。
经过前面的练习,不难知道联结之后的结果难免出现相同的列,自然联结就是排除列的多次出现,使得每列只返回一次。
DECLARE 命名游标,并定义相应的 SELECT 语句,根据需要带 WHERE 和其他子句。RIGHT(str,len)函数、
- 为在搜索子句中使用通配符,必须使用 LIKE 操作符。操作存储过程
DELIMITER //CREATE PROCEDURE procedure_name ([IN | OUT | INOUT] parameter_name data_type, ...)BEGIN -- 存储过程主体,可包含各类 SQL 语句 sql_statements;END //DELIMITER ;-- 对邮件发送清单中具有邮件地址的顾客进行计数DELIMITER //CREATE PROCEDURE MailingListCount(OUT ListCount INT) BEGIN DECLARE v_rows INT; SELECT COUNT(*) INTO v_rows FROM customers WHERE cust_email IS NOT NULL; SET ListCount = v_rows; END //DELIMITER ;
DROP PROCEDURE IF EXISTS procedure_name;
四、SQL的分类
employees 表是一个使用约束的例子。
下面想通过COUNT函数通过orderitems表统计总共有多少个订单。设计良好的数据库模式表之间都是关联的。DDL(Data Definition Language):数据定义语言
创建:CREATE + [数据库 | 表 | 视图 | ...] + name
删除:DROP + [数据库 | 表 | 视图 | ...] + name
修改:ALTER + [数据库 | 表 | 视图 | ...] + name
1、
主键值不能重用。MySQL 5 以上支持在存储过程中使用CURSOR
2、-- 如果我想统计供应商为1001的产品均价,用where子句过滤就行了SELECT AVG(prod_price)FROM productsWHERE vend_id = 1001;
但是我想统计所有供应商的产品均价呢,还要去一个一个写吗?
这时候就要用到分组了。使用存储过程(函数)
1、
下面的例子创建一个触发器,它对所有 INSERT 和 UPDATE 操作,将Customers 表中的 cust_state 列转换为大写。这就是所谓的隐式提交(implicit commit),即提交(写或保存)操作是自动进行的。
创建表时定义主键:为列添加 PRIMARY KEY 关键字
CREATE TABLE Vendors ( vend_id CHAR(10) NOT NULL PRIMARY KEY, vend_name CHAR(50) NOT NULL, vend_address CHAR(50) NULL, vend_city CHAR(50) NULL, vend_state CHAR(5) NULL, vend_zip CHAR(10) NULL, vend_country CHAR(50) NULL );
修改表时添加主键:ADD CONSTRAINTPRIMARY KEY (vend_id)
ALTER TABLE Vendors ADD CONSTRAINT PRIMARY KEY (vend_id);
(2)外键
外键是表中的一列,其值必须列在另一表的主键中。
SELECT prod_name, prod_price, vend_idFROM productsWHERE vend_id IN (1001, 1002);-- NOT 关键字可以用在要过滤的列前,而不仅仅是在其后。因此,每个雇员除了其社会安全号外还有唯一的雇员 ID(主键)。这方便了直接或交互地处理表中的行。列级别和存储过程级别等。唯一约束的语法类似于其他约束的语法。SELECT prod_id, prod_price, prod_name FROM products ORDER BY 2 DESC, 3 ASC;
(3)过滤数据--WHERE子句
使用过滤时,可以看作是将表中的每一行与过滤条件进行对比,满足条件才会被检索出来。% 和 _搜索模式(search pattern) :由字面值、检查约束的常见用途有以下几点。
- 授予用户
test_user
在 mysql数据库的所有表上的 SELECT
和 INSERT
权限:
-- 这里先创建了用户,语法后面说CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'langxi';GRANT SELECT,INSERT ON mysql.* TO 'test_user'@'localhost';
- 授予用户
admin_user
在所有数据库的所有表上的所有权限,并允许其将权限授予其他用户:
CREATE USER 'admin_user'@'localhost' IDENTIFIED BY 'langxi';GRANT ALL PRIVILEGES ON *.* TO 'admin_user'@'localhost' WITH GRANT OPTION;
(2)撤销权限(REVOKE)
撤销权限语法:
REVOKE privileges ON object FROMuser;
/* ABS(X)、什么是游标2、存储过程的管理
八、数据库是通过 DBMS 创建和操纵的容器,而具体它究竟是什么,形式如何,各种数据库都不一样。然后再翻到这些页,找出“数据类型”一词。如果将表想象为网格,网格中垂直的列为表列,水平行为表行。
模式(schema):关于数据库和表的布局及特性的信息。
但是,搜索其他列中的值通常效率不高。系统会自动完成。在MySQL 中创建占位符,可使用 SAVEPOINT 语句。
数据库索引的作用也一样。事务处理是一种机制,用来管理必须成批执行的 SQL 操作,保证数据库不包含不完整的操作结果。如果从表中删除某一行,其主键值不分配给新行。
(2)定义存储过程
对邮件发送清单中具有邮件地址的顾客进行计数
-- 对邮件发送清单中具有邮件地址的顾客进行计数DELIMITER //CREATE PROCEDURE MailingListCount(OUT ListCount INT) BEGIN DECLARE v_rows INT; SELECT COUNT(*) INTO v_rows FROM customers WHERE cust_email IS NOT NULL; SET ListCount = v_rows; END //DELIMITER ;
(3)执行存储过程
CALL MailingListCount(@ListCount);SELECT @ListCount AS ListCount;
3、触发器
触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行。
CREATE USER 'new_user'@'localhost' IDENTIFIED BY '123456';
(2)修改用户密码
语法:ALTER USER 'username'@'host' IDENTIFIED BY 'new_password';
存储过程就类似于Java中的方法,需要先定义,使用时需要调用。INOUT三种类型。触发器可以与特定表上的 INSERT、别名用 AS 关键字赋予SELECT CONCAT(vend_name, ' (', vend_country, ')') AS vend_titleFROM Vendors ORDER BY vend_name;

现在我们要计算出订单号为20008的订单总金额,就需要使用到算术计算了,创建出新的字段进行别名,从而让客户端能够使用该列。prod_price:
SELECT vend_name, prod_name, prod_priceFROM vendors, productsWHERE vendors.vend_id = products.vend_id;-- 联结的操作在FROM中执行,连接后(笛卡尔积)有6*14行,再经过WHERE进行过滤
上面使用叉联结+WHERE过滤后的结果与等值联结的结果相同。但是,不一定要求列名匹配。例如,在性别字段中只允许 M 或 F。
WHERE和HAVING一起使用:-- 列出具有两个及以上产品且其价格大于等于 4 的供应商id:
-- WHERE和having的一起使用SELECT vend_idFROM productsWHERE prod_price >= 4GROUP BY vend_idHAVING COUNT(prod_name) >= 2;
数据进行分组后,可以使用ORDER BY 对分组进行排序,注意是对分组进行排序而不是针对行进行排序
检索包含三个或更多物品的订单号和订购物品的数目,要按订购物品的数目和订单号降序排序输出
-- 检索包含三个或更多物品的订单号和订购物品的数目-- 要按订购物品的数目和订单号降序排序输出SELECT order_num, COUNT(*) AS itemsFROM orderitemsGROUP BY order_numHAVING COUNT(order_item) >= 3ORDER BY items DESC, 1 DESC;
(8)SELECT使用子查询
SELECT 语句是 SQL 的查询。
在上述例子中,联结包含了那些在相关表中没有关联行的行。约束
(1)主键
(2)外键
(3)唯一约束
(4)检查约束
2、日期和时间值以特殊的格式存储,以便能快速和有效地排序或过滤,并且节省物理存储空间。例如,在 INSERT 或 UPDATE 操作中将所有州名转换为大写。*/SELECT * FROM orders WHERE order_date BETWEEN STR_TO_DATE('2005-09-01','%Y-%m-%d') AND STR_TO_DATE('2005-09-30','%Y-%m-%d');
数值处理函数仅处理数值数据。也就是只能对最终的结果进行排序。约束
约束(constraint):管理如何插入或处理数据库数据的规则。
(2) Products 表
Products 表包含产品目录,每行一个产品。什么是事务处理
2、是否NULL、查询数据
(1)SELECT检索数据
(2)ORDER BY 对检索数据排序
(3)过滤数据--WHERE子句
(4)创建计算字段
(5)使用函数处理数据
(6)汇总数据--聚集函数的使用
(7)分组数据--GROUP BY和HAVING子句
(8)SELECT使用子查询
(9)MySQL中的表联结
(10)MySQL组合查询
2、常见的权限有 SELECT
(查询数据)、
- 撤销用户
test_user
在 mysql 数据库的所有表上的 INSERT
权限:
REVOKE INSERT ON mysql.* FROM 'test_user'@'localhost';
- 撤销用户
admin_user
在所有数据库的所有表上的所有权限:
REVOKE ALL PRIVILEGES ON *.* FROM 'admin_user'@'localhost';
2、-- DELETE 删除表中的行数据,尽量加上FROM,保持可移植性DELETE FROM Customers;-- 或者TRUNCATE TABLE orders_new;
五、结果集(result set):SQL 查询所检索出的结果。right join
许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行。
/* ALL和DISTINCT参数在聚集函数中的作用 聚集不同值,上述中会对过滤后的数据中不为NULL的列值进行汇总,其实默认有一个ALL参数 对于相同的值可能不需要汇总,比如我想在orderitem中查看有多少个订单 聚集不同的值就需要使用DISTINCT参数*/SELECT COUNT(ALL order_num) -- 11个,有重复订单FROM orderitems; SELECT COUNT(DISTINCT order_num) -- 5个,无重复订单FROM orderitems;
注意:DISTINCT 不能用于 COUNT(*)
如果指定列名,则 DISTINCT 只能用于 COUNT()。
对于填有数据的游标,根据需要取出(检索)各行。根据所使用的 DBMS的不同,触发器可在特定操作执行之前或之后执行。-- SQL 支持列别名。
SELECT COUNT(*) AS num_items, MIN(prod_price) AS price_min, MAX(prod_price) AS price_max, AVG(DISTINCT prod_price) AS price_avg FROM Products;
(7)分组数据--GROUP BY和HAVING子句
为何要分组?比如我想统计供应商为1001的产品均价,用where子句过滤然后使用AVG即可。操作表
-- 列名 数据类型 NULL 默认值 约束(主键、
这里使用vend_title替换原默认计算字段名。例如,保证发货日期大于等于今天的日期,但不超过今天起一年后的日期。主键数据总是排序的,这是 DBMS 的工作。
那么,怎么过滤分组呢?请看以下的例子:
-- 过滤供应商的产品种类少于 3 的分组(过滤的是分组而不是行哦)
-- HAVING过滤分组,WHERE过滤行-- 过滤产品种类少于3的分组SELECT vend_id, AVG(prod_price) AS avg_priceFROM productsGROUP BY vend_idHAVING COUNT(prod_name) < 3
说明:HAVING 和 WHERE 的差别
这里有另一种理解方法,WHERE 在数据分组前进行过滤,HAVING 在数据分组后进行过滤。表级别、1 个或多个字符。
那么,不使用 WHERE 使用什么呢?SQL 为此提供了另一个子句,就是HAVING 子句。WHERE prod_price > 5;
CREATE OR REPLACE VIEW CustomerEMailList AS SELECT cust_id, cust_name, cust_email FROM Customers WHERE cust_email IS NOT NULL;
DROP VIEW [IF EXISTS] view_name [, view_name] ...;DROP VIEW IF EXISTS CustomerEMailList;
4、计算字段等方式
在update中使用子查询,使用子查询检索出的数据更新列数据
表结构:
employees表:
employee_id:员工编号(主键)
salary:员工工资
salary_adjustments表:
employee_id:员工编号
adjustment_amount:工资调整金额
目标是根据salary_adjustments表中的调整金额更新employees表中的员工工资。某些顾客没有订单是完全合法的。可如下检索所订购物品的总数(所有 quantity 值之和):
-- 统计订单号为20005的所有物品个数SELECT SUM(quantity) AS prod_quantityFROM orderitemsWHERE order_num = 20005;
SUM()也可以用来合计计算值。
只允许特定的值。与 Orders 表上的 INSERT 操作相关联的触发器只在Orders 表中插入行时执行。START TRANSACTION; UPDATE customersSET cust_name = 'zhangsan'WHERE cust_id = 10012; UPDATE customersSET cust_name = 'lisi'WHERE cust_id = 10013; COMMIT;(2)回滚事务
回滚:回到事务开始前的状态,也就是结束掉本次事务的生命周期
ROLLBACK;
-- 回滚事务 START TRANSACTION;-- 删除某行DELETE FROM customersWHERE cust_id = 10012; -- 删除后已经查找不到该ID了SELECT cust_idFROM customersWHERE cust_id = 10012; -- 回滚:回到事务开始前的状态,也就是结束掉本次事务的生命周期ROLLBACK; -- 回滚后可查到该idSELECT cust_idFROM customersWHERE cust_id = 10012;
(3)使用COMMIT
一般的 SQL 语句都是针对数据库表直接执行和编写的。SELECT prod_name, prod_priceFROM productsWHERE prod_price BETWEEN 5 AND 10; -- 使用时必须指定两个值,用AND连接,并且是闭区间
-- 返回所有没有价格(空 prod_price 字段,不是价格为 0)的产品SELECT prod_name, prod_priceFROM productsWHERE prod_price IS NULL;
- 组合条件--AND和OR操作符 :AND优先级更高
-- 在处理 OR 操作符前,优先处理 AND 操作符-- 这里对于1002的供应商就会显示所有产品SELECT prod_name, prod_price, vend_idFROM productsWHERE vend_id = 1002 OR vend_id = 1001 AND prod_price <= 6;
IN 取一组由逗号分隔、
在结束游标使用时,必须关闭游标,可能的话,释放游标(有赖于具体的 DBMS)。包含主键值的列从不修改或更新。唯一约束列的值可重复使用。如果想按城市排序,则这种索引没有用处。例如,顾客表可以每行存储一个顾客。与 DESC 相对的是 ASC(或 ASCENDING),在升序排序时可以指定它。唯一的差别是,WHERE过滤行,而 HAVING 过滤分组。在这个例子中,在 Orders 的顾客 ID 列上定义了一个外键,因此该列只能接受 Customers 表的主键值。要支持回退部分事务,必须在事务处理块中的合适位置放置占位符。别名(alias)是一个字段或值的替换名。准备好的表和数据文件:(表也可以在评论区获取源码)
百度网盘链接: 百度网盘 请输入提取码
提取码: fpnx
各表的简单描述如下,详细请运行SQL文件查看。
- 在使用游标前,必须声明(定义)它。在更新多个列时,只需要使用一条 SET 命令WHERE [过滤条件];
-- 10005现在有了邮箱值kim@thetoystore.com,请更新UPDATE customersSET cust_email = 'kim@thetoystore.com'WHERE cust_id = '10005';-- 不加where进行过滤的后果就是会更新所有行的cust_email列值为'kim@thetoystore.com'-- 更改多个列值,只需要在列名+值之间以逗号分隔-- 对于表的操作,都可以叫做查询,使用UPDATE时也会读取表的内容以进行过滤等操作UPDATE customersSET cust_email = 'kim@thetoystore.com', cust_country = 'China'WHERE cust_id = '10005';
- SET支持子查询、SQL 是一种专门用来与数据库沟通的语言。什么是游标
SQL 检索操作返回一组称为结果集的行,这组返回的行都是与 SQL 语句相匹配的行(零行或多行)。
关键字(keyword):作为 SQL 组成部分的保留字。插入数据
3、OUT、订单号为 Orders 表的主键,每个订单都有唯一的订单号。描述表的这组信息就是所谓的模式(schema),模式可以用来描述数据库中特定的表,也可以用来描述整个数据库(和其中表的关系)。Extra,这些都是约束

(1)主键
主键是一种特殊的约束,用来保证一列(或一组列)中的值是唯一的,而且永不改动。INSERT
(插入数据)、
%通配符:代表搜索模式中给定位置的 0 个、DML(Data Manipulation Language):数据操作语言1、
使用子查询的情景:
- 找到包含物品 ANV01 的订单号
- 根据订单号找到顾客的ID
- 根据顾客的ID查找顾客的信息
不使用子查询,一步一步做:
-- 先找到有订购 ANV01 的订单号SELECT order_numFROM orderitemsWHERE prod_id = 'ANV01';-- 20005 -- 在找到该订单号的所有顾客idSELECT cust_idFROM ordersWHERE order_num IN (20005);-- 10001 -- 最后根据顾客id返回顾客的信息SELECT cust_name, cust_contactFROM customersWHERE cust_id IN (10001);
这里使用子查询是如何呢?就是在过滤时以子查询的结果作为过滤的条件:
-- 使用子查询SELECT cust_name, cust_contactFROM customersWHERE cust_id IN (SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id = 'ANV01');
先执行最内的子查询,最后才执行最外层的查询。其核心操作包括授予权限(GRANT)、 %d:代表一个月中的第几天,范围是 01 - 31。遗憾的是,它们很不一致,可移植性最差。CREATE
(创建数据库对象)、GROUP BY 子句指示 DBMS 分组数据,然后对每个组而不是整个结果集进行聚集。索引
(1)什么是索引,为什么使用索引
(2)创建索引
3、TLC(Transaction Control Language):事务控制语言
1、 %H:代表小时(24 小时制),范围是 00 - 23。企图检索多个列将返回错误。
2、查询数据
SELECT:是从一个或多个表中检索信息。
-- mysql的拼接只支持concat函数,不支持+或者||符号SELECT vend_name + ' (' + vend_country + ')' FROM Vendors ORDER BY vend_name; -- 列名不要加'',自己增加的某些字符或者字符串才用''包住SELECT CONCAT(vend_name, ' (', vend_country, ')')FROM Vendors ORDER BY vend_name;

RTRIM()(去掉字符串右边的空格);
LTRIM()(去掉字符串左边的空格);
TRIM()(去掉字符串左右两边的空格)
SELECT CONCAT(TRIM(vend_name), ' (', vend_country, ')')FROM Vendors ORDER BY vend_name;
这里可以看到字段名为我们的函数及其参数,很难看。
COMMIT; -- 提交本次事务的操作
(4)使用保留点 SAVEPOINT
使用简单的 ROLLBACK 和 COMMIT 语句,就可以写入或撤销整个事务。在执行这些操作时,DBMS 必须动态地更新索引。这种联结称为外联结。*/
2、