文章目录

  • 1 存储程序介绍
    • 1.1 什么是存储程序
    • 1.2 存储例程
    • 1.3 触发器
    • 1.4 事件
  • 2 创建和调用存储过程
    • 2.1 创建和调用存储过程
    • 2.2 存储过程的参数模式
    • 2.3 存储过程返回结果集
    • 2.4 存储过程的安全上下文
  • 3 创建和调用存储函数
    • 3.1 创建和调用存储函数
    • 3.2 存储函数和存储过程的主要差异
    • 3.3 存储函数和存储过程的共性特征
  • 4 管理存储例程
    • 4.1 查看存储例程的状态和定义
    • 4.2 删除存储例程
    • 4.3 修改存储例程的定义
    • 4.4 修改存储例程的特性
    • 4.5 授权执行存储例程
  • 5 在存储程序中使用游标
  • 6 在存储程序中使用事务
  • 7 触发器
    • 7.1 创建触发器
    • 7.2 查看触发器的定义
    • 7.3 删除触发器
  • 8 用事件定时执行任务
    • 8.1 事件的概念和基本属性
    • 8.2 创建事件
    • 8.3 查看事件的定义
    • 8.4 修改事件的属性和定义
    • 8.5 删除事件

1 存储程序介绍

1.1 什么是存储程序

存储程序是预先在数据库服务器端存储 SQL 命令/语句,并且过后能够在数据库服务器端被执行的数据库对象。

  • 存储程序的主体
    存储程序定义的主体中除可以包括常规的 SQL 语句外,通常还使用变量声明,选择,循环,复合语句等
  • 使用存储程序
    利用 CALL 语句等方式使用存储程序

存储程序的分类

  • 存储例程:和一个数据库相关,可以按照名字调用
  • 触发器:和一个表相关,并在该表产生特定事件时被触发
  • 事件:和一个数据库相关,代表了由 MySQL 服务器的事件调度器在特定时刻调度执行的任务。

1.2 存储例程

存储例程是存储在服务器端的 SQL 语句的集合,能够用存储例程的名字重用相应的语句代码。

经常用于提高效率和安全性:
(1)减少在 MySQL 服务器和 MySQL 客户端的数据传输
(2)对存储例程的授权管理更易于结合应用系统安全性
(3)存储例程中也是一个很好的记录日志的地方

包含过程和函数:PROCEDURE 和 FUNCTION

  • 存储过程没有返回值,通过 CALL 语句调用
  • 存储函数通过 RETURN 语句返回一个值,类似于内置函数

存储过程也是能“返回”值甚至结果集的

  • 存储过程可以使用输出类型的参数来传递值
  • 存储过程允许使用 SELECT 语句,从而使得存储过程执行后能够向客户端返回结果集

1.3 触发器

触发器是数据库中的命名对象,与一个表关联,并且在该表上的 INSERT,UPDATE,DELETE 等更改操作前/后被触发。

定义触发器
(1)WHERE:在哪张表上
(2)WHEN:由什么操作触发
(3)WHAT:被触发时所要执行的 SQL 命令

触发器的典型应用

  • 实现自定义完整性约束,
    例如一位教师在同意学期最多只允许承担 3 门课程
  • 用于值得计算
    例如订单明细发生改变时,重新计算订单金额并更新相关表(例如订单,库存等)中得相关记录
  • 日志或副本记录
    课确保系统跟踪和审计“时变”数据。

1.4 事件

事件是指在 MySQL 事件调度器的调度下,在特定的时刻所执行的任务,因此也称调度事件

定义事件的要素

  • 事件的“时刻”属性:在某一时刻仅执行一次,或按照事件间隔周期性的执行多少次
  • 事件的“任务”属性:要执行的 SQL 语句

事件典型应用

  • 常用于执行无人值守的系统管理任务,例如:更新汇总报告

2 创建和调用存储过程

存储例程是存储在服务器端的 SQL 语句的集合,利用存储例程的名字可重用相应的语句代码。存储过程是一种存储例程。

2.1 创建和调用存储过程

  • 使用 CREATE PROCEDURE 语句创建存储过程

example:创建一个存储过程,用于备份表纪律到备份表中。

create procedure backup()
insert into t_bak select * from t;
  • 用 CALL 语句调用存储过程
mysql> call backup();
Query OK, 2 rows affected (0.10 sec)
  • 存储过程的处理需要多条 SQL 语句,使用 DELIMITER 命令定义语句定界符

example:备份表记录到备份表后,删除原表的记录

delimiter $$create procedure backup2()
begininsert into t_bak select * from t;delete from t;
end $$delimiter ;

2.2 存储过程的参数模式

存储过程的参数类型可以是 MySQL 的有效数据类型。存储过程的参数有 IN,OUT 和 INOUT 三种模式。

存储过程的 IN 参数
例如,要求存储过程备份那些关键字段值小于给定值的记录。IN 可以省略书写。

delimiter $$create procedure backup3(n int)
begininsert into t_bak select * from t where id <= n;delete from t where id <= n;
end $$delimiter ;
mysql> call backup3(108);
Query OK, 1 row affected (0.10 sec)

存储过程的 OUT 参数
example:修改前述存储过程,使之传回本次备份的记录数。

delimiter $$create procedure backup4(n int, out record_count int)
begininsert into t_bak select * from t where id <= n;select count(*) into record_count from t where id <= n;delete from t where id <= n;
end $$delimiter ;
mysql> set @rec_count = 0;
Query OK, 0 rows affected (0.00 sec)mysql> call backup4(108, @rec_count);
Query OK, 1 row affected (0.12 sec)mysql> select @rec_count;
+------------+
| @rec_count |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

2.3 存储过程返回结果集

存储过程中允许使用 SELECT 等语句返回结果集

delimiter $$create procedure backup5(n int)
begininsert into t_bak select * from t where id <= n;select * from t where id <= n;delete from t where id <= n;
end $$delimiter ;
mysql> call backup5(108);
+-----+--------------+
| id  | name         |
+-----+--------------+
| 101 | 机械工程学院 |
+-----+--------------+
1 row in set (0.08 sec)Query OK, 1 row affected (0.10 sec)

2.4 存储过程的安全上下文

执行存储过程中的安全上下文
有权执行某个存储过程中的用户在执行存储过程时,存储过程内的 SQL 语句的执行,按定义者(默认)或调用者的权限进行检查。

谁是调用者,谁是定义者
调用者:执行 CALL 语句的用户
定义者:默认是执行 CREATE PROCEDURE 语句的用户,也可以用 DEFINER 子句指定另外的用户名

定义者和调用者安全上下文比较
试想:用户(调用者)执行某存储过程,且存储过程中读写某个表,存储过程的调用者没有这个表的读或写权限;存储过程的定义者拥有这个表的读或写权限。则定义者权限模式正常执行,调用者模式导致权限错误。

结论:定义者安全上下文有利于保证用户只能通过存储过程对数据进行有限的访问。

3 创建和调用存储函数

3.1 创建和调用存储函数

用 CREATE FUNCTION 语句创建函数

CREATE FUNCTION sp_name([func_parameter[,...]])RETURNS type      // 存储函数必须说明返回值类型routine_body        // 存储函数必须用 RETURN 返回值func_parameter.param_name type // 参数均视为 IN 参数

调用函数的方式
不需要像存储过程那样使用 CALL 语句,直接使用存储函数名带参数的形式,存储函数的调用可以出现在很多地方。

example:

create function hello(name char(20))returns char(50)
return concat('Hello,', name, '!');
mysql> select hello('MySQL');
+----------------+
| hello('MySQL') |
+----------------+
| Hello,MySQL!   |
+----------------+
1 row in set (0.00 sec)

功能相同的存储过程和存储函数
例如:用存储函数的方式实现前面实现过的存储过程。

delimiter $$create procedure backup4(n int, out record_count int)
begininsert into t_bak select * from t where id <= n;select count(*) into record_count from t where id <= n;delete from t where id <= n;
end $$delimiter ;

将存储过程改写成存储程序如下:

delimiter $$create function backupf(n int)returns int
begindeclare record_count int;insert into t_bak select * from t where id <= n;select count(*) into record_count from t where id <= n;delete from t where id <= n;return record_count;
end $$delimiter ;

3.2 存储函数和存储过程的主要差异

  • 向调用程序传回数据的方式不同
    存储过程借助 OUT 参数和返回结果集的方式
    存储函数使用 return 返回值的方式

  • 调用方式不同
    存储函数比存储过程的人调用更为灵活

  • 主体内允许的 SQL 不同
    存储过程中的主体中可以使用绝大多数 SQL
    存储函数受较多的限制,例如不允许包含常规 SELECT 语句

3.3 存储函数和存储过程的共性特征

存储例程特性的说明
characteristic:
| [NOT] DETERMINISTIC
| {NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }

存储例程的确定性
[NOT] DETERMINISTIC,确定性,即给定同样的输入参数是否总是产生相同的结果。

例如 MySQL 内置函数 NOW() 就是不确定的,不同的时间会得到不同的输出,而 hello() 则是确定的,对应确定的参数有确定的结果。

默认选项是 NOT DETERMINISTIC。该选项会对优化产生影响。例如,执行 DETERMINISTIC 时 MySQL 可能使用缓冲等优化手段。

存储例程特性的数据访问特性
NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA,说明存储例程的数据访问特性,默认选项 CONTAINS SQL。

NO SQL 指示存储例程不含括 SQL 语句;

CONTAINS SQL 指示该存储例程不包含读或写数据的 SQL 语句;

READS SQL DATA 指示存储例程包括读数据的语句(例如 SELECT)但不包括写数据的语句;

MODIFIES SQL DATA 指示存储例程包含写数据的语句(例如 INSERT)。

4 管理存储例程

4.1 查看存储例程的状态和定义

查看存储例程的状态

  • SHOW PROCEDURE STATUS [like…or…where]
  • SHOW FUNCTION STATUS [like…or…where]

example:

mysql> SHOW PROCEDURE STATUS LIKE 'backup'\G    # \G表示竖排显示
*************************** 1. row ***************************Db: dbName: backupType: PROCEDUREDefiner: root@localhostModified: 2020-05-06 16:26:19Created: 2020-05-06 16:26:19Security_type: DEFINERComment:
character_set_client: gbk
collation_connection: gbk_chinese_ciDatabase Collation: utf8_general_ci
1 row in set (0.00 sec)

查看存储例程的定义

  • SHOW CREATE PROCEDURE proc_name
  • SHOW CREATE FUNCTION func_name
mysql> SHOW CREATE PROCEDURE backup\G
*************************** 1. row ***************************Procedure: backupsql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTIONCreate Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `backup`()
insert into t_bak select * from t
character_set_client: gbk
collation_connection: gbk_chinese_ciDatabase Collation: utf8_general_ci
1 row in set (0.00 sec)

4.2 删除存储例程

mysql> DROP PROCEDURE backup;
Query OK, 0 rows affected (0.13 sec)mysql> DROP PROCEDURE backup;
ERROR 1305 (42000): PROCEDURE db.backup does not existmysql> DROP PROCEDURE IF EXISTS backup;
Query OK, 0 rows affected, 1 warning (0.00 sec)

4.3 修改存储例程的定义

删除并创新创建存储程序,需要先 DROP 后 CREATE

mysql> drop procedure if exists backup;
Query OK, 0 rows affected, 1 warning (0.00 sec)mysql> create procedure backup()-> insert into t_bak select * from t;
Query OK, 0 rows affected (0.00 sec)

4.4 修改存储例程的特性

  • ALTER PROCEDURE proc_name [ characteristic… ]
  • ALTER FUNCTION func_name [ characteristic… ]

characteristic:
COMMENT ‘string’
| LANGUAGE SQL
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }

alter procedure backup-> comment '备份表t到t_bak'-> modifies sql  data;
Query OK, 0 rows affected (0.05 sec)

4.5 授权执行存储例程

用 GRANT 语句授权用户执行存储例程
用户执行存储例程需要存储例程对象上的 EXECUTE 权限

GRANT EXECUTE ON [{ PROCEDURE | FUNCTION}]
{ *.* | db_name.* | db_name.routine_name } TO user

example:

GRANT EXECUTE ON course.* TO 'user1';GRANT EXECUTE ON PROCEDURE course.backup TO 'user2';

5 在存储程序中使用游标

存储程序中对结果集每行记录依次处理,需要使用游标(CURSOR)。

游标的作用

  • 在存储程序中编程访问 SELECT 所返回结果集
  • 方便逐行访问并对每行记录完成相应的处理

游标的使用

  • 先声明
    DECLARE CURSOR 和 DECLARE HANDLER
  • 后使用
    OPEN,使用游标必须先显式打开游标
    FETCH,提取当前行记录字段值
    CLOSE,最后关闭游标

example:计算学生平均绩点
把学生所选的每门课程的百分制成绩折算成绩点(例如按五级制 A/B/C/D/F 分别折算 4/3/2/1/0),将课程学分和课程绩点相乘,得到课程绩点,除以总的课程学生即平均绩点。

delimiter $$create function gpa(stu_id char(12))returns decimal(3, 2)
begindeclare score, credit, points, total_credit, total_points int default 0;declare done int default FALSE;declare cursor_choose_course cursor forselect choose.score, course.credit from choosejoin course on choose.Course_id = course.Course_idwhere choose.Student_id = stu_id and choose.score IS NOT NULL;
declare continue handler for not found set done = TRUE;open cursor_choose_course;
loop_cursor: loopfetch cursor_choose_course into score, credit;if done then leave loop_cursor;end if;set total_credit = total_credit + credit;if score >= 90 then set points = 4;elseif score >= 80 then set points = 3;elseif score >= 70 then set points = 2;elseif score >= 60 then set points = 1;else set points = 0;end if;set total_points = total_points + points * credit;
end loop;
close cursor_choose_course;
return if (total_credit > 0, total_points/total_credit, 0);
end $$delimiter ;
mysql> select gpa('M20177001');
+------------------+
| gpa('M20177001') |
+------------------+
|             4.00 |
+------------------+
1 row in set (0.41 sec)

6 在存储程序中使用事务

MySQL 默认在每一条 SQL 语句执行后都自动提交(事务),也允许在存储过程中使用显式地事务控制。

事务控制原则

  • 根据需要手工启动事务
  • 根据处理情况(成功时)提交事务或(失败时)回滚事务

常用的事务控制语句

  • START TRANSACTION ——用于启动事务
  • COMMIT ——用于提交事务
  • ROLLBACK ——用于回滚事务

事务经典案例:银行账户转账

对事务的要求

  • 转账先向转入账户增加余额,再从转出账户扣减余额
  • 如遇转出账户不够扣减,则放弃所有更改(即回滚事务)
delimiter $$create procedure transfer(account_from int, account_to int, amount int, OUT status int)
modifies sql data
begindeclare account_from_balance int;declare exit handler for sqlexception begin rollback;set status = -1;end;start transaction;update bank_account set Balance = Balance + amount where Account_Id = account_to;select balance into account_from_balance from bank_account where Account_Id = account_from;if account_from_balance < amount thenrollback;set status = -1;elseupdate bank_account set Balance = Balance - amount where Account_Id = account_from;commit;set status = 0;end if;
end $$delimiter ;

初始情况

+------------+---------+
| Account_Id | Balance |
+------------+---------+
|          1 |     500 |
|          2 |    1000 |
+------------+---------+

案例运行:一次成功的转账业务,账户1向账户2转账100元。

mysql> set @status = 0;
Query OK, 0 rows affected (0.00 sec)mysql> source E:\sql\test.sql            # 用脚本执行,脚本中内容就是上面的代码
Query OK, 0 rows affected (0.00 sec)mysql> call transfer(1, 2, 100, @status);
Query OK, 0 rows affected (0.10 sec)mysql> select @status;
+---------+
| @status |
+---------+
|       0 |
+---------+
1 row in set (0.00 sec)mysql> select * from bank_account;
+------------+---------+
| Account_Id | Balance |
+------------+---------+
|          1 |     400 |
|          2 |    1100 |
+------------+---------+
2 rows in set (0.00 sec)

案例运行:一次失败的转账业务,账户1向账户2转账1000元。

mysql> SET @status = 0;
Query OK, 0 rows affected (0.00 sec)mysql> CALL transfer(1, 2, 1000, @status);
Query OK, 0 rows affected (0.11 sec)mysql> SELECT @status;
+---------+
| @status |
+---------+
|      -1 |
+---------+
1 row in set (0.00 sec)mysql> select * from bank_account;
+------------+---------+
| Account_Id | Balance |
+------------+---------+
|          1 |     500 |
|          2 |    1000 |
+------------+---------+
2 rows in set (0.00 sec)

7 触发器

7.1 创建触发器

触发器是数据库中的命名对象,与一个表关联,并且在该表上的 INSERT,UPDATE,DELETE 等更改操作前/后被触发。

触发器的典型应用

  • 实现自定义完整性约束
  • 用于值的计算
  • 日志或副本记录

让表上的增删改操作接受一定的强制性“规则”

使用 CREATE TRIGGER 语句创建触发

CREATE TRIGGER trigger_name                      // 创建触发器
{ BEFORE | AFTER } { INSERT | UPDATE | DELETE } // 触发的时机和事件
ON tbl_name FOR EACH ROW                        // 触发器关联的表
trigger_body                                    // 触发器主体定义

example:
触发器示例1:将无效成绩“舍入”到有效成绩

delimiter $$create trigger valid_score_before_update_choose
before update
on choose for each row
beginif New.score < 0 then set New.score = 0;elseif New.score > 100 then set New.score = 100;end if;
end $$delimiter ;
mysql> update choose set score = 102 where Student_id = 'M20177006';
Query OK, 1 row affected (0.11 sec)
Rows matched: 1  Changed: 1  Warnings: 0

7.2 查看触发器的定义

查看触发器列表

  • SHOW TRIGGERS [{FROM | IN} db_name] [LIKE ‘pattern’ | WHERE expr]


查看定义存储例程的 CREATE 语句

7.3 删除触发器

使用 DROP TRIGGER 语句删除触发器

  • DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

example:

mysql> drop trigger if exists valid_score_before_update_choose;
Query OK, 0 rows affected (0.00 sec)

注意

  • 修改表名后,该表上的触发器仍然有效;
  • 删除表后,该表上创建的触发器会自动被删除。

8 用事件定时执行任务

8.1 事件的概念和基本属性

事件是指在 MySQL 事件调度器的调度下,在特定的时刻所执行的任务,因此也称为调度事件。

(一)事件调度器配置

  • 全局变量 event_scheduler 代表事件调度器的状态

    • SHOW VARIABLES LIKE ‘event_scheduler’;
      其值可以为 ON、OFF 或 DISABLED,代表启动、停止和禁用。
    • 可使用命令行参数或 my.ini 配置其为 DISABLED,且运行时不可改变
    • 未配置为 DISABLED 时,可以在运行时切换启动和停止
      SET GLOBAL event_scheduler = ON(或OFF);

事件也是一种存储程序,也有和其它存储程序相似的属性:

  • 存储程序的共性属性

    • 名称
    • 属于哪个数据库
    • 要执行的 SQL 语句
  • 和触发器相似的属性
    • 定义者(类似于触发器,有定义者,没有调用者)
  • 事件所特有的属性
    • 调度的时间和周期(类似于触发器的触发事件)

(二)调度的时间和周期

  • 在什么时间调度

    • 仅调度一次的任务在什么时间
    • 重复调度的事件,首次调度在什么时间
  • 每隔多长时间重复调度
    • 是否需要在某个时间后就不再重复调度
  • 过期的事件是否要自动删除

8.2 创建事件

  • 使用 CREATE EVENT 语句创建事件

CREATE EVENT event_name                                  // 创建事件
ON SCHEDULE                                             // 调度事件的时机{ AT time_spec                                        // 一次性事件的时刻| EVERY interval [STARTS time_spec] [ENDS time_spec] }   // 重复事件的周期和始终
[ ON COMPLETION [NOT] PRESERVE ]                        // 完成后是否保留
[ ENABLE | DISABLE ]                                    // 创建时启用还是禁用
DO event_body;                                          // 事件要执行的

example:
示例 1:定义一个一次性事件,在一分钟后备份表。

CREATE EVENT event_backup
ON SCHEDULE
AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
DO INSERT INTO t_bak SELECT * FROM t;

说明:

  • 在默认数据库中创建一个事件,名为 event_backup
  • 事件是一个一次性事件(使用了 AT 子句)
  • 事件在当前时间(CREATE EVENT 语句执行时)后 1 分钟被调度
  • 事件接受两个默认选项:创建后启用,完成后不予保留
  • 事件完成的任务是 DO 后面的一条语句

示例 2:定义一个重复性事件,在每天 1 点定时 备份表。

CREATE EVENT daily_backup
ON SCHEDULE
EVERY 1 DAY STARTS CURRENT_DATE + INTERVAL 1 HOUR
DO INSERT INTO t_bak SELECT * FROM t;

说明:

  • 在默认数据库中创建一个事件,名为 daily_backup
  • 事件是一个重复性事件(使用了 EVERY 子句)
  • 事件在的运行周期为 1 天(EVERY 1 DAY)
  • 起始时间是当天 1 点(STARTS CURRENT_DATE + INTERVAL 1 HOUR)
  • 事件将持续循环(没有使用 ENDS 指定终止时间)

8.3 查看事件的定义

查看事件列表

查看定义事件的 CREATE 语句

8.4 修改事件的属性和定义

使用 ALTER EVENT 语句

  • 不需要先删除后重新创建
  • 语句中的成分和 CREATE EVENT 非常相似
  • 增加了 RENAME TO 子句,用于修改事件名称
alter event daily_backup
on schedule
every 1 week starts current_date + interval 2 hour
rename to weekly_backup;

8.5 删除事件

使用 DROP EVENT 语句删除事件

  • DROP EVENT [IF EXISTS] [schema_name.]event_name

example:

DROP EVENT IF EXISTS weekly_backup;

【MySQL数据库设计与应用(六)】存储程序(存储过程,存储函数,触发器,事件)相关推荐

  1. WebDay18 MySQL存储过程 存储函数 触发器 事务

    MySQL存储过程 存储函数 触发器 事务 一.MySQL存储过程和函数 1.存储过程和函数的概念 2.存储过程和函数的好处 3.存储过程和函数的区别 4.创建存储过程 5.调用存储过程 6.查看存储 ...

  2. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表.---查询语句创建表 create table emp as ...

  3. MySQL表/视图/存储过程and函数/触发器/事件与数据库之间的关系

    mysql中的数据库包含表.视图.存储过程and函数.触发器.以及事件. 数据库: 数据库是存放数据的仓库.数据库中的数据不是直接存在数据库中,而是存在数据库的表中 表(table): 表是数据库中存 ...

  4. mysql数据库开发经历_六年开发经验,整理Mysql数据库技巧笔记,全网最详细的笔记集合!...

    数据库 表 DML DQL 多表查询 内连接查询 外连接查询 子查询 将一条查询语句作为一张虚拟表 Mysql约束 主键约束 特点:主键约束默认包含非空和唯一两个功能. 一张表只能有一个主键. 主键一 ...

  5. MySql基础篇---004 其它数据库对象篇:视图,存储过程与函数,变量、流程控制与游标 ,触发器

    第14章_视图 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. 常见的数据库对象 对象 描述 表(TABLE) 表是存储数据的逻辑单元,以行和列的形 ...

  6. MySQL数据库学习日志(六):索引和视图

    MySQL数据库学习日志(六):索引和视图 MySQL数据库学习日志(六):索引和视图 索引 (一)索引概述 (二)优缺点 (三)分类 1. 按照底层实现的方式 2. 按照功能划分 普通索引 唯一索引 ...

  7. 不属于mysql常量的是_MySQL中,下面______常量的写法是不正确的?-智慧树MySQL数据库设计与应用章节答案...

    MySQL数据库设计与应用:MySQL中,下面______常量的写法是不正确的?[?ж???] A:'2.1E5 B:0x123abc C:b'121' D:null MySQL数据库设计与应用章节测 ...

  8. mysql数据库设计的原则_MySQL数据库设计原则

    转自 http://www.supidea.com/post/mysql_design_database.aspx MySQL数据库设计原则 MySQL对于成为一个非常快速的数据库服务器有着当之无愧的 ...

  9. MYSQL数据库设计原则

    一.MYSQL数据库设计原则 1.核心原则 不在数据库做运算; cpu计算务必移至业务层; 控制列数量(字段少而精,字段数建议在20以内); 平衡范式与冗余(效率优先:往往牺牲范式) 拒绝3B(拒绝大 ...

  10. 数据库-优化-MYSQL数据库设计原则

    MYSQL数据库设计原则 1.核心原则 不在数据库做运算; cpu计算务必移至业务层; 控制列数量(字段少而精,字段数建议在20以内); 平衡范式与冗余(效率优先:往往牺牲范式) 拒绝3B(拒绝大sq ...

最新文章

  1. 第 18 章 Django 入门
  2. centos xampp安装mysql_在xampp上部署dvwa|centos(linux)环境
  3. Question | 网站被黑客扫描撞库该怎么应对防范?
  4. [文摘]标准的软件开发过程
  5. xp怎样安装android-studio,Xposed 框架的安装
  6. 直播回顾:如何对付臭名昭著的 IO 夯?诊断利器来了 | 龙蜥技术
  7. 关于ajax页面里的js方法无法使用的解决办法
  8. Ubuntu 16.04使用sudo apt-get -f install解决依赖时的注意事项(重点)
  9. 【预测模型】基于matlab BP神经网络预测【含Matlab源码 221期】
  10. 机械专业热门选题 论文+图纸+PPT
  11. MongoDB ODM
  12. python恶搞代码打开对方摄像头_用Python获取摄像头并实时控制人脸的实现示例
  13. 第九讲:一元函数积分学的几何应用
  14. 各大IT公司的起名缘由 [转载]
  15. 哈工大 计算机系统 一纸开卷CSAPP
  16. 专科毕业,从0到1400star,从阮一峰周刊到尤雨溪推荐的开源项目总结
  17. 微型计算机的硬件结构采用,微型计算机硬件结构内部结构
  18. wap2app(三)-- 添加引导页
  19. python发布exe_Python:程序发布方式简介一(打包为可执行文件EXE)
  20. mipcms标签列表调用

热门文章

  1. Atomikos的使用
  2. 简易扫雷游戏c语言程序,C++实现简单的扫雷游戏(控制台版)
  3. android5.1谷歌下载,谷歌发布Android 5.1源代码
  4. 储蓄卡注册paypal(无双币信用卡注册paypal)
  5. 字节跳动面试难吗,应该如何应对?
  6. idea查看class文件显示 compiled code 的问题
  7. 硬核测评,谷歌翻译被碾压!全球首个翻译引擎进化归来,“细节狂魔”搞定方言文言文...
  8. bitcoind配置文件bitcoin.conf
  9. TQ2440使用手册
  10. 推特源代码在GitHub 泄漏三个月之久