视图是一种虚拟存在的表,也由行和列组成,但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图时动态生成的。相当于临时对象,不占用内存,但一直存在着,便于更加高效地查找数据。
CREATE OR REPLACE VIEW 视图名 AS SELECT...
如有重名的视图(也就是重复创建),就用新视图replace旧视图。后面的SELECT就是普通的创建表的方法DROP VIEW 视图名
DELETE FROM clients_balance(视图名)
WHERE invoice_id=1UPDATE ...(视图)
SET …=…(字段)1.我们不会在应用程序中写SQL,它会让应用代码混乱并且难以维护,并且需要修改应用代码以满足编译条件。::md,怎么我现在还是只会myBatis啊,还是要学更多的东西啊!::所以我们应该将SQL代码从应用代码里剥离出来,在*存储过程(Stored procedure) *或 *函数(function)*中写
2.存储过程是一个包含一堆SQL代码的数据库对象,在应用程序中我们调用的就是数据库对象来存储和管理SQL代码。就是数据库语言层面的代码封装与重用。但其实存储过程也好函数也好,都不是mapper代理开发,我目前还不知道前二者该如何使用
创建存储过程
DELIMITER $$
重新设置分隔符(默认是;),*使创建存储过程这一大段代码成为一条语句。CREATE PROCEDURE get_invoices_with_balance()
创建存储过程的开头,之后()中会有参数的出现++存储过程的名字基本是小写字母+_组成++BEGIN 代码块 END $$
BEGIN和END关键字之间的内容称为存储过程的主体body,代码块中每条语句都要用;结尾,这是mysql规定的要求,而$$之前的代码同属一个分割区域。DELIMITER ;
DELIMITER $$
CREATE PROCEDURE get_invoices_with_balance()BEGIN
SELECT *FROM invoices
WHERE (invoice_total-payment_total)>0;END $$
DELIMITER ;其他方面:
CALL get_invoices_with_balance()
调用过程,但是mysql规定该过程空格内必须要填充内容,起码要填写NULL,这里是实参位置。DROP PROCEDURE IF EXISTS get_invoices_with_balance()
加上IF EXISTS是为了防止重复删除,重复删除会导致错误,通常与CREATE连用放在首行。可以连续创建procedure并且不会重复创建和删除参数
CREATE PROCEDURE get_clients_by_state(p_state CHAR(2))
,在空格内设置形参p_state,后面是形参的类型char,长度为2的字符。我们通常使用VARCHAR可变字符串,但是如果知道参数的长度固定,建议直接如上述代码声明好固定长度,这样占用的空间会更少。::与之前学的不同,mysql是先写形参,再写类型,其余的与我们学的类似。多个参数之间逗号隔开,在代码块中也可以任意使用形参::带有默认值的参数
IF p_state IS NULL THEN
+SET p_state='CA'
+END IF;
作为一条语句。BEGIN
SELECT * FROM clients c WHERE c.state = IFNULL(p_state,c.state);
END $$参数验证
SIGNAL
语句标志或者引发错误。结构是SIGNAL SQLSTATE ''
引号里面是一个包含错误代码的字符串常值,在网上可以查到很多类型。SET MESSAGE_TEXT = 'Invalid amount';
总体代码如下:BEGIN
IF amount <= 0 THEN SIGNAL SQLSTATE '22003'
SET MESSAGE_TEXT = ‘Invalid amount’; END IF; ...
END $$参数分类
SELECT a,b INTO A,B FROM...
将读取到的a,b分别赋值给A,B两个输出参数。实际调用过程是:
SET @A=0;SET @B=0;
这里@A表示A是一个用户自定义变量。CALL XXX(3,@A,@B);
需要传递这些变量SELECT @A,@B;
得到查询后的表变量
set @num=1; 或set @num:=1;
select @num:=1; 或 select @num:=字段名 from 表名 where ……
常用于输出用户变量。使用set时可以用“=”或“:=”,但是使用select时必须用“:=赋值SET GLOBAL 变量名=
或者 SET @@GLOBAL.变量名=
SHOW GLOBAL VARIABLES
SET SESSION 变量名=
或者 SET @@SESSION.变量名=
或者SET 变量名=
如果变量之前什么符号都没有,则默认为session会话变量,其中session可以由local替代。CREATE PROCEDURE get_risk_factor ()
BEGIN DECLARE risk_factor DECIMAL(9,2)DEFAULT 0;
DECLARE invoices_total DECIMAL(9,2); DECLARE invoices_count INT;
//声明本地变量 SELECT COUNT(*),SUM(invoice_total)
INTO invoices_count,invoices_total FROM invoices;
//本地变量赋值 SET risk_factor=invoices_total/invoices_count*5;
//通过本地变量计算 SELECT risk_factor;
END定义变量的两种方式:
1.set/select…into:对局部变量赋值,对其他变量申明+赋值
2.DECLARE var INT DEFAULT 0
declare语句专门用于定义局部变量,主要用于存储过程
CREATE FUNCTION risk(id INT)
,再确认返回值类型,RETURNS INT
(可以是任意数据类型),这是函数和存储过程创建的主要区别。RETURN IFNULL(risk_factor,0)
DROP FUCTION IF EXISTS risk;
删除函数,只写名字就好CREATE FUNCTION get_risk_factor_for_client
(client id INT
)RETURNS INTEGER //确认返回值类型
READS SQL DATA //读取sql数据BEGIN
risk=…RETURN risk;
END触发器是在插入、更新、删除语句前后自动执行的一堆SQL代码,通常用于保持数据的一致性
创建触发器
CREATE TRIGGER payments_after_insert
,起名的原则最好是 表名-时序-操作。AFTER INSERT ON payments
:声明时序、操作以及触发器作用的表。时序也可以为BEFORE
,操作也可以为DELETE``UPDATE
FOR EACH ROW
:表示该触发器会作用于每一个受影响的行NEW.字段名
-会返回我们刚刚插入的行的字段对应的值,用于插入后的触发器。OLD.字段名
-用于更新或删除行时返回之前的行的字段对应的值。DELIMITER $$
CREATE TRIGGER payments_after_insert AFTER INSERT ON payments
FOR EACH ROWBEGIN
UPDATE invoices //any table except payments SET payment_total = payment_total + NEW.amount
//NEW.amount:刚刚在payment中插入行的amount字段 WHERE invoice_id = NEW.invoice_id;
//别忘了id对应,否则全部的值都会被触发器更新END S$
DELIMITER ;查看触发器:SHOW TRIGGERS
查看当前数据库中的所有触发器,还可以在其基础上设置查询特定格式的触发器,如SHOW TRIGGERS LIKE 'payments%'
以payments开头的触发器。
删除触发器:DROP TRIGGER IF EXISTS payments_after_insert
注意删除触发器使用的是DROP
触发器另一个作用:审计,我们可以添加一个audit审计表,在触发器中将操作的数据、时间等信息插入到审计表中,自动记录用户的操作。
事件是根据计划(schedule)执行的任务或一堆代码,可以只执行一次,也可以按照某种规律执行,通过事件,我们可以自动化数据库维护工作任务,比如定时清理,定时更新数据、生成汇总报告
event_scheduler
的值即可动态地控制事件调度器的启用。即先SHOW VARIABLES LIKE 'events%';
找到事件调度器对应的变量,再SET GLOBAL event_scheduler = ON或者1 ;
但是,该全局变量如果都设置为ON,那么会造成系统资源的浪费,在此我建议只更改会话变量,在之后的大型库中再对全局变量进行修改。CREATE EVENT yearly_delete_stale_audit_rows
名称如此,每年删除过期审计行ON SCHEDULE AT '2022-07-25'
或者定期执行ON SCHEDULE EVERY 1 YEAR STARTS '2022-07-25' ENDS '2022-08-26'
“1 YEAR”可以改为任何时间段,STARTS/ENDS都是可选择的DO BEGIN...END$$
这个DO很容易忘SHOW EVENTS LIKE 'yearly%'
DROP EVENT IF EXISTS ...
该页面进阶部分的删除全部是DROP,DELETE只用于删除表中的记录ALTER EVENT...
ALTER EVENT a DISABLE/ENABLE
%% 事务是代表单个工作单元的一组SQL语句,这些语句作为一个单元一起成功或失败。
ACID:1.Atomicity原子性:不可被分割
2.Consistency一致性:通过使用事务,数据库将始终保持一致的状态,其执行的结果将使数据库从一种一致性状态变迁到另一种一致性状态,数据库的完整性没有被破坏。
3.Isolation隔离性:多事务互相隔离,并且有锁,一次最多只有一个事务可以更新目标行,不能多事务同时更新一个行
4.Durability持久性:一旦事务被提交,其产生的作用是永久性的,如果出现停电等特殊情况,事务的作用仍然保持
START TRANSACTION;
申明接下来的语句都属于同一事务COMMIT;
提交事务:当MySQL看到commit时,它就会把所有的更改都写入数据库,如果有语句更改失败,MySQL会自动撤销之前的更改,此时称作事务被退回了。ROLLBACK;
回滚事务:手动退回事务以便于检查错误,将commit换成rollbackExecute Current Statement
想要执行哪一步就把光标移到哪里,在执行上面的语句,应该可以检查一些debug并发:多个用户同时访问相同数据的情况,在一个用户修改其他用户正在检索或修改的数据时,并发往往会出现问题
%% 读取未提交、读取已提交、可重复读(默认)、可串行化(可序化) %%
更低的隔离级别更容易并发,会有更多用户同时接触到同一数据,另一方面,低级的隔离换来高效的性能,因为我们需要添加的锁少了 %% 更高的隔离级别降低了性能以及可扩展性,在存储和CPU方面都需要额外的资源,给服务器加重负担
SHOW VARIABLES LIKE 'transaction_isolation';
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
,该语句不涉及变量,所以只为下一个事务设置隔离级别,如果是该会话或连接SET后就要加SESSION而不能省略,如果是全局设置级别就要在SET后面加GLOBALSTART TRANSACTION
或BEGIN
命令(-删除后回滚)后,所有的 DML(INSERT | UPDATE | DELETE) 语句都需显示执行COMMIT命令(autocommit=OFF情况下)。其他的诸如 DDL(CREATE | DROP | ALTER)语句的,都是隐式提交的数值类型的另一个属性:补零ZEROFILL,相当于两步,设置宽度+补零
如INT(4)=>0001总是会有四位,便于排版对齐
BOOL/BOOLEAN:true/false,一样的
ENUM('small','medium','large')
,之后只能写这三个值(不论大小写)JSON(JavaScript Object Notation,JS对象简谱)是一种通过网络存储和数据传输的轻量级数据交换格式,它在网络和移动应用中被大量使用。在大多数情况下,移动应用程序通过JSON将数据发送到后端。JSON相当于简单的、完全独立于编程语言的数据库
++有关详细的JSON我们之后再学哦!已经涉及到前后端和JS了++
JSON的组成:
方法一:标准JSON创建
UPDATE products
SET properties = ’ //MySQL设置JSON对象需要再加’’
{
“dimensions”:[1,2,3],//数组
"weight":10,
“manufacturer”:{ “name”:“sony” }//嵌套对象
}
’
`` WHERE product_id = 1;
方法二:关于JSON的函数
UPDATE products
SET properties = JSON_OBJECT(
'weight',10,
‘dimensions’,JSON_ARRAY(1,2,3),//数组
'manufacturer',JSON_OBJECT('name','sony')
)
`` WHERE product_id = 1;
++应用了MySQL内部函数,所以不需要遵顼什么"":等,直接用英文单引号就行,(MySQL中单引号双引号等效)一个键、一个值依次交替++
查找JSON某一键值对的值
SELECT JSON_EXTRACT(properties,'$.weight')FROM products
,该函数第一个参数就是一个JSON对象,第二个参数是一条路径,用字符串表示。$表示当前的JSON文档 .访问单独的属性或者键。SELECT properties ->'$.weight'
properties->'$.dimensions[0]'
,0表示第一个数properties->'$.manufacturer.name'
用点运算符访问嵌套对象的单个属性,但是如果此时的值是字符串,那么返回的结果为字符串如"sony",如果我们只想要其中的内容就要用->>
去掉双引号。更改或添加JSON键值对的值:
UPDATE products
SET properties = JSON_SET(
properties,
‘ . w e i g h t ′ , 20 , ‘ ‘ ′ .weight',20, `` ' .weight′,20,‘‘′.age’,10
`` )
%% 该函数第一个参数是要修改的JSON对象,然后键值对依次排列。注意,我们可以任意添加新的键值对如上’$.age’
删除JSON键值对:
UPDATE products
SET properties = JSON_REMOVE(
properties,
‘ . w e i g h t ′ , ‘ ‘ ′ .weight', `` ' .weight′,‘‘′.age’
`` )
这两个函数,都是拾取一个JSON对象,修改并返回一个新的JSON对象