存储 订阅
1、存储,把钱或物等积存起来。《清会典事例·户部·库藏》:“户部奏部库空虚,应行存储款项。”《清会典·户部仓场衙门·侍郎职掌》:“每年新漕进仓,仓场酌量旧存各色米多寡匀派分储,将某仓存储某年米色数目,造册先期咨部存案。”鲁迅《书信集·致李小峰》:“《旧时代之死》之作者之家族,现颇窘,几个友人为之集款存储,作孩子读书之用。”2、指积存的钱或物等。沙汀《医生》:“即或偶而想到自己的晚景,想到存储不多,他也能够叹口气就丢开。” 展开全文
1、存储,把钱或物等积存起来。《清会典事例·户部·库藏》:“户部奏部库空虚,应行存储款项。”《清会典·户部仓场衙门·侍郎职掌》:“每年新漕进仓,仓场酌量旧存各色米多寡匀派分储,将某仓存储某年米色数目,造册先期咨部存案。”鲁迅《书信集·致李小峰》:“《旧时代之死》之作者之家族,现颇窘,几个友人为之集款存储,作孩子读书之用。”2、指积存的钱或物等。沙汀《医生》:“即或偶而想到自己的晚景,想到存储不多,他也能够叹口气就丢开。”
信息
常见方式
DAS,NAS和SAN,分布式存储
拼    音
cún chǔ
存储媒介类型
硬盘、磁带、光盘、移动存储设备、分布式存储、企业级存储
含    义
把钱、数据或物等积存起来
中文名
存储
外文名
Storage
存储释义
1、把钱或物等积存起来。《清会典事例·户部·库藏》:“户部奏部库空虚,应行存储款项。”《清会典·户部仓场衙门·侍郎职掌》:“每年新漕进仓,仓场酌量旧存各色米多寡匀派分储,将某仓存储某年米色数目,造册先期咨部存案。”鲁迅《书信集·致李小峰》:“《旧时代之死》之作者之家族,现颇窘,几个友人为之集款存储,作孩子读书之用。”2、指积存的钱或物等。沙汀《医生》:“即或偶而想到自己的晚景,想到存储不多,他也能够叹口气就丢开。” 3、存储就是根据不同的应用环境通过采取合理、安全、有效的方式将数据保存到某些介质上并能保证有效的访问,总的来讲可以包含两个方面的含义:一方面它是数据临时或长期驻留的物理媒介;另一方面,它是保证数据完整安全存放的方式或行为。存储就是把这两个方面结合起来,向客户提供一套数据存放解决方案。
收起全文
精华内容
下载资源
问答
  • mysql存储引擎

    万次阅读 多人点赞 2019-07-31 19:28:44
    数据库存储引擎 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还...

    数据库存储引擎

    数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。

    因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(Table Type,即存储和操作此表的类型)。

    如创建一个InnoDB类型的表:

    CREATE TABLE `brand` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `brand_name` varchar(64) NOT NULL,
      `brand_logo` varchar(255) NOT NULL,
      `description` varchar(255) NOT NULL,
      `parent_id` int(11) NOT NULL,
      `layer` int(11) NOT NULL DEFAULT '0',
      `enabled` int(11) NOT NULL DEFAULT '0',
      `path` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `brand_name` (`brand_name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    mysql存储引擎

    MySQL给开发者提供了查询存储引擎的功能,执行以下sql即可查询到mysql中的存储引擎

    SHOW ENGINES

    我的mysql版本是5.7.22,下面是在Navicat中执行的结果

    InnoDB存储引擎

    InnoDB是事务型数据库的首选引擎,通过上图也看到了,InnoDB是目前MYSQL的默认事务型引擎,是目前最重要、使用最广泛的存储引擎。支持事务安全表(ACID),支持行锁定和外键。InnoDB主要特性有:

    1、InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句中提供一个类似Oracle的非锁定读。这些功能增加了多用户部署和性能。在SQL查询中,可以自由地将InnoDB类型的表和其他MySQL的表类型混合起来,甚至在同一个查询中也可以混合

    2、InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的

    3、InnoDB存储引擎完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB将它的表和索引在一个逻辑表空间中,表空间可以包含数个文件(或原始磁盘文件)。这与MyISAM表不同,比如在MyISAM表中每个表被存放在分离的文件中。InnoDB表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上

    4、InnoDB支持外键完整性约束,存储表中的数据时,每张表的存储都按主键顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此作为主键

    5、InnoDB被用在众多需要高性能的大型数据库站点上

    InnoDB不创建目录,使用InnoDB时,MySQL将在MySQL数据目录下创建一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件。

    场景:由于其支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。

    MyISAM存储引擎

    MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物和外键。

    MyISAM主要特性有:

    1、大文件(达到63位文件长度)在支持大文件的文件系统和操作系统上被支持

    2、当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成

    3、每个MyISAM表最大索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16

    4、最大的键长度是1000字节,这也可以通过编译来改变,对于键长度超过250字节的情况,一个超过1024字节的键将被用上

    5、BLOB和TEXT列可以被索引,支持FULLTEXT类型的索引,而InnoDB不支持这种类型的索引

    6、NULL被允许在索引的列中,这个值占每个键的0~1个字节

    7、所有数字键值以高字节优先被存储以允许一个更高的索引压缩

    8、每个MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当INSERT和UPDATE操作的时候该列被更新,同时AUTO_INCREMENT列将被刷新。所以说,MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快

    9、可以把数据文件和索引文件放在不同目录

    10、每个字符列可以有不同的字符集

    11、有VARCHAR的表可以固定或动态记录长度

    12、VARCHAR和CHAR列可以多达64KB

    存储格式:

    1、静态表(默认):字段都是非变长的(每个记录都是固定长度的)。存储非常迅速、容易缓存,出现故障容易恢复;占用空间通常比动态表多。

    2、动态表:占用的空间相对较少,但是频繁的更新删除记录会产生碎片,需要定期执行optimize table或myisamchk -r命令来改善性能,而且出现故障的时候恢复比较困难。

    3、压缩表:使用myisampack工具创建,占用非常小的磁盘空间。因为每个记录是被单独压缩的,所以只有非常小的访问开支。

    静态表的数据在存储的时候会按照列的宽度定义补足空格,在返回数据给应用之前去掉这些空格。如果需要保存的内容后面本来就有空格,在返回结果的时候也会被去掉。(其实是数据类型char的行为,动态表中若有这个数据类型也同样会有这个问题)

    使用MyISAM引擎创建数据库,将产生3个文件。文件的名字以表名字开始,扩展名之处文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex)。

    场景:如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。

    MERGE存储引擎

    MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表结构必须完全相同,尽管其使用不如其它引擎突出,但是在某些情况下非常有用。说白了,Merge表就是几个相同MyISAM表的聚合器;Merge表中并没有数据,对Merge类型的表可以进行查询、更新、删除操作,这些操作实际上是对内部的MyISAM表进行操作。

    场景:对于服务器日志这种信息,一般常用的存储策略是将数据分成很多表,每个名称与特定的时间端相关。例如:可以用12个相同的表来存储服务器日志数据,每个表用对应各个月份的名字来命名。当有必要基于所有12个日志表的数据来生成报表,这意味着需要编写并更新多表查询,以反映这些表中的信息。与其编写这些可能出现错误的查询,不如将这些表合并起来使用一条查询,之后再删除Merge表,而不影响原来的数据,删除Merge表只是删除Merge表的定义,对内部的表没有任何影响。

    MEMORY存储引擎

    MEMORY存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。MEMORY主要特性有:

    1、MEMORY表的每个表可以有多达32个索引,每个索引16列,以及500字节的最大键长度

    2、MEMORY存储引擎执行HASH和BTREE缩影

    3、可以在一个MEMORY表中有非唯一键值

    4、MEMORY表使用一个固定的记录长度格式

    5、MEMORY不支持BLOB或TEXT列

    6、MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引

    7、MEMORY表在所由客户端之间共享(就像其他任何非TEMPORARY表)

    8、MEMORY表内存被存储在内存中,内存是MEMORY表和服务器在查询处理时的空闲中,创建的内部表共享

    9、当不再需要MEMORY表的内容时,要释放被MEMORY表使用的内存,应该执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE)

    MEMORY存储引擎默认使用哈希(HASH)索引,其速度比使用B-+Tree型要快,但也可以使用B树型索引。由于这种存储引擎所存储的数据保存在内存中,所以其保存的数据具有不稳定性,比如如果mysqld进程发生异常、重启或计算机关机等等都会造成这些数据的消失,所以这种存储引擎中的表的生命周期很短,一般只使用一次。现在mongodb、redis等NOSQL数据库愈发流行,MEMORY存储引擎的使用场景越来越少。

    场景:如果需要该数据库中一个用于查询的临时表。

    ARCHIVE存储引擎

    Archive是归档的意思,在归档之后很多的高级功能就不再支持了,仅仅支持最基本的插入和查询两种功能。在MySQL 5.5版以前,Archive是不支持索引,但是在MySQL 5.5以后的版本中就开始支持索引了。Archive拥有很好的压缩机制,它使用zlib压缩库,在记录被请求时会实时压缩,所以它经常被用来当做仓库使用。

    场景:由于高压缩和快速插入的特点Archive非常适合作为日志表的存储引擎,但是前提是不经常对该表进行查询操作。

    CSV存储引擎

    使用该引擎的MySQL数据库表会在MySQL安装目录data文件夹中的和该表所在数据库名相同的目录中生成一个.CSV文件(所以,它可以将CSV类型的文件当做表进行处理),这种文件是一种普通文本文件,每个数据行占用一个文本行。该种类型的存储引擎不支持索引,即使用该种类型的表没有主键列;另外也不允许表中的字段为null。csv的编码转换需要格外注意。

    场景:这种引擎支持从数据库中拷入/拷出CSV文件。如果从电子表格软件输出一个CSV文件,将其存放在MySQL服务器的数据目录中,服务器就能够马上读取相关的CSV文件。同样,如果写数据库到一个CSV表,外部程序也可以立刻读取它。在实现某种类型的日志记录时,CSV表作为一种数据交换格式,特别有用。

    BLACKHOLE存储引擎(黑洞引擎)

    该存储引擎支持事务,而且支持mvcc的行级锁,写入这种引擎表中的任何数据都会消失,主要用于做日志记录或同步归档的中继存储,这个存储引擎除非有特别目的,否则不适合使用。

    场景:如果配置一主多从的话,多个从服务器会在主服务器上分别开启自己相对应的线程,执行binlogdump命令而且多个此类进程并不是共享的。为了避免因多个从服务器同时请求同样的事件而导致主机资源耗尽,可以单独建立一个伪的从服务器或者叫分发服务器。

    PERFORMANCE_SCHEMA存储引擎

    该引擎主要用于收集数据库服务器性能参数。这种引擎提供以下功能:提供进程等待的详细信息,包括锁、互斥变量、文件信息;保存历史的事件汇总信息,为提供MySQL服务器性能做出详细的判断;对于新增和删除监控事件点都非常容易,并可以随意改变mysql服务器的监控周期,例如(CYCLE、MICROSECOND)。 MySQL用户是不能创建存储引擎为PERFORMANCE_SCHEMA的表。

    场景: DBA能够较明细得了解性能降低可能是由于哪些瓶颈。

    Federated存储引擎

    该存储引擎可以不同的Mysql服务器联合起来,逻辑上组成一个完整的数据库。这种存储引擎非常适合数据库分布式应用。

    Federated存储引擎可以使你在本地数据库中访问远程数据库中的数据,针对federated存储引擎表的查询会被发送到远程数据库的表上执行,本地是不存储任何数据的。

    缺点:

    1.对本地虚拟表的结构修改,并不会修改远程表的结构

    2.truncate 命令,会清除远程表数据

    3. drop命令只会删除虚拟表,并不会删除远程表

    4.不支持 alter table 命令

    5. select count(*), select * from limit M, N 等语句执行效率非常低,数据量较大时存在很严重的问题,但是按主键或索引列查询,则很快,如以下查询就非常慢(假设 id 为主索引)

    select id from db.tablea where id >100 limit 10 ;

    而以下查询就很快:

    select id from db.tablea where id >100 and id<150

    6.  如果虚拟虚拟表中字段未建立索引,而实体表中为此字段建立了索引,此种情况下,性能也相当差。但是当给虚拟表建立索引后,性能恢复正常。

    7. 类似 where name like "str%" limit 1 的查询,即使在 name 列上创建了索引,也会导致查询过慢,是因为federated引擎会将所有满足条件的记录读取到本地,再进行 limit 处理。

    场景: dblink。

    存储引擎的选择

    功 能

    MYISAM

    Memory

    InnoDB

    Archive

    存储限制

    256TB

    RAM

    64TB

    None

    支持事物

    No

    No

    Yes

    No

    支持全文索引

    Yes

    No

    No

    No

    支持数索引

    Yes

    Yes

    Yes

    No

    支持哈希索引

    No

    Yes

    No

    No

    支持数据缓存

    No

    N/A

    Yes

    No

    支持外键

    No

    No

    Yes

    No

     

    展开全文
  • Mysql 存储过程简介--实现存储过程

    万次阅读 多人点赞 2019-01-23 13:35:44
    什么是存储引擎: Mysql中的数据用各种不同的技术存储在文件(或者内存)中, 每一种技术都使用不同的存储机制, 索引技巧 锁定水平并且最 终提供广泛的不同的功能和能力。通过选择不同的额技术你能过够获得额外 ...

    什么是存储引擎:

    Mysql中的数据用各种不同的技术存储在文件(或者内存)中, 每一种技术都使用不同的存储机制,
    索引技巧 锁定水平并且最 终提供广泛的不同的功能和能力。通过选择不同的额技术你能过够获得额外 的速度或者功能从而改 善你的应用整体功能。不同的存储引擎性能是不一的你能够获得额外的速度或者功能,从而改善你的应用的整体功能。查看Mysql可用的引擎可以用:show engines查询出来后边有 yes 的 是支持的 no 是不支持的。

    2.Mysql 的常见引擎 :

    1.MEMORY:

    memory使用 存在内存中的内容来创建表,每个MEMORY表实际对应一个磁盘文件,格式是.frm(就是表里的结构)。memory类型的表访问速度非常快,因为它的数据放在内存中 并且默认使用 HASH索引,但是一旦服务器关闭 表中的数据就会丢失, 但是表还会继续存在。​

    2.MylSAM:

    拥有较高的插入(如 insert into 新增),查询速度,但不支持事物,也不支持外键。 每个MylSAM在磁盘上存放3个文件,其中文件名和表名相同,但是扩展名 分别为 .frm 存储表的一个定义 . MYD:存储真是的数据 .MYI:存储索引 MyISAM适合: (1)做很多count 的计算; (2)插入不频繁,查询非常频繁; (3)没有事务。

    3.InnoDB:

    5.5版本后Mysql的默认数据库,事物型数据库的首选引擎,支持ACID事物,支持行级锁定 innoDB写的处理效率差,他会占用空间来保存数据和索引。 InnoDB适合: (1)可靠性要求比较高,或者要求事务; (2)表更新和查询都相当的频繁,并且表锁定的机会比较大的情况指定数据引擎的创建 让所有的灵活性成为可能的开关是提供给ANSI SQL的MySQL扩展——TYPE参数。 MySQL能够让你在表格这一层指定数据库引擎,所以它们有时候也指的是table formats。 下面的示例代码表明了如何创建分别使用MyISAM、ISAM和HEAP引擎的表格。 下面的代码显示了如何使用ALTER TABLE把MyISAM表格移动到InnoDB的引擎: 代码:ALTER TABLE tblMyISAM CHANGE TYPE=InnoDB 3. Memory:所有数据置于内存的存储引擎,拥有的极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在 Mysql 重新启动时丢失。 4.Merge:将一定数量的 MyISAM 表联合而成一个整体,在超大规模数据存储时很有用。 5.Archive:非常适合存储大量的独立的,作为历史纪录的数据。因为它们不经常被读取。 Archive 拥有高效的插入速度,但其对查询的支持相对较差。 6.CSV:逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每个数据表创建一个 .CSV文件这是一个普通的文本文件,每个数据行占用一个文本行。CSV存储引擎不支持索引。7.BlackHole:黑洞引擎,写入的任何数据都会消失,一般用于记录 binlog 做复制的中继。

    ACID:

    A 事务的原子性(Atomicity):指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行 了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱 却没出来.这两步必须同时完成.要么就不完成. C 事务的一致性(Consistency):指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了 a+b=10,一个事务改变了a, 那么b也应该随之改变. I 独立性(Isolation):事务的独立性也有称作隔离性,是指两个以上的事务不会出现交错执行的状态. 因为这样可能会导致数据不一致. D 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久 的保存在数据库之中, 不会无缘无故的回滚.

    Innodb介绍:

    innoDB是一种可靠性高的高性能 Mysql 数据库存储引擎,它有如下优点:​
    1.它遵循ACID模式设计,具有与事物(Transactions),回滚和保护用户数据的崩溃恢复能力。 2.提供行锁。 3.InnoDB表基于主键在磁盘上安排数据,有优化的常见查询功能。每一个InnoDB表都有一个叫做 聚集索引的主键索引,能尽可能减少数据查询次数。 4.为了维护数据完整性,InnoDB还支持外键完整性约束。 5.可以与其它MySQL存储引擎混合使用InnoDB表。列如,能用一个结合操作在一个单独查询中综合源自 InnoDB和InnoDB表的数据 6.InnoDB是针对提高 CPU效率而设计的,并且在处理大数据时表现最佳。MyISAM和InnoDB的区别;

    什么是存储过程:

    一组可编程的函数,是为完成 特定 功能的SQL语句 存储 过程是具有名字的代码段 ,来完成一些特定的功能。 创建的存储过程保存在数据库的字典中。

    为什么用存储过程:

    将重复性高的一些操作,封装到一个存储过程中,简化对Sql的调用。 批量处理 统一接口, 确保数据的安全 相对与oracle数据来说,Mysql的存储过程功能较弱 使用较少

    存储过程的创建 和调用:

    delimiter $ $: 他与存储过程无关 delimiter 语句将标准分割符–分号(;)更改 $ $ , 因为我们想将存储过程 作为一个整体传递给服务器,而不是让mysql 工具一次解析每个语句,告诉mysql解析器 ,该段命令是否已经结束了,mysql是否可以执行了,默认情况下delimiter是分号;。在命令行客户端中,如果有一行以分号结束,那么回车 后执行 改命令,但是有的时候,不希望mysql这么做。在为可能输入较多的语句,且 语句包含有分号,使用delimiterr$ $ 这样只有$ $出现之后mysql解析器解析执行这段语句

    案例:

    创建存储过程:

    delimiter $$  -- 定义好开始  符号 可以 为$$ 或者//
     CREATE PROCEDURE user_tt()  -- 给存储过程取一个名字
    BEGIN -- 开始
    SELECT * from t_user; --sql语句执行 注意sql 语句结束有分号
    END $$  --结束  注意 符号 和定义开始一致
    

    在这里插入图片描述
    调用存储过程:

    delimiter;-- 把分号改回来
    
    CALL user_tt;
    

    在这里插入图片描述

    查看存储过程:
    查看所有的存储过程:SHOW PROCEDURE STATUS;
    在这里插入图片描述

    ##查看指定数据库的存储过程:SHOW PROCEDURE STATUS WHERE db=“存储过程名”;

    在这里插入图片描述
    查看 指定存储过程源代码: SHOW CREATE PROCEDURE + 存储过程名

    在这里插入图片描述
    删除存储过程 :drop PROCEDURE +存储过程名;

    在这里插入图片描述
    存储过程变量:

    delimiter $$  -- 定义好开始  符号 可以 为$$ 或者//
     CREATE PROCEDURE text_user()  -- 给存储过程取一个名字
    BEGIN -- 开始
    
      -- 声明变量  关键 字declare   `DEFAULT ''  默认值 空字符串
    
    
    
    DECLARE  jie  VARCHAR(255) default ''; 
    
    DECLARE   x,y INT   default 0;
    
    
    SELECT * from t_user; -- sql语句执行 注意sql 语句结束有分号
    
    
    END $$  -- 结束  注意 符号 和定义开始一致
    
    

    在这里插入图片描述
    给变量赋值:
    在这里插入图片描述
    变量的范围:如果在存储过程中声明变量,那么当达到存储过程的 END 语句时 它超出了范围。因此在其他代码块无法 访问

    存储过程参数:

    三种类型:

                                   in  输入类型
                                    
                                    --  根据传入的名称, 获取对应的信息、
    delimiter $$
    CREATE PROCEDURE getName(in name VARCHAR(225))-- 传入参数  in 关键字  VARCHAR类型
    BEGIN 
    
     SELECT * from t_user where  user_code =name; -- 给要查的 赋值
    
    
    END $$
    
    delimiter;
    

    在这里插入图片描述

            out类型的 输出
    
    
    
    delimiter $$
    CREATE PROCEDURE getMima(in name VARCHAR(225),out mima int )-- 传入参数 out  关键字  输出数据
    BEGIN 
    
     SELECT  user_pass into mima  from t_user where  user_code = name; -- 给要查的 user_pass into mima  赋值  name 
    
    
    END $$
    
    
    
    查询结果
    CALL  getMima('鲁班',@m);  -- @m 就时out 的参数  首先执行这句话
    SELECT @m; -- 这里的@m 就是上面所定义的 在这可以直接输出 这只是简写
    
    SELECT @m  from  DUAL 这个是mysql 数据库 提供的一张假表  可以加上参数调用
    
    

    在这里插入图片描述

     inout 类型是又输入又是输出
      delimiter $$
    CREATE PROCEDURE test1808(inout num  int ,in abc  int  )-- 传入参数 out  关键字  输出数据
    BEGIN 
    
    
    set num = num + abc;
     
    END $$
    
    delimiter;
    
    查询结果
    set @num1=220;
    CALL test1808(@num1,10);
    SELECT @num1;
    

    在这里插入图片描述

    存储过程语句:

    if语句: IF expression THEN
    statements;
    END IF;
    IF expression THEN
    statements;
    ELSE
    else-statements;
    END IF;
    CASE语句:
    CASE case_expression
    WHEN when_expression_2 THEN commands …
    ELSE commands
    END CASE;
    循环语句:
    WHILE expression DO
    statements
    END WHILE
    2)REPEAT
    stalemeents;
    UNTIL expression
    END REPEAT

    自定义函数

    案例:

    
      定义 一个自定义函数  在定义函数 和存储过程有区别  定义函数function
    delimiter $$
    CREATE  FUNCTION rand_str(n int) returns  varchar(225)
    BEGIN
    -- 生明一个str 52字母
    DECLARE str VARCHAR(100)  DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    -- 记录 当前是第几个
    DECLARE i INT DEFAULT 0;
    -- 生成的结果
    DECLARE  res_str  VARCHAR(255)   DEFAULT '';
    -- 循环  
    WHILE i < n DO
    -- 随机生成一个指定的字符串 b bc bce 
    --   1+ RAND()*52  floor(1+rand ()*52);
    --  SUBSTR(str FROM (1+rand()*52),1)
    set res_str=CONCAT(res_str,SUBSTR(str,FLOOR(1+RAND()*52),1));
    SET i= i+1;
    END WHILE;
    RETURN res_str;
    END $$
    delimiter ;
    
    
    结果
    SELECT rand_str(5);
    

    在这里插入图片描述

    案例批量新增:

    这里调用了以上的随机数 方法 函数
    
    delimiter $$
    CREATE  PROCEDURE insert_emp10(in  startNum int, in  max_num int) 
                            --  startNum 从几开始
                            --   max_num 要插入多少条数据
    begin 
    -- 声明 一个变量叫记录当前是第几条数据
     DECLARE  i INT default 0;
    -- 默认情况是自动 提交数据
      set autocommit = 0; -- 不让它自动 提交
    repeat 
    set i= i+1; -- 每循环一次 让i+1
    -- 插入数据
    INSERT into  emp VALUES (startNum+i,rand_str(5),FLOOR(10+RAND()*30));
                                 --  startNum代表是id ,+i是每次循环+1
                                 -- rand_str(5) 调用 数据 数 对name 每一次循环
                                   --   都去生成一个5个字母的名字
                                   --  FLOOR(10+RAND()*30) 年龄 也是随机的 +10
                                   --  是应为随机数是从0开始 *30 是到30岁
    until i =max_num  -- 当i=max_num 就让它退出循环
    
    end  repeat;
    commit;  -- 整体提交所有数据  提高效率 
    end $$
    
    delimiter ;
    

    结果:
    在这里插入图片描述

    展开全文
  • ORACLE存储过程

    万次阅读 多人点赞 2018-11-02 18:14:48
    oracle存储过程 目录 一.什么是存储过程 二.为什么要写存储过程 三.存储过程基础 1.存储过程结构 2.存储过程语法 3.pl/sql处理存储过程 四.存储过程进阶 1.BUIK COLLECT 2.FORALL 3.pl/sql调试存储过程 ...

                                                  oracle存储过程

    目录

             一.什么是存储过程

    二.为什么要写存储过程

    三.存储过程基础

    1.存储过程结构

    2.存储过程语法

    3.pl/sql处理存储过程

    四.存储过程进阶

    1.BUIK COLLECT

    2.FORALL

    3.pl/sql调试存储过程

    4.案例实战

    附.参考资料


    一.什么是存储过程

    存储过程,百度百科上是这样解释的,存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来调用存储过程。

    简单的说就是专门干一件事一段sql语句。

    可以由数据库自己去调用,也可以由java程序去调用。

    在oracle数据库中存储过程是procedure。

    二.为什么要写存储过程

    1.效率高

      存储过程编译一次后,就会存到数据库,每次调用时都直接执行。而普通的sql语句我们要保存到其他地方(例如:记事本  上),都要先分析编译才会执行。所以想对而言存储过程效率更高。

    2.降低网络流量

    存储过程编译好会放在数据库,我们在远程调用时,不会传输大量的字符串类型的sql语句。

    3.复用性高

    存储过程往往是针对一个特定的功能编写的,当再需要完成这个特定的功能时,可以再次调用该存储过程。

    4.可维护性高

    当功能要求发生小的变化时,修改之前的存储过程比较容易,花费精力少。

    5.安全性高

    完成某个特定功能的存储过程一般只有特定的用户可以使用,具有使用身份限制,更安全。

    三.存储过程基础

    1.存储过程结构

    (1).基本结构

    Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常(可写可不写,要增强脚本的容错性和调试的方便性那就写上异常处理)

    (2).无参存储过程

    CREATE OR REPLACE PROCEDURE demo AS/IS
    	变量2 DATE;
    	变量3 NUMBER;
    BEGIN
    	--要处理的业务逻辑
    	EXCEPTION    --存储过程异常
    END 
    

    这里的as和is一样任选一个,在这里没有区别,其中demo是存储过程名称。

    (3).有参存储过程

    a.带参数的存储过程

    CREATE OR REPLACE PROCEDURE 存储过程名称(param1 student.id%TYPE)
    AS/IS
    name student.name%TYPE;
    age number :=20;
    BEGIN
      --业务处理.....
    END

    上面脚本中,

    第1行:param1 是参数,类型和student表id字段的类型一样。

    第3行:声明变量name,类型是student表name字段的类型(同上)。

    第4行:声明变量age,类型数数字,初始化为20

     

    b.带参数的存储过程并且进行赋值

    CREATE OR REPLACE PROCEDURE 存储过程名称(
           s_no in varchar,
           s_name out varchar,
           s_age number) AS
    total NUMBER := 0;
    BEGIN
      SELECT COUNT(1) INTO total FROM student s WHERE s.age=s_age;
      dbms_output.put_line('符合该年龄的学生有'||total||'人');
      EXCEPTION
        WHEN too_many_rows THEN 
        DBMS_OUTPUT.PUT_LINE('返回值多于1行'); 
    END

    上面脚本中:

    其中参数IN表示输入参数,是参数的默认模式。
    OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
    OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
    IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去

    第7行:查询语句,把参数s_age作为过滤条件,INTO关键字,把查到的结果赋给total变量。

    第8行:输出查询结果,在数据库中“||”用来连接字符串

    第9—11行:做异常处理

    2.存储过程语法

    (1).运算符

    这里s,m,n是变量,类型是number;

    分类

    运算符

    含义

    示例表达式

     

     

     

    算术运算符

    +

    s := 2 + 2;

    -

    s := 3 – 1;

    *

    s := 2 * 3;

    /

    s := 6 / 2;

    mod(,)

    取模,取余

    m : = mod(3,2)

    **

    乘方

    10**2 =100

     

     

     

    关系运算符

    =

    等于

    s = 2

    <>或!=或~=

    不等于

    s != 2

    <

    小于

    s < 3

    >

    大于

    s > 0

    <=

    小于等于

    s <= 9

    >=

    大于等于

    s >= 1

     

     

    比较运算符

    LIKE

    满足匹配为true

    ‘li’ like ‘%i’返回true

    BETWEEN

    是否处于一个范围中

    2 between 1 and 3 返回true

    IN

    是否处于一个集合中

    ‘x’ in (‘x’,’y’) 返回true

    IS NULL

    判断变量是否为空

    若:n:=3,n is null,返回false

     

    逻辑运算符

    AND

    逻辑与

    s=3 and c is null

    OR

    逻辑或

    s=3 or c is null

    NOT

    逻辑非

    not c is null

     

    其他

    :=

    赋值

    s := 0;

    ..

    范围

    1..9,即1至9范围

    ||

    字符串连接

    ‘hello’||’world’

     

    (2).SELECT INTO STATEMENT语句

    该语句将select到的结果赋值给一个或多个变量,例如:

    CREATE OR REPLACE PROCEDURE DEMO_CDD1 IS
    s_name VARCHAR2;   --学生名称
    s_age NUMBER;      --学生年龄
    s_address VARCHAR2; --学生籍贯
    BEGIN
      --给单个变量赋值
      SELECT student_address INTO s_address
      FROM student where student_grade=100;
       --给多个变量赋值
      SELECT student_name,student_age INTO s_name,s_age
      FROM student where student_grade=100;
      --输出成绩为100分的那个学生信息
      dbms_output.put_line('姓名:'||s_name||',年龄:'||s_age||',籍贯:'||s_address);
    END

    上面脚本中:

    存储过程名称:DEMO_CDD1, student是学生表,要求查出成绩为100分的那个学生的姓名,年龄,籍贯

    (3).选择语句

    a.IF..END IF

    学生表的sex字段:1-男生;0-女生

    IF s_sex=1 THEN
      dbms_output.put_line('这个学生是男生');
    END IF

    b.IF..ELSE..END IF

    IF s_sex=1 THEN
      dbms_output.put_line('这个学生是男生');
    ELSE
      dbms_output.put_line('这个学生是女生');
    END IF

    (4).循环语句

    a.基本循环

    LOOP
      IF 表达式 THEN
        EXIT;
      END IF
    END LOOP;

    b.while循环

    WHILE 表达式 LOOP
      dbms_output.put_line('haha');
    END LOOP;

    c.for循环

    FOR a in 10 .. 20 LOOP
      dbms_output.put_line('value of a: ' || a);
    END LOOP;

    (5).游标

        Oracle会创建一个存储区域,被称为上下文区域,用于处理SQL语句,其中包含需要处理的语句,例如所有的信息,行数处理,等等。

        游标是指向这一上下文的区域。 PL/SQL通过控制光标在上下文区域。游标持有的行(一个或多个)SQL语句返回。行集合光标保持的被称为活动集合。

    a.下表是常用的游标属性

    属性

    描述

    %FOUND

    如果DML语句执行后影响有数据被更新或DQL查到了结果,返回true。否则,返回false。

    %NOTFOUND

    如果DML语句执行后影响有数据被更新或DQL查到了结果,返回false。否则,返回true。

    %ISOPEN

    游标打开时返回true,反之,返回false。

    %ROWCOUNT

    返回DML执行后影响的行数。

    b.使用游标

    声明游标定义游标的名称和相关的SELECT语句:

    CURSOR cur_cdd IS SELECT s_id, s_name FROM student;

    打开游标游标分配内存,使得它准备取的SQL语句转换成它返回的行:

    OPEN cur_cdd;

    抓取游标中的数据,可用LIMIT关键字来限制条数,如果没有默认每次抓取一条:

    FETCH cur_cdd INTO id, name ;

    关闭游标来释放分配的内存:

    CLOSE cur_cdd;

    3.pl/sql处理存储过程

    (1).新建存储过程:右键procedures,点击new,弹出PROCEDURE框,再点击OK,如下图:

     

    (2).在下面的编辑区,编写存储过程脚本

     

    (3).在这里我们编写一个demo_cdd存储过程,要求输出“hello world”,如下图:

     

    (4).右键刚才新建的存储过程名称,点击“Test”,在点击执行按钮

     

    4.案例实战

    场景:

    有表student(s_no, s_name, s_age, s_grade),其中s_no-学号,也是主键,是从1开始向上排的(例如:第一个学生学号是1,第二个是2,一次类推);s_name-学生姓名;s_age-学生年龄;s_grade-年级;这张表的数据量有几千万甚至上亿。一个学年结束了,我要让这些学生全部升一年级,即,让s_grade字段加1。

    这条sql,写出来如下:

    update student set s_grade=s_grade+1

    分析:

    如果我们直接运行运行这条sql,因数据量太大会把数据库undo表空间撑爆,从而发生异常。那我们来写个存储过程,进行批量更新,我们每10万条提交一次。

    CREATE OR REPLACE PROCEDURE process_student is
    total NUMBER := 0;
    i NUMBER := 0;
    BEGIN
      SELECT COUNT(1) INTO total FROM student;
      WHILE i<=total LOOP
        UPDATE student SET grade=grade+1 WHERE s_no=i;
        i := i + 1;
        IF i >= 100000 THEN
          COMMIT;
        END IF;
      END LOOP;
      dbms_output.put_line('finished!');
    END;
    

    四.存储过程进阶

           在上面的案例中,我们的存储过程处理完所有数据要多长时间呢?事实我没有等到它执行完,在我可接受的时间范围内它没有完成。那么对于处理这种千万级数据量的情况,存储过程是不是束手无策呢?答案是否定的,接下来我们看看其他绝招。

           我们先来分析下执行过程的执行过程:一个存储过程编译后,在一条语句一条语句的执行时,如果遇到pl/sql语句就拿去给pl/sql引擎执行,如果遇到sql语句就送到sql引擎执行,然后把执行结果再返回给pl/sql引擎。遇到一个大数据量的更新,则执行焦点(正在执行的,状态处于ACTIVE)会不断的来回切换。

           Pl/SQL与SQL引擎之间的通信则称之为上下文切换,过多的上下文切换将带来过量的性能负载。最终导致效率降低,处理速度缓慢。

           从Oracle8i开始PL/SQL引入了两个新的数据操纵语句:FORALLBUIK COLLECT,这些语句大大滴减少了上下文切换次数(一次切换多次执行),同时提高DML性能,因此运用了这些语句的存储过程在处理大量数据时速度简直和飞一样。

    1.BUIK COLLECT

        Oracle8i中首次引入了Bulk Collect特性,Bulk Collect会能进行批量检索,会将检索结果结果一次性绑定到一个集合变量中,而不是通过游标cursor一条一条的检索处理。可以在SELECT INTO、FETCH INTO、RETURNING INTO语句中使用BULK COLLECT,接下来我们一起看看这些语句中是如何使用BULK COLLECT的。

    (1).SELECT INTO

    查出来一个结果集合赋值给一个集合变量。

    语法结构是:

    SELECT field BULK COLLECT INTO var_conllect FROM table where colStatement;

    说明:

           field:要查询的字段,可以是一个或多个(要保证和后面的集合变量要向对应)。

           var_collect:集合变量(联合数组等),用来存放查到的结果。

           table:表名,要查询的表。

           colStatement:后面过滤条件语句。比如s_age < 10;

    例子:查出年龄小于10岁的学生姓名赋值给数组arr_name变量

    SELECT s_name BULK COLLECT INTO arr_name FROM s_age < 10;

    (2).FETCH INTO

    从一个集合中抓取一部分数据赋值给一个集合变量。

    语法结构如下:

    FETCH cur1 BULK COLLECT INTO var_collect [LIMIT rows]

    说明:

            cur1:是个数据集合,例如是个游标。

            var_collect:含义同上。

            [LIMIT rows]:可有可无,限制每次抓取的数据量。不写的话,默认每次一条数据。

    例子:给年龄小于10岁的学生的年级降一级。

    --查询年龄小于10岁的学生的学号放在游标cur_no里
    CURSOR cur_no IS 
    		SELECT s_no FROM student WHERE s_age < 10;
    
    --声明了一个联合数组类型,元素类型和游标cur_no每个元素的类型一致
    TYPE ARR_NO IS VARRAY(10) OF cur_no%ROWTYPE;
    
    --声明一个该数组类型的变量no
    no ARR_NO;
    BEGIN
      FETCH cur_no BULK COLLECT INTO no LIMIT 100;
      FORALL i IN 1..no.count SAVE EXCEPTONS
    	UPDATE student SET s_grade=s_grade-1 WHERE no(i);
    END;
    

    说明:先查出年龄小于10岁的学生的学号放在游标里,再每次从游标里拿出100个学号,进行更新,给他们的年级降一级。

    (3).RETURNING

    BULK COLLECT除了与SELECT,FETCH进行批量绑定之外,还可以与INSERT,DELETE,UPDATE语句结合使用,可以返回这些DML语句执行后所影响的记录内容(某些字段)。

    再看一眼学生表的字段情况:student(s_no, s_name, s_age, s_grade)

    语法结构如下:

    DMLStatement
           RETURNING field BULK COLLECT INTO var_field;

    说明:

            DMLStatement:是一个DML语句。

            field:是这个表的某个字段,当然也可以写多个逗号隔开(field1,field2, field3)。

            var_field:一个类型为该字段类型的集合,多个的话用逗号隔开,如下:

            (var_field1, var_field2, var_field3)

     

    例子:获取那些因为年龄小于10岁而年级被将一级的学生的姓名集合。

    TYPE NAME_COLLECT IS TABLE OF student.s_name%TYPE;
    names NAME_COLLECT;
    BEGIN
      UPDATE student SET s_grade=s_grade-1 WHERE s_age < 10
      RETURNING s_name BULK COLLECT INTO names;
    END;

    说明:

           NAME_COLLECT:是一个集合类型,类型是student表的name字段的类型。

           names:定义了一个NAME_COLLECT类型的变量。

    (4).注意事项

    a.不能对使用字符串类型作键的关联数组使用BULK COLLECT 子句。

    b.只能在服务器端的程序中使用BULK COLLECT,如果在客户端使用,就会产生一个不支持这个特性的错误。

    c.BULK COLLECT INTO 的目标对象必须是集合类型。

    d.复合目标(如对象类型)不能在RETURNING INTO 子句中使用。

    e.如果有多个隐式的数据类型转换的情况存在,多重复合目标就不能在BULK COLLECT INTO 子句中使用。

    f.如果有一个隐式的数据类型转换,复合目标的集合(如对象类型集合)就不能用于BULK COLLECTINTO 子句中。

    2.FORALL

    (1).语法

    FORALL index IN bounds [SAVE EXCEPTIONS]     
         sqlStatement;

    说明:

            index是指下标;

            bounds是一个边界,形式是start..end

            [SAVE EXCEPTIONS] 可写可不写,这个下面介绍;

            sqlStatement是一个DML语句,这里有且仅有一个sql语句;

    例子:

    --例子1:移除年级是5到10之间的学生
    FORALL i IN 5..10
           DELETE FROM student where s_grade=i;
    --例子:2,arr是一个数组,存着要升高一年级的学生名称
    FORALL s IN 1..arr.count SAVE EXCEPTIONS
           UPDATE student SET s_grade=s_grade+1 WHERE s_name=arr(i);

    (2).SAVE EXCEPTIONS

    通常情况写我们在执行DML语句时,可能会遇到异常,可能致使某个语句或整个事务回滚。如果我们写FORALL语句时没有用SAVE EXCEPTIONS语句,那么DML语句会在执行到一半的时候停下来。

           如果我们的FORALL语句后使用了SAVE EXCEPTIONS语句,当在执行过程中如果遇到异常,数据处理会继续向下进行,发生的异常信息会保存到SQL%BULK_EXCEPTONS的游标属性中,该游标属性是个记录集合,每条记录有两个字段,例如:(1, 02300);

           ERROR_INDEX:该字段会存储发生异常的FORALL语句的迭代编号;

           ERROR_CODE:存储对应异常的,oracle错误代码;

    SQL%BULK_EXCEPTONS这个异常信息总是存储着最近一次执行的FORALL语句可能发生的异常。而这个异常记录集合异常的个数则由它的COUNT属性表示,即:

           SQL%BULK_EXCEPTONS.COUNT,SQL%BULK_EXCEPTIONS有效的下标索引范围在1到%BULK_EXCEPTIONS.COUNT之间。

    (3). INDICES OF

    在Oracle数据库10g之前有一个重要的限制,该数据库从IN范围子句中的第一行到最后一行,依次读取集合的内容,如果在该范围内遇到一个未定义的行,Oracle数据库将引发ORA-22160异常事件:ORA-22160: element at index [N] does not exist。针对这一问题,Oracle后续又提供了两个新语句:INDICES OF 和 VALUES OF。

    接下来我们来看看这个INDICES OF语句,用于处理稀疏数组或包含有间隙的数组(例如:一个集合的某些元素被删除了)。

    该语句语法结构是:

    FORALL i INDICES OF collection [SAVE EXCEPTIONS]
    
           sqlStatement;

    说明:

    i:集合(嵌套表或联合数组)下标。

    collection:是这个集合。

    [SAVE EXCEPTIONS]和sqlStatement上面已经解释过。

    例子:arr_std是一个联合数组,每个元素包含(name,age,grade),现在要向student表插入数据。

    FORALL i IN INDICES OF arr_stu
           INSERT INTO student VALUES(
               arr_stu(i).name,
                  arr_stu(i).age,
                  arr_stu(i).grade
           );

    (4). VALUES OF

    VALUES OF适用情况:绑定数组可以是稀疏数组,也可以不是,但我只想使用该数组中元素的一个子集。VALUES OF选项可以指定FORALL语句中循环计数器的值来自于指定集合中元素的值。但是,VALUES OF在使用时有一些限制:

           如果VALUES OF子句中所使用的集合是联合数组,则必须使用PLS_INTEGER和BINARY_INTEGER进行索引,VALUES OF 子句中所使用的元素必须是PLS_INTEGER或BINARY_INTEGER;

           当VALUES OF 子句所引用的集合为空,则FORALL语句会导致异常;

    该语句的语法结构是:

    FORALL i IN VALUES OF collection [SAVE EXCEPTIONS]
           sqlStatement;

    说明:i和collection含义如上

    联合数组请看文章(或自行百度):https://blog.csdn.net/leshami/article/details/7372061

    3.pl/sql调试存储过程

    首先,当前这个用户得有能调试存储过程的权限,如果没有的话,以数据库管理员身份给你这个用户授权:

    --userName是你要拿到调试存储过程权限的用户名
    GRANT DEBUG ANY PROCEDURE,DEBUG CONNECT SESSION TO username;

    (1).右键一个存储过程名称,点击测试,如下图:

    这里我用的pl/sql是12.0.4版本的,下面截图中与低版本的pl/sql按钮位置都相同,只是图标不一样。

     

    (2).点击两次step into按钮,进入语句调试,如下图:

     

    (3).每点击一次step into按钮,会想下执行一条语句,也可以查看变量和表达式的值,如下图:

     

    查看变量值:在查看变量区域,在Variable列输入变量i,在Value列点击下,该变量的值就显示出来了。

    4.案例实战

    场景和上面的案例实战是同一个,如下:

    有表student(s_no, s_name, s_age, s_grade),其中s_no-学号,也是主键,是从1开始向上排的(例如:第一个学生学号是1,第二个是2,一次类推);s_name-学生姓名;s_age-学生年龄;s_grade-年级;这张表的数据量有几千万甚至上亿。一个学年结束了,我要让这些学生全部升一年级,即,让s_grade字段加1。

    这条sql,写出来如下:

    update student set s_grade=s_grade+1

    编写存储过程:

    (1).存储过程1

    名称为:process_student1,student表的s_no字段类型为varchar2(16)。

    CREATE OR REPLACE PROCEDURE process_student1 AS
        CURSOR CUR_STUDENT IS SELECT s_no FROM student;
        TYPE REC_STUDENT IS VARRAY(100000) OF VARCHAR2(16);
        students REC_STUDENT;
    BEGIN
      OPEN CUR_STUDENT;
      WHILE (TRUE) LOOP
        FETCH CUR_STUDENT BULK COLLECT INTO students LIMIT 100000;
        FORALL i IN 1..students.count SAVE EXCEPTIONS
          UPDATE student SET s_grade=s_grade+1 WHERE s_no=students(i);
        COMMIT;
        EXIT WHEN CUR_STUDENT%NOTFOUND OR CUR_STUDENT%NOTFOUND IS NULL;
      END LOO;
      dbms_output.put_line('finished');
    END;

    说明:

            把student表中要更新的记录的学号拿出来放在游标CUR_STUDENT,每次从这个游标里抓取10万条数据赋值给数组students,每次更新这10万条记录。循环进行直到游标里的数据全部抓取完。

            FETCH .. BULK COLLECT INTO .. LIMIT rows语句中:这个rows我测试目前最大可以为10万条。

    (2).存储过程2(ROWID)

           如果我们这个student表没有主键,也没有索引呢,该怎么来做呢?

    分析下:

           ROWNUM是伪列,每次获取结果后,然后在结果集里会产生一列,从1开始排,每次都是从1开始排。

            ROWID在每个表中,每条记录的ROWID都是唯一的。在这种情况下,我们可以用ROWID。但要注意的是,ROWID是一个类型,注意它和VARCHAR2之间的转换。有两个方法:ROWIDTOCHAR()是把ROWID类型转换为CHAR类型;CHARTOROWID()是把CAHR类型转换为ROWID类型。

    接下来我们编写存储过程process_student2,脚本如下:

    CREATE OR REPLACE PROCEDURE process_student1 AS
        CURSOR CUR_STUDENT IS SELECT ROWIDTOCHAR(ROWID) FROM student;
        TYPE REC_STUDENT IS VARRAY(100000) OF VARCHAR2(16);
        students REC_STUDENT;
    BEGIN
      OPEN CUR_STUDENT;
      WHILE (TRUE) LOOP
        FETCH CUR_STUDENT BULK COLLECT INTO students LIMIT 100000;
        FORALL i IN 1..students.count SAVE EXCEPTIONS
          UPDATE student SET s_grade=s_grade+1 WHERE ROWID=CHARTOROWID(students(i));
        COMMIT;
        EXIT WHEN CUR_STUDENT%NOTFOUND OR CUR_STUDENT%NOTFOUND IS NULL;
      END LOO;
      dbms_output.put_line('finished');
    END;

    说明:

           我们首先查到记录的ROWID并把它转换为CHAR类型,存放到游标CUR_STUDENT里,

    再每次抓取10万条数据赋值给数组进行更新,更新语句的WHERE条件时,又把数组元素是CAHR类型的rowid串转换为ROWID类型。

    附.参考资料

    存储过程基础:

           https://www.yiibai.com/plsql/plsql_basic_syntax.html

    存储过程进阶之FORALL:

           https://blog.csdn.net/leshami/article/details/7536926

           https://blog.csdn.net/jie1336950707/article/details/49966753

    存储过程进阶之BUIL COLLECT:

           https://blog.csdn.net/leeboy_wang/article/details/7991021

           https://blog.csdn.net/leshami/article/details/7545597

    联合数组:

           https://blog.csdn.net/leshami/article/details/7372061

    展开全文
  • MySQL数据库存储过程讲解与实例

    万次阅读 多人点赞 2018-06-03 00:48:17
    SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。...

    存储过程简介

        SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。

        存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式。

        存储过程的优点:

        (1).增强SQL语言的功能和灵活性:存储过程可以用控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。

        (2).标准组件式编程:存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,对应用程序源代码毫无影响。

        (3).较快的执行速度:如果某一操作包含大量的Transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。

        (4).减少网络流量:针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的Transaction-SQL语句被组织进存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大减少网络流量并降低了网络负载。

        (5).作为一种安全机制来充分利用:通过对执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。

    MySQL的存储过程

        存储过程是数据库的一个重要的功能,MySQL 5.0以前并不支持存储过程,这使得MySQL在应用上大打折扣。好在MySQL 5.0开始支持存储过程,这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程的灵活性。

    MySQL存储过程的创建

        语法

    CREATE PROCEDURE  过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]]) [特性 ...] 过程体

    DELIMITER //
      CREATE PROCEDURE myproc(OUT s int)
        BEGIN
          SELECT COUNT(*) INTO s FROM students;
        END
        //
    DELIMITER ;
        分隔符

        MySQL默认以";"为分隔符,如果没有声明分割符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以要事先用“DELIMITER //”声明当前段分隔符,让编译器把两个"//"之间的内容当做存储过程的代码,不会执行这些代码;“DELIMITER ;”的意为把分隔符还原。

        参数

        存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用","分割开。MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT:

    IN参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值OUT:该值可在存储过程内部被改变,并可返回INOUT:调用时指定,并且可被改变和返回

        过程体

        过程体的开始与结束使用BEGIN与END进行标识。

    MySQL实例与讲解

    1. 创建一存储过程,求l+2+3+…+n,并打印结果

    先使用MySQL语句创建存储过程,再使用call语句调用这一存储过程查看结果,可以看到由于未输入n的值,sum结果为0。

    2.调用上面addresult存储过程,打印l十2+3+…+10的结果

    在第一题的addresult过程基础上,加上一条“set n=10”语句,设定n的值,调用该过程后打印结果,可以看到结果为sum=1+2+3+...+10=55。

     

    3. 修改上述存储过程addresult1,使得n为输入参数,其具体值由用户调用此存储过程时指定。

    在这里需要注意的是,MySQL存储过程只能改名字和定义,不能改里面的内容。要删了重新建。所以这里选择重新建立一个addresult1过程,调用后输入n,查看打印结果。

     

    4.上面修改后的addresult1存储过程,打印l+2+3+…+100的结果

    调用上述过程,输入参数n为100,可以看到打印结果中sum=5050,结果正确。


    5.
    修改上述存储过程addresult2n参数设定默认值为10,并改设sum为输出参数,让主程序能够接收计算结果。

    3中存储过程中的“in n int”修改为“out sum int”,并在存储过程中设定n默认值为10。

     

    6.调用上面修改后的addresult2存储过程,设置变量接收计算l+2+3+…+10的结果

    调用addresult2过程,可以看到输出结果sum=55。

     

    7.创建一存储过程Proc_Student,用于显示学号为“0102”的学生基本信息包括学号、姓名、性别和系

    创建存储过程,将查询语句写在存储过程中,相当于将一个查询语句封装在存储过程中,通过调用这个存储过程,便可执行该查询操作。

     

    8.创建一存储过程Stu_grade通过读取某门课的编号求出不及格的学生的学号

    同上一题,将查询过程封装在存储过程中,并且使用“int ID int”来实现课程编号的自定义输入,再根据输入的课程编号进行查询。

     

    9.调用上面的存储过程Stu_grade,求出课程编号为“0101”的不及格的学生

    调用存储过程Stu_grade,输入课程编号为“0101”,查看打印结果。

     

    10.创建一存储过程avgGrade,通过读取学生的学号以参数形式返回该学生的平均分

    在创建存储过程时,设定学号为输入,平均成绩为输出,且因为平均成绩可能出现小数,所以设定其数据类型为float。通过select语句将平均分以参数形式返回。

     

    11.调用上面的存储过程avgGrade,求出学号为“990102014”的平均分

    输入学号与输出参数,可以看到该学生的平均成绩被打印出来。

     

    12.删除上述存储过程avgGrade

    对于存储过程的删除,使用drop语句即可。

     

    13.创建存储过程search,该存储过程有三个参数,分别为t、p1,p2,根据这些参数,找出书名与t有关,价格在p1与p2(p2>=p1)之间的书的编号,书名,价格,出舨日期。如果用户调用时没有指定t参数的值.则表示可为任意值,如用户没有指定p2,则书本价格没有上限。用到的关系为:titles (title_id,title,price,pubdate)。

     



    14.调用上面的存储过程search,求出书名与computer有关而且价格小于$20大于$10的书。

    调用存储过程search,将参数computer,10,20传入,查看打印结果。



     


    总结

        本次主要是掌握了对于存储过程的使用,总的来说,存储过程实际上类似于C++中的函数,而在C++中我们是需要在创建这一过程的文件中去调用这一函数,但是对于存储过程来说,相当于是将这一操作过程存储在数据库中,可以使用call与对其进行调用,并输入或者输出一些参数和结果。

        印象最深的是类似“in n int”和“out sum int”这样的对于输入输出的定义,通过查看相关博客,可以总结如下对于输入输出定义的使用规律:

        MySQL存储过程的参数用在存储过程的定义,共有三种参数类型

        IN,OUT,INOUT
        格式为:Create procedure|function([[IN |OUT |INOUT ] 参数名 数据类形...])

        IN 输入参数
            表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值

        OUT 输出参数
            该值可在存储过程内部被改变,并可返回

        INOUT 输入输出参数
            调用时指定,并且可被改变和返回

        IN 和 OUT在实验中已有体会,主要是对INOUT的理解,这里引用一个例子:

     

    参数inout的使用实例(既能输入一个值又能传出来一个值)
        语句功能:传一个年龄,自动让年龄增长10岁
        create procedure p3(inout age int)
        begin
        set age:=age+10;
        end
        其中:调用的时候,inout型的参数值既是输入类型又是输出类型,给它一个值,值不是变量,因此我们需要先设置一个变量并初始化这个值,调用的时候直接传这个变量即可。
        set @currentAge=8$
        call p3(@currentAge)$
        select @currentAge$
        创建并执行完存储过程,运行结果如下:
            

     

    另外,更多关于数据库、网络技术、信息安全等方面的文章,感兴趣的(尤其是想打CTF的)欢迎来我的博客上看看

    展开全文
  • SQL存储过程使用介绍

    万次阅读 多人点赞 2017-04-25 13:54:13
    1. 存储过程的概念存储过程 (Stored Procedure) 是在大型数据库系统中 , 一组为了完成特定功能的 SQL 语句集 , 存储在数据库中 , 经过第一次编译后再次调用不需要再次编译 , 用户通过指定存储过程的名字并给出参数 ...
  • 彻底搞懂Android文件存储---内部存储,外部存储以及各种存储路径解惑 1、Android中内部存储,外部存储的概念 2、清除数据和清除缓存到底清除了什么数据 3、/storage/sdcard,/sdcard,/mnt/sdcard,/storage/...
  • 从头开始学MySQL-------存储过程与存储函数(1)

    万次阅读 多人点赞 2018-11-03 17:00:19
    10.1.1 创建存储过程 存储过程就是一条或者多条SQL语句的集合,可以视为批文件。它可以定义批量插入的语句,也可以定义一个接收不同条件的SQL。 创建存储过程的语句为 CREATE PROCEDURE,创建存储函数的语句为...
  • Android 文件外/内部存储的获取各种存储目录路径

    万次阅读 多人点赞 2018-06-12 14:51:50
    前言 对于任何一个应用来说,无论是PC端应用还是Android应用,存储肯定是必不可少的。对于很多做Android开发的同学来说,可能认为文件存储很简单,调用一些诸如getFilesDir,getExternalStorageDirectory方法行了,...
  • 计算机存储的发展(块存储,文件存储,对象存储

    万次阅读 多人点赞 2018-09-15 15:04:08
    存储 DAS SAN 文件存储存储和文件存储异同: 对象存储 1、对象 2、对象存储设备 3、元数据服务器(Metadata Server,MDS) 4、对象存储系统的客户端Client 三者之间异同比较 参考文献 如果要实现一个...
  • Oracle存储过程及举例(几种参数情况的存储过程)

    万次阅读 多人点赞 2017-05-06 22:22:50
    Oracle存储过程及举例(几种参数情况的存储过程)
  • 三种存储类型和三种存储方式

    万次阅读 多人点赞 2019-01-22 17:07:39
    存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备(Object-based Storage Device)简称OSD。 本质是一样...
  • FreeNAS家庭工作存储搭建指南(一)——硬件篇

    万次阅读 多人点赞 2019-07-10 01:34:51
    FreeNAS 是一款开源免费的专门用于构建 NAS 服务器的专业操作系统。本文介绍一种基于 FreeNAS 来 DIY 搭建家庭工作存储的方案,特点在于灵活性和可扩展性。
  • 分布式存储与传统存储架构

    万次阅读 2019-04-10 20:34:58
    随着主机、磁盘、网络等技术的发展,对于承载大量数据存储的服务器来说,服务器内置存储空间,或者说内置磁盘往往不足以满足存储需要或者虽然能满足要求,但各个服务器之间独立,严重降低了磁盘的利用率。...
  • 存储单元,存储字长,存储字,.存储容量

    万次阅读 多人点赞 2018-04-09 11:34:20
    1.1百度上:存储字长:一个存储单元存储一串二进制代码(存储字),这串二进制代码的位数称为存储字长,存储字长可以是8位、16位、32位等。—–再结合存储单元的定义,所以存储字长是8位 1.2百度上:存储字:是指...
  • 对象存储(云存储)概述

    万次阅读 多人点赞 2019-03-08 17:54:09
    文章目录三种存储形态1、块存储2、文件存储3、对象存储对象存储对象存储需求对象存储含义对象存储与传统网络存储的区别扩展知识:NAS与SAN概述1、NAS(Network Attached Storage)优点局限2、SAN(Storage Area ...
  • 使用阿里云OSS存储文件

    万次阅读 2020-10-31 23:46:36
    使用阿里云OSS存储文件 创建 bucket 创建 RAM 账号 创建 用户组,并授予 OSS 相关权限,将刚刚创建的 RAM 账号添加进该用户组
  • 开源分布式存储系统的对比

    万次阅读 多人点赞 2018-04-20 16:32:49
    我们在选型开源分布式存储系统框架之前需要对不同的框架进行调研。 所有的开源存储系统介绍链接 存储系统对比 目前比较热门的分布式文件系统有如下几种: Ceph,GlusterFS,Sheepdog,Lustre,Swift,Cinder,TFS,HDFS...
  • mysql 在存储过程中输出日志信息

    万次阅读 2018-04-02 17:17:05
    mysql 在存储过程中输出日志信息 更多原创性能测试文章关注 十年性能测试专家&7DGroup公众号 直接用select 打印输出 SELECT 'Comment'; 用concat连接变量输出 declare myvar INT default 0; SET myvar...
  • 顺序存储在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构。特点:随机存取表中元素。插入和删除操作需要移动元素。链接存储在计算机中用一组任意的存储单元存储线性表的...
  • 在此收集了一些厂商的服务器存储设备的默认管理口信息,以供大家日后运维时方便查找,若有错误的地方请指正,谢谢! 服务器管理口信息: 设备类型 设备型号 默认管理IP 默认用户名 默认密码 IBM...
  • 顺序存储结构和链式存储结构的优缺点比较

    万次阅读 多人点赞 2018-10-09 17:45:34
    顺序存储结构和链式存储结构的比较 优缺点 顺序存储时,相邻数据元素的存放地址也相邻(逻辑与物理统一);要求内存中可用存储单元的地址必须是连续的。 优点:存储密度大(=1),存储空间利用率高。 缺点:...
  • 存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储。 顺序结构和链接结构适用在内存结构中。 索引结构和散列结构适用在外存与内存交互结构。 顺序存储:在计算机中用一组地址连续的存储单元依次...
  • 存储 VS 列存储

    万次阅读 多人点赞 2018-07-06 12:56:03
    概述目前大数据存储有两种方案可供选择:行存储(Row-Based)和列存储(Column-Based)。业界对两种存储方案有很多争持,集中焦点是:谁能够更有效地处理海量数据,且兼顾安全、可靠、完整性。从目前发展情况看,关系...
  • 首先看看课本的索引存储结构的解析 索引表里必须存关键字这一项,这就出现很大的冗余 但是散列存储(哈希存储)的区别特殊性:体现在它的关键码能确定数据元素的存储位置;还可以用来制作缓存,在没有redis等缓存...
  • 存储基础知识

    万次阅读 2018-05-17 12:52:25
    存储的发展历程 什么是存储存储:就是根据不同的应用环境通过采取合理、安全、有效的方式将数据保存到某些截止上并能保证有效的访问。 当前存储的主要体系结构有三种:DAS、NAS、SAN。 存储发展历程的两...
  • 首先,我说下块存储。块存储可以看作为是裸盘,最明显的特征是不能被操作系统直接访问。可以通过划分逻辑卷、做RAID、LVM(逻辑卷)等方式将它格式化,可以格式化为你所指定的文件系统(Ext3,Ext4,NTFS,FAT32等)...
  • https://blog.csdn.net/enweitech/article/details/51445087 块存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象...
  • mysql手册07_存储引擎

    万次阅读 2020-08-15 17:30:45
    mysql手册07_存储引擎 存储引擎其实就是对于数据库文件的一种存取机制,实现存储数据,建立索引,以及更新和查询数据等技术的方式。 存储引擎是建立在 数据表 层面上的,同一数据库的不同表可以建立不同的存储引擎...
  • 本质是一样的,底层都是块存储,只是在对外接口上表现不一致,分别应用于不同的业务场景。 分布式存储的应用场景相对于其存储接口,现在流行分为三种: 对象存储: 也就是通常意义的键值存储,其接口就是简单的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,274,346
精华内容 509,738
关键字:

存储