第19章 插入数据
一、数据插入概述
INSERT语句用于向数据库表中插入(添加)数据,是SQL中常用的数据操作语句之一。它可以用多种方式使用,包括插入完整的行、插入行的一部分、插入多行以及插入某些查询的结果。同时,MySQL的安全机制可针对每个表或每个用户禁止使用INSERT语句,以保障数据的安全性。
二、插入完整的行
- 基本语法与问题:使用基本的INSERT语法插入完整的行时,需要指定表名和被插入到新行中的值。例如:
INSERT INTO Customers VALUES (NULL, 'Pep E.LaPew', '100 Main Street', 'Los Angeles', 'CA', 'USA', '90046', NULL, NULL);
此语句向customers表插入一个新客户,但这种方式高度依赖于表中列的定义次序,若表结构发生变化,列的顺序改变,该语句可能会出错。因此,这种语法并不安全,应尽量避免使用。
2. 更安全的插入方式:为确保代码的稳定性,编写INSERT语句时应明确列出列名。例如:
INSERT INTO customers (cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES ('Pep E.LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', NULL, NULL);
这种方式下,VALUES列表中的值会按指定的列名顺序进行填充,即使表结构改变,只要列名存在,该语句仍能正确工作。同时,使用这种语法还可以省略某些列,前提是这些列允许NULL值或在表定义中有默认值。
3. VALUES的正确使用:无论使用哪种INSERT语法,都必须确保VALUES提供的数值数量正确。若不提供列名,则必须给每个表列提供一个值;若提供列名,则必须对每个列出的列给出一个值,否则会产生错误消息,导致行插入不成功 。
4. 降低INSERT优先级:由于INSERT操作可能会影响数据库性能,特别是在有很多索引需要更新时,会降低等待处理的SELECT语句的性能。若数据检索是首要任务,可以在INSERT和INTO之间添加关键字LOW_PRIORITY,指示MySQL降低INSERT语句的优先级 。例如:
INSERT LOW_PRIORITY INTO customers (cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES ('New Customer', 'Some Address', 'Some City', 'Some State', '12345', 'Some Country');
三、插入多个行
- 多条INSERT语句方式:可以使用多条INSERT语句插入多个行,每条语句用分号结束,并且可以一次提交这些语句。例如:
INSERT INTO customers (cust_name, cust_city, cust_state, cust_address, cust_zip, cust_country)
VALUES ('Pep E.LaPew', 'Los Angeles', 'CA', '100 Main Street', '90046', 'USA');
INSERT INTO customers (cust_name, cust_city, cust_state, cust_address, cust_zip, cust_country)
VALUES ('M.Martian', 'New York', 'NY', '42 Galaxy Way', '11213', 'USA');
- 组合INSERT语句方式:当每条INSERT语句中的列名(和次序)相同时,可以将多个插入操作组合在一条INSERT语句中。例如:
INSERT INTO customers (cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES ('Pep E.LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA'),
('M.Martian', '42 Galaxy Way', 'New York', 'NY', '11213', 'USA');
这种方式可以提高数据库处理的性能,因为MySQL用单条INSERT语句处理多个插入比使用多条INSERT语句更快。
四、插入检索出的数据
- INSERT SELECT语法:INSERT SELECT用于将一条SELECT语句的结果插入到表中。例如,将custnew表中的数据导入到customers表中:
INSERT INTO customers (cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
SELECT cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country
FROM custnew;
在这个例子中,SELECT语句从custnew表检索出要插入的值,插入的行数取决于custnew表中的行数。如果custnew表为空,则不会插入任何行,但操作仍然合法。
2. 列名与WHERE子句:在INSERT SELECT中,不一定要求INSERT和SELECT语句中的列名匹配,MySQL会根据列的位置进行插入。同时,SELECT语句可包含WHERE子句以过滤插入的数据。例如,只插入custnew表中特定条件的数据:
INSERT INTO customers (cust_name, cust_city, cust_state)
SELECT cust_name, cust_city, cust_state
FROM custnew
WHERE cust_state = 'CA';
五、小结
本章详细介绍了使用INSERT语句向数据库表中插入数据的多种方法,包括插入完整的行、插入多个行以及插入检索出的数据。强调了明确使用列名的重要性,以及不同插入方式对性能的影响。在实际应用中,应根据具体需求选择合适的插入方式,确保数据的准确插入和数据库的高效运行。
实战案例
- 实战数据准备
- 建表语句
-- 创建员工表
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
department VARCHAR(50),
salary DECIMAL(10, 2),
email VARCHAR(100)
);
-- 创建临时员工表,结构与员工表类似,用于测试数据插入
CREATE TABLE temp_employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
department VARCHAR(50),
salary DECIMAL(10, 2),
email VARCHAR(100)
);
- **插入数据语句(用于临时员工表,为后续测试做准备)**
INSERT INTO temp_employees (emp_name, department, salary, email)
VALUES ('Alice', 'HR', 5000.00, 'alice@example.com'),
('Bob', 'IT', 6000.00, 'bob@example.com'),
('Charlie', 'Finance', 5500.00, 'charlie@example.com');
- 题目与解析
- 题目1:插入完整的行:向employees表中插入一条新员工记录,员工名为David,部门为Marketing,薪水为4500.00,邮箱为david@example.com。
- 解析:使用明确列出列名的INSERT语法,确保数据准确插入。
- 脚本答案:
INSERT INTO employees (emp_name, department, salary, email)
VALUES ('David', 'Marketing', 4500.00, 'david@example.com');
- 题目2:插入多个行:向employees表中插入两条新员工记录,一条员工名为Eve,部门为Sales,薪水为4800.00,邮箱为eve@example.com;另一条员工名为Frank,部门为Sales,薪水为4700.00,邮箱为frank@example.com。
- 解析:使用组合INSERT语句方式,一次插入多条记录,提高插入效率。
- 脚本答案:
INSERT INTO employees (emp_name, department, salary, email)
VALUES ('Eve', 'Sales', 4800.00, 'eve@example.com'),
('Frank', 'Sales', 4700.00, 'frank@example.com');
- 题目 3:插入检索出的数据:将temp_employees表中部门为IT的员工数据插入到employees表中。
- 解析:利用INSERT SELECT语句,从temp_employees表中筛选出部门为IT的员工数据,并插入到employees表中。
- 脚本答案:
INSERT INTO employees (emp_name, department, salary, email)
SELECT emp_name, department, salary, email
FROM temp_employees
WHERE department = 'IT';
第20章 更新和删除数据
一、更新数据
- 1.1 UPDATE语句的用途与基本语法:UPDATE语句用于更新(修改)表中的数据,可更新表中特定行或所有行 。基本的UPDATE语句由三部分组成:要更新的表、列名和它们的新值、确定要更新行的过滤条件 。例如,更新customers表中客户10005的电子邮件地址:
UPDATE customers
SET cust_email = 'elmerefudd.com'
WHERE cust_id = 10005;
在这条语句中,UPDATE指定要更新的表为customers,SET用于设置新值,将cust_email列的值更新为elmerefudd.com,WHERE子句指定仅更新cust_id为10005的行。
2. 1.2 更新多个列的语法:更新多个列时,只需在SET命令后使用逗号分隔每个“列 = 值”对。例如,同时更新客户10005的cust_name和cust_email列:
UPDATE customers
SET cust_name = 'The Fudds',
cust_email = 'eTmerfudd.com'
WHERE cust_id = 10005;
- 1.3 在UPDATE语句中使用子查询:UPDATE语句中可以使用子查询,利用SELECT语句检索出的数据更新列数据 。这在需要根据其他表的数据来更新当前表时非常有用。例如,如果有一个new_emails表存储了新的电子邮件地址,且与customers表通过cust_id关联,可以使用以下语句更新customers表中的电子邮件地址:
UPDATE customers
SET cust_email = (SELECT new_email
FROM new_emails
WHERE customers.cust_id = new_emails.cust_id)
WHERE EXISTS (SELECT 1
FROM new_emails
WHERE customers.cust_id = new_emails.cust_id);
- 1.4 IGNORE关键字的使用:当使用UPDATE语句更新多行时,如果在更新过程中某一行或多行出现错误,默认情况下整个UPDATE操作会被取消,已更新的行将恢复到原来的值 。若希望即使发生错误也继续进行更新,可使用IGNORE关键字 。例如:
UPDATE IGNORE customers
SET cust_email = 'new_email@example.com'
WHERE cust_id IN (10001, 10002, 10003);
二、删除数据
- 2.1 DELETE语句的基本用法:DELETE语句用于从表中删除数据,可删除特定的行或所有行 。删除特定行时,需要使用WHERE子句指定过滤条件。例如,从customers表中删除客户10006:
DELETE FROM customers
WHERE cust_id = 10006;
这条语句中,DELETE FROM指定要删除数据的表为customers,WHERE子句确保仅删除cust_id为10006的行。如果省略WHERE子句,将删除表中的所有数据,因此使用时需格外小心。
2. 2.2 删除表的内容与表的区别:DELETE语句仅删除表中的行,不会删除表本身 。如果想删除表的所有内容,使用DELETE语句虽然可行,但从效率角度考虑,对于大数据量的表,使用TRUNCATE TABLE语句会更快,因为它实际上是删除原来的表并重新创建一个表,而不是逐行删除数据 。例如:
TRUNCATE TABLE customers;
- 2.3 设置列值为NULL:为删除某个列的值(前提是表定义允许NULL值),可使用UPDATE语句将该列设置为NULL。例如,去除customers表中客户10005的电子邮件地址:
UPDATE customers
SET cust_email = NULL
WHERE cust_id = 10005;
三、更新和删除的指导原则
- 3.1 使用WHERE子句的重要性:在使用UPDATE或DELETE语句时,除非确实打算更新或删除每一行,否则绝对不要使用不带WHERE子句的语句,以免误操作导致数据丢失或错误更新 。
- 3.2 主键的使用:保证每个表都有主键,并尽可能在WHERE子句中使用它来指定要操作的行。可以指定单个主键值、多个值或值的范围,这样能更准确地定位和操作数据 。
- 3.3 预先测试:在对UPDATE或DELETE语句使用WHERE子句前,应该先用SELECT进行测试,确保过滤的是正确的记录,避免编写错误的WHERE子句导致数据错误操作 。
- 3.4 引用完整性:使用强制实施引用完整性的数据库,这样MySQL将不允许删除具有与其他表相关联的数据的行,从而保证数据的一致性和完整性 。
四、小结
本章介绍了如何使用UPDATE和DELETE语句处理表中的数据,详细讲解了它们的语法、使用场景以及使用时的注意事项和指导原则。在实际操作中,务必谨慎使用这两条语句,以确保数据的准确性和安全性。
实战案例
- 实战数据准备
- 建表语句
CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(50),
price DECIMAL(10, 2),
stock INT
);
- **插入数据语句**
INSERT INTO products (product_name, price, stock)
VALUES ('Product A', 10.00, 50),
('Product B', 15.00, 30),
('Product C', 20.00, 20);
- 题目与解析
- 题目1:更新数据:将products表中product_id为1的产品价格提高20%,并减少库存5个。
- 解析:使用UPDATE语句,在SET子句中对price和stock列进行更新操作,通过WHERE子句指定要更新的行。
- 脚本答案:
UPDATE products
SET price = price * 1.2,
stock = stock - 5
WHERE product_id = 1;
- 题目2:删除数据:从products表中删除stock为0的产品记录。
- 解析:使用DELETE语句,通过WHERE子句过滤出stock为0的行进行删除。
- 脚本答案:
DELETE FROM products
WHERE stock = 0;
- 题目3:更新和删除的综合操作:先将products表中product_name为Product B的价格设置为NULL(假设表允许该列NULL值),然后删除价格为NULL的产品记录。
- 解析:分两步进行,第一步使用UPDATE语句将指定产品的价格设置为NULL,第二步使用DELETE语句删除价格为NULL的行。
- 脚本答案:
-- 更新操作
UPDATE products
SET price = NULL
WHERE product_name = 'Product B';
-- 删除操作
DELETE FROM products
WHERE price IS NULL;
第21章 创建和操纵表
一、创建表
1.1 创建表的方式:MySQL可通过两种方式创建表。一是使用具有交互式创建和管理表的工具,如MySQL Administrator、MySQL Query Browser等,这些工具会自动生成并执行相应的MySQL语句;二是直接使用MySQL的CREATE TABLE语句来创建表。
1.2 表创建基础:使用CREATE TABLE语句创建表时,必须指定新表的名字以及表列的名字和定义,各列之间用逗号分隔 。例如:
CREATE TABLE customers (
cust_id INT NOT NULL AUTO_INCREMENT,
cust_name CHAR(50) NOT NULL,
cust_address CHAR(50) NULL,
cust_city CHAR(50) NULL,
cust_state CHAR(5) NULL,
cust_zip CHAR(10) NULL,
cust_country CHAR(50) NULL,
cust_contact CHAR(50) NULL,
cust_email CHAR(255) NULL,
PRIMARY KEY (cust_id),
ENGINE=InnoDB
);
在上述代码中,CREATE TABLE后紧跟表名customers,表定义包含9列,每列定义以列名开头,后跟数据类型,PRIMARY KEY指定cust_id为主键列,ENGINE=InnoDB指定存储引擎。语句格式化时,可将长语句分成多行并适当缩进,以提高可读性。同时,创建新表时表名不能已存在,否则会出错;若想在表不存在时创建,可使用IF NOT EXISTS关键字。
1.3 使用NULL值:NULL值表示没有值或缺值。在创建表时,需定义每个表列是否允许NULL值。例如:
CREATE TABLE orders (
order_num INT NOT NULL AUTO_INCREMENT,
order_date DATETIME NOT NULL,
cust_id INT NOT NULL,
PRIMARY KEY (order_num),
ENGINE=InnoDB
);
在orders表中,3个列都定义为NOT NULL,这意味着插入行时这些列必须有值,否则插入失败。而在vendors表中:
CREATE TABLE vendors (
vend_id INT NOT NULL AUTO_INCREMENT,
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,
PRIMARY KEY (vend_id),
ENGINE=InnoDB
);
vend_name列不允许NULL值,其余部分列允许NULL值。需注意,NULL值与空串不同,空串是一个有效的值,而NULL值用关键字NULL指定。
1.4 主键再介绍:主键用于唯一标识表中的每一行,其值必须唯一。可以使用单个列作为主键,如前面例子中的cust_id、order_num、vend_id等;也可以使用多个列组成主键,例如:
CREATE TABLE orderitems (
order_num INT NOT NULL,
order_item INT NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INT NOT NULL,
item_price DECIMAL(8, 2) NOT NULL,
PRIMARY KEY (order_num, order_item),
ENGINE=InnoDB
);
在orderitems表中,order_num和order_item的组合作为主键,确保每个订单中的每个物品都有唯一标识。同时,主键中只能使用不允许NULL值的列。
1.5 使用AUTO_INCREMENT:AUTO_INCREMENT用于为表中的列自动生成唯一的序列值。例如,在customers表中:
cust_id INT NOT NULL AUTO_INCREMENT,
当每次执行INSERT操作时,MySQL会自动对cust_id列进行增量,赋予下一个可用的值。每个表只允许一个AUTO_INCREMENT列,且该列必须被索引(通常作为主键) 。若要在插入数据时获取自动生成的AUTO_INCREMENT值,可使用last_insert_id()函数 。例如:
INSERT INTO customers (cust_name) VALUES ('New Customer');
SELECT last_insert_id();
1.6 指定默认值:在创建表时,可以使用DEFAULT关键字为列指定默认值。例如:
CREATE TABLE orderitems (
order_num INT NOT NULL,
order_item INT NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INT NOT NULL DEFAULT 1,
item_price DECIMAL(8, 2) NOT NULL,
PRIMARY KEY (order_num, order_item),
ENGINE=InnoDB
);
在orderitems表中,quantity列的默认值被设置为1,这意味着在插入行时若未指定quantity的值,MySQL将使用默认值1 。需注意,MySQL不允许使用函数作为默认值,只支持常量。
1.7 引擎类型:MySQL具有多种数据库引擎,不同引擎有各自的功能和特性。常见的引擎有:
- InnoDB:是一个可靠的事务处理引擎,支持事务处理,但不支持全文本搜索。
- MEMORY:功能等同于MyISAM,数据存储在内存中,速度快,适合用于临时表。
- MyISAM:性能极高,支持全文本搜索,但不支持事务处理。
在创建表时,可通过ENGINE关键字指定引擎类型,如不指定,则使用默认引擎(通常是MyISAM)。例如:
CREATE TABLE products (
prod_id CHAR(10) NOT NULL,
-- 其他列定义...
PRIMARY KEY (prod_id),
ENGINE=InnoDB
);
同时要注意,外键不能跨引擎混用,在选择引擎时,需根据具体需求综合考虑。
二、更新表
2.1 ALTER TABLE语句的使用:使用ALTER TABLE语句可更新表的定义,如添加列、删除列、修改列的数据类型等。例如,给vendors表添加一个vend_phone列:
ALTER TABLE vendors
ADD vend_phone CHAR(20);
若要删除刚添加的列,可使用:
ALTER TABLE vendors
DROP COLUMN vend_phone;
ALTER TABLE的常见用途还包括定义外键。例如:
ALTER TABLE orderitems
ADD CONSTRAINT fk_orderitems_orders
FOREIGN KEY (order_num) REFERENCES orders (order_num);
使用ALTER TABLE时需谨慎,因为数据库表的更改通常不可撤销,可能会导致数据丢失或其他问题,所以在改动前最好进行完整备份。对于复杂的表结构更改,可能需要手动删除过程,涉及创建新表、复制数据、检验新表、重命名表等步骤。
三、删除表
删除表使用DROP TABLE语句,例如:
DROP TABLE customers2;
该语句将永久删除customers2表(假设表存在),删除操作没有确认步骤,执行后表将无法恢复,所以使用时需格外小心。
四、重命名表
使用RENAME TABLE语句可重命名一个表,例如:
RENAME TABLE customers2 TO customers;
也可以同时对多个表进行重命名,如:
RENAME TABLE backup_customers TO customers, backup_vendors TO vendors, backup_products TO products;
五、小结
本章介绍了MySQL中创建、更新、删除和重命名表的相关知识,包括CREATE TABLE、ALTER TABLE、DROP TABLE和RENAME TABLE等语句的使用,以及表的各种属性设置,如NULL值、主键、AUTO_INCREMENT、默认值和引擎类型等。在实际操作中,这些语句的使用需谨慎,以确保数据库表结构的正确管理和数据的安全。
实战案例
- 实战数据准备
- 建表语句:创建一个简单的students表,包含学生ID、姓名、年龄和所在班级列,并设置主键和默认值。
CREATE TABLE students (
student_id INT AUTO_INCREMENT PRIMARY KEY,
student_name VARCHAR(50) NOT NULL,
age INT DEFAULT 18,
class VARCHAR(20)
);
- 插入数据语句:插入几条测试数据。
INSERT INTO students (student_name, class) VALUES ('Alice', 'Class 1'), ('Bob', 'Class 2');
- 题目与解析
- 题目1:修改表结构:向students表中添加一个email列,数据类型为VARCHAR(100)。
- 解析:使用ALTER TABLE语句的ADD子句添加列。
- 脚本答案:
ALTER TABLE students
ADD email VARCHAR(100);
- 题目2:删除表中的列:从students表中删除age列。
- 解析:使用ALTER TABLE语句的DROP COLUMN子句删除列。
- 脚本答案:
ALTER TABLE students
DROP COLUMN age;
- 题目3:重命名表:将students表重命名为new_students。
- 解析:使用RENAME TABLE语句进行表重命名。
- 脚本答案:
RENAME TABLE students TO new_students;
- 题目4:删除表:删除new_students表。
- 解析:使用DROP TABLE语句删除表。
- 脚本答案:
DROP TABLE new_students;
第22章 使用视图
一、视图基础
1.1 视图的定义与作用:视图是虚拟的表,它不同于包含实际数据的表,仅包含使用时动态检索数据的查询。例如,在复杂的多表查询场景中,若经常需要从customers、orders和orderitems表中检索特定数据,可将相关查询创建为视图,简化数据检索操作。如创建一个名为productcustomers的视图:
CREATE VIEW productcustomers AS
SELECT cust_name, cust_contact, prod_id
FROM customers, orders, orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num = orders.order_num;
通过该视图,可轻松检索已订购任意产品的所有客户列表,后续使用时只需对视图进行查询,无需重复编写复杂的多表联结语句。
1.2 为什么使用视图:视图在数据库操作中有多种应用:
- 重用SQL语句:将常用的复杂查询封装为视图,避免重复编写相同的SQL代码,提高开发效率。
- 简化复杂的SQL操作:对于涉及多表联结、复杂过滤条件等操作,使用视图可隐藏底层查询细节,使数据检索更简单直观。
- 使用表的组成部分而不是整个表:可根据需求从表中选取特定列组成视图,只提供用户所需的数据,增强数据安全性和针对性。
- 保护数据:通过授予用户对视图的特定访问权限,限制用户对底层表数据的直接访问,从而保护敏感数据。
- 更改数据格式和表示:可对视图中的数据进行格式化处理,以满足不同的展示需求,而不影响底层表的数据存储格式。
二、视图的规则和限制
2.1 命名规则:与表一样,视图必须唯一命名,不能与其他视图或表重名,以确保数据库对象的唯一性和可识别性。
2.2 创建数量限制:对可以创建的视图数目没有限制,可根据实际业务需求创建多个视图,以满足不同的数据查询和展示需求 。
2.3 访问权限:创建视图需要足够的访问权限,这些权限通常由数据库管理人员授予,以保证只有授权用户能够创建和使用视图,维护数据库的安全性 。
2.4 嵌套视图:视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造新的视图。但需注意,过多的嵌套可能会影响性能,在实际使用中应谨慎考虑 。
2.5 ORDER BY的使用:ORDER BY可在视图中使用,但如果从该视图检索数据的SELECT语句中也含有ORDER BY,则视图中的ORDER BY将被覆盖 。
2.6 其他限制:视图不能索引,也不能有关联的触发器或默认值。不过,视图可以和表一起使用,例如编写联结表和视图的SELECT语句 。
三、使用视图
3.1 创建视图:使用CREATE VIEW语句创建视图,语法为CREATE VIEW viewname AS SELECT...。例如前面创建的productcustomers视图。创建视图时,应确保查询的正确性和有效性,因为视图的功能依赖于其背后的查询逻辑 。
3.2 查看创建视图的语句:使用SHOW CREATE VIEW viewname;语句可查看创建指定视图的具体语句,这在需要了解视图的定义、进行调试或维护时非常有用 。
3.3 删除视图:使用DROP VIEW viewname;语句删除视图。删除视图时需谨慎操作,因为删除后视图及其相关数据将无法恢复 。
3.4 更新视图:更新视图有两种方式。一是先用DROP删除视图,再用CREATE重新创建;二是使用CREATE OR REPLACE VIEW语句,如果要更新的视图不存在,则创建一个新视图;如果存在,则替换原有视图 。
3.5 利用视图简化复杂的联结:视图常用于隐藏复杂的SQL联结操作。例如,通过productcustomers视图检索订购了产品TNT2的客户:
SELECT cust_name, cust_contact
FROM productcustomers
WHERE prod_id = 'TNT2';
此操作简化了多表联结的复杂性,提高了数据检索的效率和便捷性 。
3.6 用视图重新格式化检索出的数据:若经常需要特定格式的数据结果,可创建视图来实现。例如,将vendors表中的供应商名和位置信息格式化为特定格式:
CREATE VIEW vendorlocations AS
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title
FROM vendors
ORDER BY vend_name;
之后,只需查询vendorlocations视图即可获取格式化后的数据,无需每次都执行复杂的字符串拼接操作 。
3.7 用视图过滤不想要的数据:视图可用于过滤数据。例如,创建一个过滤没有电子邮件地址的客户的视图:
CREATE VIEW customeremaillist AS
SELECT cust_id, cust_name, cust_email
FROM customers
WHERE cust_email IS NOT NULL;
在需要发送电子邮件时,可直接使用该视图,避免检索出无电子邮件地址的客户数据 。
3.8 使用视图与计算字段:视图能简化计算字段的使用。例如,将计算订单物品总价的查询创建为视图:
CREATE VIEW orderitemsexpanded AS
SELECT order_num, prod_id, quantity, item_price, quantity * item_price AS expanded_price
FROM orderitems;
使用该视图可方便地获取包含计算字段的订单详细信息,如检索订单20005的详细内容:
SELECT *
FROM orderitemsexpanded
WHERE order_num = 20005;
3.9 更新视图:通常情况下,视图是可更新的,更新视图实际上是更新其基表的数据。但并非所有视图都可更新,若视图定义中包含分组(使用GROUP BY和HAVING)、联结、子查询、并、聚集函数(Min()、Count()、Sum()等)、DISTINCT或导出(计算)列等操作,则不能进行视图的更新 。一般来说,应将视图主要用于数据检索,而非更新操作。
四、小结
视图作为MySQL中的重要特性,提供了一种灵活且高效的数据处理方式。通过创建和使用视图,可简化复杂的SQL操作,实现数据的重用、格式化、过滤以及对计算字段的便捷使用。同时,了解视图的规则和限制,有助于在实际应用中正确地创建和使用视图,提高数据库的管理和操作效率。
实战案例
- 实战数据准备
- 建表语句:创建employees表和departments表,并建立关联关系。
CREATE TABLE departments (
dept_id INT AUTO_INCREMENT PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL
);
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
dept_id INT,
salary DECIMAL(10, 2),
FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);
- 插入数据语句:向表中插入测试数据。
INSERT INTO departments (dept_name) VALUES ('HR'), ('IT'), ('Finance');
INSERT INTO employees (emp_name, dept_id, salary) VALUES ('Alice', 1, 5000.00), ('Bob', 2, 6000.00), ('Charlie', 1, 5500.00);
- 题目与解析
- 题目1:创建视图并查询:创建一个视图,显示每个员工的姓名、所在部门名称和薪水,并查询该视图。
- 解析:通过联结employees表和departments表,选取相关列创建视图,然后对视图进行查询。
- 脚本答案:
-- 创建视图
CREATE VIEW employee_department_salary AS
SELECT emp_name, dept_name, salary
FROM employees
JOIN departments ON employees.dept_id = departments.dept_id;
-- 查询视图
SELECT *
FROM employee_department_salary;
- 题目2:利用视图过滤数据:创建一个视图,只显示薪水大于5500的员工信息,并查询该视图。
- 解析:在视图定义中使用WHERE子句过滤薪水大于5500的员工数据。
- 脚本答案:
-- 创建视图
CREATE VIEW high_salary_employees AS
SELECT *
FROM employees
WHERE salary > 5500;
-- 查询视图
SELECT *
FROM high_salary_employees;
- 题目3:更新视图(假设视图可更新):假设上述high_salary_employees视图可更新,将其中某个员工的薪水增加1000。
- 解析:使用UPDATE语句对视图进行更新,由于视图可更新,实际会更新其基表employees中的数据。
- 脚本答案:
UPDATE high_salary_employees
SET salary = salary + 1000
WHERE emp_name = 'Bob';