[MySQL]存储过程与函数

2023-10-27


文章目录


1. 存储过程概述

1.1 含义

存储过程的英文是 Stored Procedure 。存储过程就是一组经过预先编译的 SQL 语句的封装。

1.2 执行过程

存储过程预先存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列 SQL 语句全部执行。

1.3 好处

1、简化操作,提高了sql语句的重用性,减少了开发程序员的压力
2、减少操作过程中的失误,提高效率
3、减少网络传输量(客户端不需要把所有的 SQL 语句通过网络发给服务器)
4、减少了 SQL 语句暴露在
网上的风险,也提高了数据查询的安全性

1.4 与视图、函数的对比

存储过程和视图有着同样的优点,清晰、安全,还可以减少网络传输量。不过它和视图不同,视图是 虚拟表 ,通常不对底层数据表直接操作,而存储过程是程序化的 SQL,可以 直接操作底层数据表 ,相比于面向集合的操作方式,能够实现一些更复杂的数据处理。

一旦存储过程被创建出来,使用它就像使用函数一样,可以直接通过调用存储过程名即可。相较于函数,存储过程是 没有返回值 的

1.5 存储过程的分类

存储过程的参数类型可以是IN、OUT和INOUT。

根据这点分类如下:
1、没有参数(无参数无返回)
2、仅仅带 IN 类型(有参数无返回)
3、仅仅带 OUT 类型(无参数有返回)
4、既带 IN 又带 OUT(有参数有返回)
5、带 INOUT(有参数有返回)

注意:IN、OUT、INOUT 都可以在一个存储过程中带多个。

2. 创建存储过程

2.1 语法

CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
	存储过程体
END

注意:如果没有定义参数种类, 默认就是 IN ,表示输入参数。

  • IN :当前参数为输入参数,存储过程只是读取这个参数的值。
  • OUT :当前参数为输出参数,执行完成之后,调用这个存储过程的客户端或者应用程序就可以读取这个参数返回的值了。
  • INOUT :当前参数既可以为输入参数,也可以为输出参数。
  • 参数类型:参数类型可以是 MySQL数据库中的任意类型。
  • characteristics:表示创建存储过程时指定的对存储过程的约束条件,其取值信息如下:
    • LANGUAGE SQL :说明存储过程执行体是由SQL语句组成的,当前系统支持的语言为SQL。
    • [NOT] DETERMINISTIC :指明存储过程执行的结果是否确定。
      • DETERMINISTIC表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。
      • NOT DETERMINISTIC表示结果是不确定的,相同的输入可能得到不同的输出。比如,返回的结果与随机数有关,则相同的输入可能得到不同的输出。
      • 如果没有指定任意一个值,默认为NOT ETERMINISTIC
    • { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } :指明子程序使用SQL语句的限制。
      • CONTAINS SQL表示当前存储过程的子程序包含SQL语句,但是并不包含读写数据的SQL语句;
      • NO SQL表示当前存储过程的子程序中不包含任何SQL语句;
      • READS SQL DATA表示当前存储过程的子程序中包含读数据的SQL语句;
      • MODIFIES SQL DATA表示当前存储过程的子程序中包含写数据的SQL语句。
      • 默认情况下,系统会指定为CONTAINS SQL
    • SQL SECURITY { DEFINER | INVOKER } :执行当前存储过程的权限,即指明哪些用户能够执行当前存储过程。
      • DEFINER 表示只有当前存储过程的创建者或者定义者才能执行当前存储过程;
      • INVOKER 表示拥有当前存储过程的访问权限的用户能够执行当前存储过程。
      • 如果没有设置相关的值,则MySQL默认指定值为DEFINER
    • COMMENT 'string' :注释信息,可以用来描述存储过程,比如存储过程的作用。
  • 存储过程体中可以有多条 SQL 语句,SQL语句写在 BEGIN 和 END 之间,如果仅仅一条SQL 语句,则可以省略 BEGIN 和 END。

2.2 设置结束标志

语法

DELIMITER 新的结束标记

由于在MySQL中,默认以分号为SQL语句的结尾,而在存储过程中,通常存在多条SQL语句,为了防止在存储过程的执行过程中遇到分号而直接结束报错,需要使用DELIMITER来指定新的SQL语句的结束标记,防止存储过程执行一半直接结束报错。

# 修改SQL语句的结束符
DELIMITER $

CREATE PROCEDURE select_emps()
BEGIN
    SELECT * FROM employees;
END$

# 修改SQL语句的结束符为原来的结束符
# 避免影响其他SQL语句
DELIMITER ;

2.3 创建存储过程示例

2.3.1 准备工作

# 创建数据库
CREATE DATABASE dbtest15;

# 使用新创建的数据库
USE dbtest15;

# 创建表格
CREATE TABLE employees
AS
SELECT * FROM atguigudb.employees;

CREATE TABLE departments
AS
SELECT * FROM atguigudb.departments;

2.3.2 代码示例

2.3.2.1 创建无参存储过程

创建存储过程select_all_data(),查看 emps 表的所有数据。

# 在 datagrip 中执行成功
# 如果因为结束符号报错,使用 DELIMITER 设置结束符号
CREATE PROCEDURE select_all_data()
BEGIN
    SELECT * FROM employees;
END;

在这里插入图片描述

创建存储过程avg_employee_salary(),返回所有员工的平均工资。

# 创建存储过程avg_employee_salary(),返回所有员工的平均工资
CREATE PROCEDURE avg_employee_salary()
BEGIN
    SELECT AVG(salary) FROM employees;
END;

在这里插入图片描述
创建存储过程show_max_salary(),用来查看“emps”表的最高薪资值。

# 创建存储过程show_max_salary(),用来查看“emps”表的最高薪资值。
CREATE PROCEDURE show_max_salary()
BEGIN
    SELECT MAX(salary) FROM employees;
END;

在这里插入图片描述

2.3.2.2 创建带OUT参数的存储过程

创建存储过程show_min_salary(),查看“emps”表的最低薪资值。并将最低薪资通过OUT参数“ms”输出

# 创建存储过程show_min_salary(),查看“emps”表的最低薪资值。并将最低薪资通过OUT参数“ms”输出
# 由于employees表中薪资字段的数据类型为DOUBLE(8, 2)
# 所以OUT参数“ms”的数据类型为DOUBLE(8, 2)
CREATE PROCEDURE show_min_salary( OUT ms DOUBLE(8, 2))
BEGIN
    # 将查询出来的结果给 ms
    SELECT MIN(salary) INTO ms
    FROM employees;
END;

在这里插入图片描述

2.3.2.3 创建带IN参数的存储过程

创建存储过程show_someone_salary(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名。

# 创建存储过程show_someone_salary(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名。
CREATE PROCEDURE show_someone_salary( IN empname VARCHAR(20))
BEGIN
    SELECT salary
    FROM employees
    WHERE last_name = empname;
END;

在这里插入图片描述

2.3.2.4 创建带IN参数与OUT参数的存储过程

创建存储过程show_someone_salary2(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名,用OUT参数empsalary输出员工薪资。

# 创建存储过程show_someone_salary2(),查看“emps”表的某个员工的薪资,并用IN参数empname
# 输入员工姓名,用OUT参数empsalary输出员工薪资。
CREATE PROCEDURE show_someone_salary2(IN empname VARCHAR(20), OUT empsalary DECIMAL(10, 2))
BEGIN
    SELECT salary INTO empsalary
    FROM employees
    WHERE last_name = empname;
END;

在这里插入图片描述

2.3.2.5 创建带INOUT参数的存储过程

创建存储过程show_mgr_name(),查询某个员工领导的姓名,并用INOUT参数“empname”输入员工姓名,输出领导的姓名。

# 创建存储过程show_mgr_name(),查询某个员工领导的姓名,并用INOUT参数“empname”输入员
# 工姓名,输出领导的姓名。
CREATE PROCEDURE show_mgr_name(INOUT emp_name VARCHAR(25))
BEGIN
    SELECT last_name INTO emp_name
    FROM employees
    WHERE employee_id = (
        SELECT manager_id
        FROM employees
        WHERE last_name = emp_name
        );
END;

在这里插入图片描述

3. 调用存储过程

调用存储过程,使用 CALL 关键字。

3.1 无参存储过程的调用

语法:

CALL 存储过程名();

调用存储过程select_all_data()

CALL select_all_data();

在这里插入图片描述

调用存储过程avg_employee_salary()

CALL avg_employee_salary();

在这里插入图片描述

调用存储过程show_max_salary()

CALL show_max_salary();

在这里插入图片描述

3.2 调用带OUT参数的存储过程

语法:

# 将自定义变量传入存储过程中用于接收存储过程中的查询结果
# 使用@定义自定义变量
CALL 存储过程名(@自定义变量名);
SELECT @自定义变量名;
CALL show_min_salary(@min_sal);
SELECT @min_sal;

在这里插入图片描述

3.3 调用带IN参数的存储过程

语法:

# 方式一
CALL 存储过程名('值');

# 方式二
# 定义变量并赋值, := 为变量赋值
SET @变量名 := '值';
# 将变量传递给存储过程的IN参数
CALL 存储过程名(@变量名);

调用存储过程show_someone_salary()

CALL show_someone_salary('Abel');

在这里插入图片描述

SET @emp_name := 'Abel';
CALL show_someone_salary(@emp_name);

在这里插入图片描述

3.4 调用带IN参数与OUT参数的存储过程

调用存储过程show_someone_salary2()

SET @emp_name = 'Abel';
# @emp_name 传入参数
# @emp_salary 接收查询结果
CALL show_someone_salary2(@emp_name, @emp_salary);
SELECT @emp_salary;

在这里插入图片描述

3.5 调用带INOUT参数的存储过程

调用存储过程show_mgr_name()

SET  @emp_name := 'Abel';
# @emp_name 传入参数并接收结果
CALL show_mgr_name(@emp_name);
SELECT @emp_name;

在这里插入图片描述

4. 存储过程的调试

在 MySQL 中,存储过程不像普通的编程语言(比如 VC++、Java 等)那样有专门的集成开发环境。因此,你可以通过 SELECT 语句,把程序执行的中间结果查询出来,来调试一个 SQL 语句的正确性。调试成功之后,把 SELECT 语句后移到下一个 SQL 语句之后,再调试下一个 SQL 语句。这样 逐步推进 ,就可以完成对存储过程中所有操作的调试了。当然,你也可以把存储过程中的 SQL 语句复制出来,逐段单独调试。

5. 存储函数

存储函数就是自定义的函数,定义好之后,调用方式与调用MySQL中预定义的系统函数一样。

5.1 存储函数语法

CREATE FUNCTION 函数名(参数名 参数类型,...)
RETURNS 返回值类型 # 指定返回结果的数据类型
[characteristics ...]
BEGIN
	函数体 #函数体中肯定有 RETURN 语句
END
  • 参数列表:FUNCTION中参数类型只能为IN,指定参数OUT或INOUT只对PROCEDURE是合法的。
  • RETURNS type 语句表示函数返回数据的类型;RETURNS子句只能对FUNCTION做指定,对函数而言这是 强制 的。它用来指定函数的返回类型,而且函数体必须包含一个 RETURN value 语句。
  • characteristic 创建函数时指定的对函数的约束。取值与创建存储过程时相同。
  • 函数体也可以用BEGIN…END来表示SQL代码的开始和结束。如果函数体只有一条语句,也可以省略BEGIN…END。

5.2 调用存储函数

在MySQL中,存储函数的使用方法与MySQL内部函数的使用方法是一样的。即用户自己定义的存储函数与MySQL内部函数是一个性质的。

语法:

SELECT 函数名(实参列表)

5.3 代码示例

注意:
若在创建存储函数中报错 you might want to use the less safe log_bin_trust_function_creators variable ,有两种处理方法:
方式1:
加上必要的函数特性 [NOT] DETERMINISTIC{CONTAINS SQL | NO SQL | READS SQL DATA |MODIFIES SQL DATA}
方式2:

SET GLOBAL log_bin_trust_function_creators = 1;

5.3.1 无参存储函数

创建存储函数,名称为email_by_name(),参数定义为空,该函数查询Abel的email,并返回,数据类型为字符串型。

# 创建存储函数,名称为 email_by_name(),参数定义为空,
# 该函数查询Abel的email,并返回,数据类型为字符串型。
CREATE FUNCTION email_by_name()
    RETURNS VARCHAR(25)
    # 该函数中包含读数据的SQL语句
    READS SQL DATA
BEGIN
    RETURN (
        SELECT email
        FROM employees
        WHERE last_name = 'Abel'
    );
END;
# 调用函数
SELECT email_by_name();

在这里插入图片描述

5.3.2 带参存储函数

创建存储函数,名称为email_by_id(),参数传入emp_id,该函数查询emp_id的email,并返回,数据类型为字符串型。

# 创建存储函数,名称为 email_by_id(),参数传入emp_id,
# 该函数查询emp_id的email,并返回,数据类型为字符串型。
# 存储函数中的参数都为IN类型,可以不用写参数的类别
CREATE FUNCTION email_by_id(emp_id INT)
RETURNS VARCHAR(25)
CONTAINS SQL # 该存储函数包含SQL语句
READS SQL DATA # 该存储函数包含读取数据的SQL
BEGIN
    RETURN (
        SELECT email
        FROM employees
        WHERE employee_id = emp_id
        );
END;

SELECT email_by_id(100);

在这里插入图片描述

6. 存储函数和存储过程的对比

在这里插入图片描述

  • 存储函数可以放在查询语句中使用,存储过程不行。
  • 存储过程的功能更加强大,包括能够执行对表的操作(比如创建表,删除表等)和事务操作,这些功能是存储函数不具备的。

7. 存储过程和函数的查看、修改、删除

7.1 查看

MySQL存储了存储过程和函数的状态信息,用户可以使用SHOW STATUS语句或SHOW CREATE语句来查看,也可直接从系统的information_schema数据库中查询。

7.1.1 SHOW CREATE

使用SHOW CREATE语句查看存储过程和函数的创建信息.

语法:

SHOW CREATE {PROCEDURE | FUNCTION} 存储过程名或函数名;
SHOW CREATE PROCEDURE show_mgr_name;

在这里插入图片描述

SHOW CREATE FUNCTION email_by_id;

在这里插入图片描述

7.1.2 SHOW STATUS

使用SHOW STATUS语句查看存储过程和函数的状态信息.

语法:

SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
  • [LIKE 'pattern']:匹配存储过程或函数的名称,可以省略。当省略不写时,会列出MySQL数据库中存在的所有存储过程或函数的信息。
SHOW PROCEDURE STATUS;

在这里插入图片描述

SHOW PROCEDURE STATUS LIKE 'show_max_salary';

在这里插入图片描述

7.1.3 information_schema.Routines表中查看存储过程和函数的信息

MySQL中存储过程和函数的信息存储在information_schema数据库下的Routines表中。可以通过查询该表的记录来查询存储过程和函数的信息。

语法:

SELECT * 
FROM information_schema.Routines
WHERE ROUTINE_NAME='存储过程或函数的名' [AND ROUTINE_TYPE = {'PROCEDURE|FUNCTION'}];

如果在MySQL数据库中存在存储过程和函数名称相同的情况,最好指定ROUTINE_TYPE查询条件来指明查询的是存储过程还是函数。

SELECT *
FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = 'email_by_id';

在这里插入图片描述

7.2 修改

修改存储过程或函数,不能修改存储过程或函数的功能,只能修改存储过程或函数的相关特性。使用ALTER语句实现。

如果需要修改存储过程或函数的功能,需要将存储过程或函数删除之后重新创建。

语法:

ALTER {PROCEDURE | FUNCTION} 存储过程或函数的名 [characteristic ...]

characteristic指定存储过程或函数的特性,其取值信息与创建存储过程、函数时的取值信息略有不同。

{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
  • CONTAINS SQL ,表示子程序包含SQL语句,但不包含读或写数据的语句。
  • NO SQL ,表示子程序中不包含SQL语句。
  • READS SQL DATA ,表示子程序中包含读数据的语句。
  • MODIFIES SQL DATA ,表示子程序中包含写数据的语句。
  • SQL SECURITY { DEFINER | INVOKER } ,指明谁有权限来执行。
    • DEFINER ,表示只有定义者自己才能够执行。
    • INVOKER ,表示调用者可以执行。
  • COMMENT 'string' ,表示注释信息。
ALTER PROCEDURE show_max_salary
COMMENT '查询员工的最高工资';

SHOW PROCEDURE STATUS LIKE 'show_max_salary';

在这里插入图片描述

7.3 删除

删除存储过程和函数,可以使用DROP语句

语法:

DROP {PROCEDURE | FUNCTION} [IF EXISTS] 存储过程或函数的名
DROP PROCEDURE IF EXISTS show_max_salary;

SHOW PROCEDURE STATUS LIKE 'show_max_salary';

在这里插入图片描述

8. 存储过程与函数的优缺点

8.1 优点

1、存储过程可以一次编译多次使用。存储过程只在创建时进行编译,之后的使用都不需要重新编译,这就提升了 SQL 的执行效率

2、可以减少开发工作量。将代码 封装 成模块,实际上是编程的核心思想之一,这样可以把复杂的问题拆解成不同的模块,然后模块之间可以 重复使用 ,在减少开发工作量的同时,还能保证代码的结构清晰。

3、存储过程的安全性强。我们在设定存储过程的时候可以 设置对用户的使用权限 ,这样就和视图一样具有较强的安全性。

4、可以减少网络传输量。因为代码封装到存储过程中,每次使用只需要调用存储过程即可,这样就减少了网络传输量。

5、良好的封装性。在进行相对复杂的数据库操作时,原本需要使用一条一条的 SQL 语句,可能要连接多次数据库才能完成的操作,现在变成了一次存储过程,只需要 连接一次即可 。

8.2 缺点

阿里开发规范
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

1、可移植性差。存储过程不能跨数据库移植,比如在 MySQL、Oracle 和 SQL Server 里编写的存储过程,在换成其他数据库时都需要重新编写。

2、调试困难。只有少数 DBMS 支持存储过程的调试。对于复杂的存储过程来说,开发和维护都不容易。虽然也有一些第三方工具可以对存储过程进行调试,但要收费。

3、存储过程的版本管理很困难。比如数据表索引发生变化了,可能会导致存储过程失效。我们在开发软件的时候往往需要进行版本管理,但是存储过程本身没有版本控制,版本迭代更新的时候很麻烦。

4、它不适合高并发的场景。高并发的场景需要减少数据库的压力,有时数据库会采用分库分表的方式,而且对可扩展性要求很高,在这种情况下,存储过程会变得难以维护, 增加数据库的压力 ,显然就不适用了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[MySQL]存储过程与函数 的相关文章

  • Flutter mysql1 数据包乱序

    我在建立 VPS 与图书馆的连接时遇到一些问题mysql1上颤动 我收到这个错误Unhandled Exception Error 1156 08S01 Got packets out of order当我执行查询时 MySQL服务器版本
  • 将 SQL Server 数据库合并为 1

    我需要将 20 个具有相同结构的数据库合并为 1 个数据库 我看到了这个帖子 以最小的延迟将来自许多不同数据库的数据整合到一个数据库中 https stackoverflow com questions 2537986 consolidat
  • $http.get 和 method:'GET' 之间的区别

    我正在使用 Spring Data REST 并有一个 MySQL DB 来管理我的数据 我使用 AngularJS 编写了第一页 并希望从数据库中获取数据 为了获取我的数据 我知道有两种不同的方式 http get http myURL
  • 我可以跨两个 MySQL 数据库执行事务吗?

    我可不可以做 Start transaction insert into db1 table1 field1 values 100 100 insert into db2 table2 field2 values 100 100 commi
  • 您可以使用 PDO 将占位符放入查询的选择部分吗?

    我打算使用 PDOprepare and execute 防止SQL注入攻击的机制 通常 SQL 中的占位符位于条件部分 例如select name age from members where age gt and gender f 但是
  • 如何左连接或内连接表本身

    例如 我将这些数据存储在表中 id name parent parent id 1 add self 100 2 manage null 100 3 add 10 200 4 manage null 200 5 add 20 300 6 m
  • 在 Python 中捕获 MySQL 警告

    我想用 Python 捕获并记录 MySQL 警告 例如 如果您提交 MySQL 会向标准错误发出警告 DROP DATABASE IF EXISTS database of armaments 当不存在这样的数据库时 我想捕获并记录它 但
  • 禁止 MySQL/MariaDB 中的存储过程使用 NULL 参数

    我可以指定表列不为空 但如何使存储过程或函数仅与非空参数兼容 在参数名称后添加 NOT NULL 不起作用 您需要自己验证传递的参数值 如果您使用 MySQL 5 5 及更高版本 您可以使用SIGNAL https dev mysql co
  • 无法使用 Spring Boot 创建 mysql 数据库

    我试图在没有像 h2 和 derby 这样的嵌入式数据库的情况下实现 Spring Boot 而是使用 mysql 我不断收到未知的数据库错误 pom xml
  • SQL:获取每组中的第N项

    我有一个这样的用户表 user id community id registration date 1 1 2008 01 01 2 1 2008 05 01 3 2 2008 01 28 4 2 2008 07 22 5 3 2008 0
  • 如果第一个 SELECT 返回 0 行,则执行第二个 SELECT 查询

    我正在尝试加快 PHP 脚本的速度 并且目前正在该事物的 Mysql 域中推送一些 PHP 逻辑 如果第一个 Select 没有返回行或计数为零 是否有办法进行不同的选择查询 请记住 第一个查询需要首先运行 第二个查询应该only如果第一个
  • 如何连接mysql表

    我有一张这样的旧桌子 user gt id name address comments 现在我必须创建一个 别名 表 以允许某些用户出于某种原因拥有别名 我创建了一个新表 user alias 如下所示 user alias gt name
  • mysqldump 错误 1045 尽管密码正确等但访问被拒绝

    这是一个棘手的问题 我有以下输出 mysqldump 出现错误 1045 尝试连接时用户 root localhost 使用密码 YES 访问被拒绝 当尝试导出我的数据库时mysqldump在 Windows XP 上 用户名是 root
  • 无法导入 python-mysqldb

    我使用安装了 python mysqldb sudo apt get install python mysqldb 我尝试使用它但没有成功 以下命令在 Python 提示符下不起作用 import python mysqldb Or imp
  • MySQL如何连接两个字段的表

    我有两张桌子date and id字段 我想加入这两个领域 我试过 JOIN t2 ON CONCAT t1 id t1 date CONCAT t2 id t2 date 这有效 但速度非常慢 有一个更好的方法吗 JOIN t2 ON t
  • 在codeigniter中处理存储过程输出参数

    我在 mysql 中有一个带有输出参数的存储过程 我需要将结果发送到使用 codeigniter 的 php 寄存器模式 public function registerUser data sql call register new use
  • MySQL - 基于日期加入

    是否可以根据同一日期连接两个表 而不考虑时间 就像是 从预约左侧加入销售 约会 日期 销售 日期 唯一的问题是它是一个日期时间字段 所以我想确保它只查看日期并忽略时间 你可以这样做 FROM appointments LEFT JOIN s
  • 使用git在测试和生产环境之间同步数据库

    我正在尝试在 php mysql 应用程序的开发过程中实现 git 到目前为止 我已经设置了 git repos 并且我们正在使用本地计算机进行测试 并且我们成功地将其用于文件 但我真的不知道如何处理数据库 服务器上有一个 cron 脚本
  • ImportError:没有使用 Python3 的名为 mysql.connector 的模块?

    尝试导入python mysql connector on Python 3 2 3并收到奇数堆栈 我怀疑我的 ubuntu 12 04 安装配置错误 vfi ubuntu usr share pyshared python3 Python
  • 数组 (UUID[ ]) 会破坏 1NF 吗?

    我的问题是包含 UUID 数组的字段是否会破坏范式 http en wikipedia org wiki Database normalization 在包含数组之前位于 NF 中的表中 原表 CREATE TABLE Floor Floo

随机推荐

  • Cocos 常用功能介绍

    学习来源链接 Cocos Creator零基础小白超神教程 cocos思想 cocos2d的编程最重要的是在于继承 一个对象继承自一个类 cocos creator的编程是每一个对象都是一个节点 在节点中可以挂载组件 一个节点中可以挂载无数
  • 夏普比率计算

    夏普比率的计算公式为 s h a r p e ThickSpace r a
  • 一文理解主数据和参考数据

    如果你准备要开展推动数据治理或者是数据质量的项目 那么你就有可能会听说到几个词 主数据和参考数据 一开始听到主数据这一词听起来就很高大上 而且非专业人士肯定不理解 即便是从事数据行业的朋友也很难参透 这一小节将会解答如下疑惑 1 什么是主数
  • 解决安装SolidWorks以后原来Altium designer创建的PCB、SCH以及工程文件图标改变,双击无法用Altium Designer打开的问题。

    第一步 打开Altium designer的系统设置图标 如下图 第二步 点击 system 如下图 第三步 点击 File Types 如下图所示 第四步 在右侧的列表中把pcb pcbdoc sch schdoc以及PrjPcb等前面方
  • c#数据类型

    数据类型 值类型 int float bool sizeof 查询变量占内存大小 一字节 8比特位 float 单精度浮点数 doublle 结构体 struct Student 访问类型 public公开 private类或结构体内部 i
  • bootstrap知识总结

    Bootstrap框架 一 Bootstrap简介 Bootstrap是一个用于快速开发Web应用程序和网站的前端框架 Bootstrap是基于HTML CSS JavaScript的 二 Bootstrap 特点 1 跨设备 跨浏览器 可
  • Angular4之动画

    在angular里面 动画的本质 是在一定时间 由一个状态转换到另一个状态 期间的过渡效果就是显示出来就是动画 例如 import Component Input from angular core import trigger state
  • 基于MCGS与PLC的四路抢答器

    实验要求 四路抢答器每一位抢答的选手都有一个抢答按钮 1号抢答按钮为SB1 2号抢答按钮为SB2 3号抢答按钮为SB3 4号抢答按钮为SB4 以及各位抢答选手的指示灯 主持人的位置设有抢答开始按钮SB5以及清零按钮SB6 另外系统中 有一个
  • 读《影响力》西奥迪尼---笔记

    读 影响力 西奥迪尼 笔记 1 本书框架 包括互惠 承诺与一致 社会认同 喜爱 权威 稀缺六大影响力武器 2 文书意图 从原理 成因上讲述这六个影响力武器对我们的影响 以及商家或者其他想要获利的如何利用影响力武器获取利益 意图说服我们如何拒
  • dvwa靶场通关(十二)

    第十二关 Stored Cross Site Scripting XSS 存储型xss low 这一关没有任何防护 直接输入弹窗代码 弹窗成功 medium 先试试上面的代码看看 有没有什么防护 发现我们的script标签不见了 应该是被过
  • 在JSP编译的时候,服务器内部做了什么?

    在JSP第一次获得请求时 不管请求来自于客户端浏览器还是服务器上的servlet JSP文件将被JSP引擎 JSP engine 转换成为一个servlet 而这个引擎本身也是一个servlet 在JSWDK 它就是 JspServlet
  • OpenCV - Mat、滤波、卷积的实现

    1 Mat数据类型 创建图像 Mat M 2 2 CV 8UC3 Scalar 0 0 255 改变图像尺寸 M create 4 4 CV 8UC2 快速创建图像的集中方法 Mat E Mat eye 4 4 CV 64F Mat F M
  • 子网掩码详解

    IP地址 IP地址被用来给Internet上的电脑一个编号 大家日常见到的情况是每台联网的PC上都需要有IP地址 才能正常通信 我们可以把 个人电脑 比作 一台电话 那么 IP地址 就相当于 电话号码 而Internet中的路由器 就相当于
  • C++设计模式

    设计模式有 6 大设计原则 单 职责原则 就 个类 应该仅有 个引起它变化的原因 开放封闭原则 软件实体可以扩展 但是不可修改 即 对需求 对程序的改动可以通过增加代码来完成 但是不能改动现有的代码 代换原则 个软件实体如果使 的是 个基类
  • HTML和CSS实现京东登录页面(html,css代码详解)

    HTML代码 基本布局 QQ 2248557717 下载链接地址 https download csdn net download dwjdj 15807158
  • STM32 C语言使用 memset清空结构体 导致改变其他结构体数据的问题

    首先 在C语言中 清空结构体的方法 我们一般会采用 memset函数 其原型是 void memset void ptr int value size t num 函数功能 填充内存块 将ptr指向的内存块的前num个字节设置为指定值 va
  • 2021年华中杯A题(马赛克瓷砖选色问题)详细分析

    目录 一 基本介绍 1 1 题目描述 1 2 待解决问题 二 问题分析与求解 2 1 问题一分析与求解 2 2 问题二分析与求解 2 3 问题三分析与求解 三 完整代码 四 总结 一 基本介绍 1 1 题目描述 马赛克瓷砖是一种尺寸较小 常
  • 七、JDK1.7中HashMap扩容机制

    导读 前面文章一 深入理解 Java集合初篇 中我们对Java的集合体系进行一个简单的分析介绍 上两篇文章二 Jdk1 7和1 8中HashMap数据结构及源码分析 三 JDK1 7和1 8HashMap数据结构及源码分析 续 中我们分别对
  • 基于货运APP的全栈开发实践:后端用PHP,前端用Uni-app实现兼容性

    在上一篇文章中 我们介绍了货运APP如何助您提高运输效率 本文将重点介绍该货运APP的技术实现 并探讨后端和前端所使用的技术以及如何实现兼容性 后端技术实现 PHP 货运APP的后端采用PHP作为开发语言 下面是一些关键点的介绍 服务器环境
  • [MySQL]存储过程与函数

    文章目录 1 存储过程概述 1 1 含义 1 2 执行过程 1 3 好处 1 4 与视图 函数的对比 1 5 存储过程的分类 2 创建存储过程 2 1 语法 2 2 设置结束标志 2 3 创建存储过程示例 2 3 1 准备工作 2 3 2