学习MYSQL存储过程_MySQL
一、 简介
存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。
虽然常用术语是存储过程(stored procedure),但MySQL实际上实现了两中类型,除了存储过程外,还有存储函数(stored routine),它们统称为存储例程。
二、基本格式
1、存储过程
CREATE PROCEDURE 过程名 ([过程参数[,...]])
[特性 ...] 过程体
如创建: CEATE PROCEDURE p1 (a INT)
SELECT a;
调用一下:CALL p1(8);
将显示:
+------+
| a |
+------+
| 8 |
+------+
1 row in set (0.00 sec)
2、存储函数
CREATE FUNCTION 函数名 ([函数参数[,...]])
RETURNS 返回类型
[特性 ...] 函数体
如创建:CREATE FUNCTION f1 (x INT)
RETURNS INT
RETURN x; /* 过程函数一次只能返回一个值
调用一下:SELECT f1 (3);
将显示:
+-------+
| f1(3) |
+-------+
| 3 |
+-------+
1 row in set (0.00 sec)
3、过程参数
[ IN | OUT | INOUT ] 参数名 参数类型
4、函数参数
参数名 参数类型
5、返回类型
有效的MySQL数据类型即可
6、过程体/函数体格式如下
BEGIN
有效的SQL语句
END
7、特性(一般不要求)
LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
8、存储过程中参数的IN,OUT,INOUT类型
存储过程可以接受输入参数,并把参数返回给调用方。不过,对于每个参数,需要声明其参数名、数据类型,还要指定此参数是用于向过程传递信息,还是从过程传回信息,或是二者兼有。
为声明参数的作用,使用如下3个关键字之一:
˜ IN : IN参数只用来向过程传递信息,为默认值。
˜ OUT : OUT参数只用来从过程传回信息。
˜ INOUT : INOUT参数可以向过程传递信息,如果值改变,则可再从过程外调用。
如果仅仅想把数据传给 MySQL 存储过程,那就使用“in” 类型参数;如果仅仅从 MySQL 存储过程返回值,那就使用“out” 类型参数;如果需要把数据传给 MySQL 存储过程,还要经过一些计算后再传回给我们,此时,要使用“inout” 类型参数。
对于任何声明为OUT或INOUT的参数,,当调用存储过程时需要在参数名前加上@符号,这样该参数就可以在过程外调用了。
下面举三个实例:MySQL 存储过程 “in” 参数:跟 C 语言的函数参数的值传递类似, MySQL 存储过程内部可能会修改此参数,但对 in 类型参数的修改,对调用者(caller)来说是不可见的(not visible)。
create procedure pr_param_in( in id int -- in 类型的 MySQL 存储过程参数)begin if (id is not null) then set id = id + 1; end if; select id as id_inner;end;set @id = 10; call pr_param_in(@id); select @id as id_out;mysql> call pr_param_in(@id);+----------+| id_inner |+----------+| 11 |+----------+ mysql> select @id as id_out;+--------+| id_out |+--------+| 10 |+--------+可以看到:用户变量 @id 传入值为 10,执行存储过程后,在过程内部值为:11(id_inner),但外部变量值依旧为:10(id_out)。
MySQL 存储过程 “out” 参数:从存储过程内部传值给调用者。在存储过程内部,该参数初始值为 null,无论调用者是否给存储过程参数设置值。
create procedure pr_param_out( out id int)begin select id as id_inner_1; /* id 初始值为 null*/ if (id is not null) then set id = id + 1; select id as id_inner_2; else select 1 into id; end if; select id as id_inner_3;end;set @id = 10; call pr_param_out(@id); select @id as id_out;mysql> set @id = 10;mysql>mysql> call pr_param_out(@id); /*外部变量不能传给存储过程*/+------------+| id_inner_1 |+------------+| NULL |+------------+ +------------+| id_inner_3 |+------------+| 1 |+------------+ mysql> select @id as id_out; /*过程将改变的值传给外部变量*/+--------+| id_out |+--------+| 1 |+--------+可以看出,虽然我们设置了用户定义变量 @id 为 10,传递 @id 给存储过程后,在存储过程内部,id 的初始值总是 null(id_inner_1)。最后 id 值(id_out = 1)传回给调用者。
MySQL 存储过程 inout 参数跟 out 类似,都可以从存储过程内部传值给调用者。不同的是:调用者还可以通过 inout 参数传递值给存储过程。
drop procedure if exists pr_param_inout; create procedure pr_param_inout( inout id int)begin select id as id_inner_1; -- id 值为调用者传进来的值 if (id is not null) then set id = id + 1; select id as id_inner_2; else select 1 into id; end if; select id as id_inner_3;end;set @id = 10; call pr_param_inout(@id); select @id as id_out;mysql> set @id = 10; mysql>mysql> call pr_param_inout(@id);+------------+| id_inner_1 |+------------+| 10 |+------------+ +------------+| id_inner_2 |+------------+| 11 |+------------+ +------------+| id_inner_3 |+------------+| 11 |+------------+mysql>mysql> select @id as id_out;+--------+| id_out |+--------+| 11 |+--------+从结果可以看出:我们把 @id(10),传给存储过程后,存储过程最后又把计算结果值 11(id_inner_3)传回给调用者。 MySQL 存储过程 inout 参数的行为跟 C 语言函数中的引用传值类似。
通过以上例子:如果仅仅想把数据传给 MySQL 存储过程,那就使用“in” 类型参数;如果仅仅从 MySQL 存储过程返回值,那就使用“out” 类型参数;如果需要把数据传给 MySQL 存储过程,还要经过一些计算后再传回给我们,此时,要使用“inout” 类型参数。
9、声明和设置变量
(1) 声明变量
在存储例程使用局部变量之前,必须声明局部变量,变量声明通过DECLARE语句实现,其原型如下:
DECLARE variable_name TYPE ;
如:DECLARE x VARCHAR(254);
在声明变量时,声明必须放在BEGIN/END块中。此外声明必须在执行该块任何其它语句之前进行。
(2) 设置变量
SET语句用来设置声明的存储例程变量值。其原型如下:
SET variable_name =value;
如下声明和设置变量过程:
DECLARE x INT;
SET x = 155;
也可使用SELECT…..INTO语句设置变量。
如:
SELECT 155 INTO x;
当然,此变量是声明该变量的BEGIN/END块作用范围内的一个局部变量。如果希望在存储例程外使用此变量,需要将其作为OUT变量传递。
10、执行存储例程
执行存储例程一般是通过CALL和SELECT语句来完成的。
三、多语句存储例程
单语句存储例程非常有用,但存储例程的真正功能在于它能够封装和执行多个SQL语句。
下面介绍创建多语句存储例程时常用的语法。
1、BEGIN和END
当创建多语句存储例程时,需要将语句包围在BEGIN/END块中。
此块的原型如下:
BEGIN
statement 1;
statement 2;
……
statement N;
END
注意,块中每条语句必须以分号结尾。
2、条件语句
˜ IF-ELSEIF-ELSE语句
和C语言中if语句相似。
其原型如下:
IF condition1 THEN
statement1;
ELSEIF condition2 THEN
Statement2;
…….
END IF
˜ CASE语句
需要比较一组可能的值时CASE语句很有用。也是一种条件判断语句。
其原型如下:
CASE
WHEN condition1 THEN statement1;
WHEN condition2 THEN statement2;
………
END CASE;
3、迭代
有些任务需要能够重复地执行一组语句。下面介绍能够迭代执行和退出循环的各种方法。
˜ ITERATE语句
执行ITERATE语句将使嵌入该语句的LOOP、REPEAT或WHILE循环返回顶部,并在此执行。
其原型如下:
ITERATE label
˜ LEAVE语句
在得到变量的值或特定任务的结果后,可能希望通过LEAVE命令立即退出循环或BEGIN/END块。
其原型如下:
LEAVE label
˜ LOOP语句
LOOP语句将不断的迭代处理定义在其代码块中的一组语句,直到遇到LEAVE为止。
其原型如下:
[begin_label:] LOOP
Statement_list
END LOOP [end_label]
˜ REPEAT语句
REPEAT语句在操作上几乎与WHILE相同,很想C语言中的DO….WHERE语句。
其原型如下:
REPEAT
Statement_list
UNTIL condition
END REPEAT
˜ WHILE语句
其原型如下:
WHILE condition DO
Statement_list
END WHILE
下面写一个循环语句的存储过程:
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p2` $$
CREATE PROCEDURE `yyw`.`p2` ()
BEGIN
declare v int;
set v=0;
LOOP_LABLE:loop
if v=3 then
set v=v+1;
ITERATE LOOP_LABLE;
end if;
insert into vs values(v); /*将循环值插入数据表vs中*/
set v=v+1;
if v>=5 then
leave LOOP_LABLE;
end if;
end loop;
END $$
DELIMITER ;
四、从另一个例程中调用例程
DELIMITER //
CREATE PROCEDURE p1()
BEGIN
Statement_list
END//
CREATE PROCEDURE p2()
BEGIN
Statement_list
END//
CREATE PROCEDURE p3()
BEGIN
CALL p1();
CALL p2();
END//
注意:直接采用MySQL的Administrator管理器编辑时,可以直接采用函数文本录入;
但若在脚本中自动导入存储过程或函数时,由于MySQL默认以";"为分隔符,则过程体的每一句都被MySQL以存储过程编译,则编译过程会报错;所以要事先用DELIMITER关键字申明当前段分隔符
用完了就把分隔符还原。 如下所示:
DELIMITER $$
Stored Procedures and Functions
DELIMITER ;
五、删除和查看存储例程
1、删除存储例程
要删除存储例程,可以执行DROP语句。
其原型如下:
DROP (PROCEDURE|FUNCTION) P_name;
2、查看例程状态
其原型如下:
SHOW (PROCEDURE|FUNCTION) STATUS LIKE ‘P_name’
如:
SHOW PROCEDURE STATUS LIKE ‘P3’/G;
注意: 使用/G选项以垂直格式显示输出信息。
3、查看例程的创建语法
通过SHOW CREATE语句可以查看创建特定例程所用的语法。
其原型如下;
SHOW CREATE (PROCEDURE|FUNCTION) Db_name.P_name
六、实例
一般在MySQL Query Browser中更方便的创建存储过程及修改内容。
(1)简单的加法运算
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p4` $$
CREATE DEFINER=`yang`@`10.10.19.161` PROCEDURE `p4`(a int,b int)
BEGIN
declare c int; /*声明的变量
if a is null then /*IF语句
set a = 0;
end if;
if b is null then
set b = 0;
end if;
set c = a + b;
select c as sum; /*结果显示c的值
END $$
DELIMITER ;
调用以下:CALL p4(3,4);
将显示:
+------+
| sum |
+------+
| 7 |
+------+
1 row in set (0.00 sec)
(2)存储过程中的循环语句、数据表数据的导入导出及SQL函数的使用
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p4` $$
CREATE DEFINER=`yang`@`10.10.19.161` PROCEDURE ‘pro_prime2’(in num int)
BEGIN
declare i,j,x,y int default 0; /*声明变量并默认为0*/
select yywID into j from text1; /*从数据表txte1中字段yywID的值赋给变量j*/
select 'count ',j; /*显示count字符和j的值*/
while i
pp1:while x if j%x=0 then /*if循环语句*/
set y=1;
leave pp1;
else
set x=x+1;
end if;
end while;
if y=1 then
set y=0;
else
set i=i+1;
insert into text2 values(j); /*将j的值插入数据表text2*/
end if;
set j=j+1; /*实现j的自增*/
end while;
END $$
DELIMITER ;
假如原先在数据库中分别建立表text1和text2,text1中有一个字段初始值为3,text2为空;
下面执行一下此存储过程:
mysql> CALL pro_prime2(5);
+--------+------+
| count | j |
+--------+------+
| count | 3 |
+--------+------+
1 row in set (0.00 sec)
mysql> select *from text2;
+-------+
| yywID |
+-------+
| 3 |
| 5 |
| 7 |
| 11 |
| 13 |
+-------+
5 rows in set (0.00 sec)
(3)用存储过程实现计算数据库中某个成绩表总分及平均分,并且调用过程后
能够自动显示基本信息(如学号、姓名、总分、平均分等)。
首先在数据库中建一个成绩表(命名为chengjibiao)如下:
+-----+------+--------+-------+--------+
| NUM | Name | Enlish | Maths | Physis |
+-----+------+--------+-------+--------+
| 1 | 杨业 | 92 | 87 | 96 |
| 2 | 剑锋 | 82 | 98 | 93 |
| 3 | 张美 | 96 | 86 | 94 |
| 4 | 张文 | 76 | 99 | 95 |
| 5 | 叶倩 | 97 | 86 | 88 |
| 6 | 方文 | 87 | 96 | 94 |
| 7 | 李丽 | 97 | 86 | 83 |
| 8 | 贾宇 | 67 | 89 | 77 |
| 9 | 王勃 | 89 | 67 | 75 |
| 10 | 刘三 | 85 | 78 | 95 |
+-----+------+--------+-------+--------+
‚ 用SQL语句写存储过程p1
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p1` $$
CREATE DEFINER=`yang`@`10.10.19.161` PROCEDURE `p1`(N int)
BEGIN
declare a int; /* 变量的声明 */
declare b int;
declare c int;
declare d int;
declare e int;
declare f char(100);
declare g decimal(4,2);
set e=1;
create table zongping (NUM int,Name char(255),Enlish int,Maths int,Physis int,Total int,aver decimal( 4,2)); /* 建一个数据表以存放要显示的内容*/
repeat /* 引进一个REPEAT循环,来计算每位学生总分及平均分*/
select Enlish,Maths,Physis,Name into a,b,c,f from chengjibiao where NUM=e;
/* 导出数据库chengjibiao中的三门成绩及姓名,并把它们分别赋给变量a,b,c,f;*/
set d=a+b+c; /*求和*/
set g=(a+b+c)/3; /*求平均分*/
insert into zongping (NUM,Name,Enlish,Maths,Physis,Total,aver) values (e,f,a,b,c,d,g);
/*将学号,姓名,三门成绩,总分,平均分的数据插入新建的数据表zongping中
set e=e+1; /*该条件可结束循环*/
until e=N /*N是调用存储过程时根据学生数目来设定的*/
end repeat;
select *from zongping; /* 以数据表的形式显示运行结果*/
drop table zongping; /*显示结果后删除表,也可不删*/
END $$
DELIMITER ;
l 调用存储过程
CALL P1 (11); /* 因为原成绩表中有10列数据 ,故设N=11,也可根据不同的成绩表另设
显示结果如下:
+------+------+--------+-------+--------+-------+
| Name | Enlish | Maths | Physis | Total | Aver |
+------+------+--------+-------+--------+-------+-------+
| 1 | 杨业 | 92 | 87 | 96 | 275 | 91.67 |
| 2 | 剑锋 | 82 | 98 | 93 | 273 | 91.00 |
| 3 | 张美 | 96 | 86 | 94 | 276 | 92.00 |
| 4 | 姜文 | 76 | 99 | 95 | 270 | 90.00 |
| 5 | 叶倩 | 97 | 86 | 88 | 271 | 90.33 |
| 6 | 方文 | 87 | 96 | 94 | 277 | 92.33 |
| 7 | 李丽 | 97 | 86 | 83 | 266 | 88.67 |
| 8 | 贾宇 | 67 | 89 | 77 | 233 | 77.67 |
| 9 | 王勃 | 89 | 67 | 75 | 231 | 77.00 |
| 10 | 刘三 | 85 | 78 | 95 | 258 | 86.00 |
+------+------+--------+-------+--------+-------+-------+

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











소셜 미디어의 급속한 발전으로 Xiaohongshu는 가장 인기 있는 소셜 플랫폼 중 하나가 되었습니다. 사용자는 Xiaohongshu 계정을 만들어 자신의 개인 신원을 표시하고 다른 사용자와 소통하고 상호 작용할 수 있습니다. 사용자의 Xiaohongshu 번호를 찾으려면 다음의 간단한 단계를 따르세요. 1. Xiaohongshu 계정을 사용하여 사용자를 찾는 방법은 무엇입니까? 1. Xiaohongshu 앱을 열고 오른쪽 하단에 있는 "검색" 버튼을 클릭한 다음 "메모" 옵션을 선택합니다. 2. 노트 목록에서 찾고자 하는 사용자가 게시한 노트를 찾아보세요. 클릭하시면 메모 세부정보 페이지로 이동합니다. 3. 노트 상세페이지에서 해당 사용자의 아바타 아래 '팔로우' 버튼을 클릭하여 해당 사용자의 개인 홈페이지로 진입합니다. 4. 이용자 개인 홈페이지 우측 상단의 점 3개 버튼 클릭 후 '개인정보' 선택

로컬 사용자 및 그룹 유틸리티는 컴퓨터 관리에 내장되어 있으며 콘솔에서 또는 독립적으로 액세스할 수 있습니다. 그러나 일부 사용자는 Windows 11에 로컬 사용자 및 그룹이 누락되어 있음을 발견합니다. 액세스 권한이 있는 일부 사용자에게는 이 스냅인이 이 버전의 Windows 10에서 작동하지 않을 수 있다는 메시지가 표시됩니다. 이 컴퓨터의 사용자 계정을 관리하려면 제어판의 사용자 계정 도구를 사용하십시오. 이 문제는 Windows 10의 이전 버전에서 보고되었으며 일반적으로 사용자 측의 문제 또는 감독으로 인해 발생합니다. Windows 11에서 로컬 사용자 및 그룹이 누락되는 이유는 무엇입니까? Windows Home 버전을 실행 중이며 Professional 버전 이상에서는 로컬 사용자 및 그룹을 사용할 수 있습니다. 활동

Ubuntu 시스템에서는 루트 사용자가 일반적으로 비활성화되어 있습니다. 루트 사용자를 활성화하려면 passwd 명령을 사용하여 비밀번호를 설정한 다음 su- 명령을 사용하여 루트로 로그인할 수 있습니다. 루트 사용자는 무제한 시스템 관리 권한을 가진 사용자입니다. 그는 파일, 사용자 관리, 소프트웨어 설치 및 제거, 시스템 구성 변경에 액세스하고 수정할 수 있는 권한을 가지고 있습니다. 루트 사용자와 일반 사용자 사이에는 분명한 차이가 있습니다. 루트 사용자는 시스템에서 가장 높은 권한과 더 넓은 제어 권한을 갖습니다. 루트 사용자는 일반 사용자가 할 수 없는 중요한 시스템 명령을 실행하고 시스템 파일을 편집할 수 있습니다. 이 가이드에서는 Ubuntu 루트 사용자, 루트로 로그인하는 방법, 일반 사용자와 어떻게 다른지 살펴보겠습니다. 알아채다

권한으로 인해 특정 폴더에 항상 액세스할 수 있는 것은 아닙니다. 오늘 가이드에서는 Windows 11의 기존 하드 드라이브에 있는 사용자 폴더에 액세스하는 방법을 보여 드리겠습니다. 프로세스는 간단하지만 드라이브 크기에 따라 시간이 걸릴 수 있으며 때로는 몇 시간이 걸릴 수도 있으므로 인내심을 갖고 이 가이드의 지침을 자세히 따르십시오. 기존 하드 드라이브에 있는 사용자 폴더에 액세스할 수 없는 이유는 무엇입니까? 사용자 폴더는 다른 컴퓨터의 소유이므로 수정할 수 없습니다. 이 폴더에 대한 소유권 외에는 어떤 권한도 없습니다. 오래된 하드 드라이브에서 사용자 파일을 여는 방법은 무엇입니까? 1. 폴더 소유권을 가져오고 권한을 변경합니다. 이전 사용자 디렉터리를 찾아 마우스 오른쪽 버튼으로 클릭하고 속성을 선택합니다. "안"으로 이동

sudo(수퍼유저 실행)는 일반 사용자가 루트 권한으로 특정 명령을 실행할 수 있도록 하는 Linux 및 Unix 시스템의 핵심 명령입니다. sudo의 기능은 주로 다음 측면에 반영됩니다. 권한 제어 제공: sudo는 사용자에게 일시적으로 수퍼유저 권한을 얻을 수 있는 권한을 부여하여 시스템 리소스와 민감한 작업을 엄격하게 제어합니다. 일반 사용자는 필요할 때만 sudo를 통해 임시 권한을 얻을 수 있으며, 항상 슈퍼유저로 로그인할 필요는 없습니다. 향상된 보안: sudo를 사용하면 일상적인 작업 중에 루트 계정을 사용하지 않아도 됩니다. 모든 작업에 루트 계정을 사용하면 올바르지 않거나 부주의한 작업에는 전체 권한이 부여되므로 예기치 않은 시스템 손상이 발생할 수 있습니다. 그리고

Microsoft는 Windows 503145511H22 이상에 대한 선택적 업데이트로 KB2를 대중에게 출시하기 시작했습니다. 이는 지원되는 영역의 Windows Copilot, 시작 메뉴 항목에 대한 미리 보기 지원, 작업 표시줄 그룹 해제 등을 포함하여 Windows 11 Moment 4 기능을 기본적으로 활성화하는 첫 번째 업데이트입니다. 또한 메모리 누수를 일으키는 잠재적인 성능 문제를 포함하여 여러 Windows 11 버그를 수정합니다. 하지만 아이러니하게도 2023년 9월의 선택적 업데이트는 업데이트를 설치하려는 사용자에게, 심지어 이미 설치한 사용자에게도 재앙이 될 것입니다. 많은 사용자가 이 Wi-Fi를 설치하지 않을 것입니다.

Ubuntu 시스템에 많은 사용자가 추가되었습니다. 더 이상 사용하지 않는 사용자를 삭제하고 싶습니다. 아래의 자세한 튜토리얼을 살펴보겠습니다. 1. 터미널 명령줄을 열고 userdel 명령을 사용하여 지정된 사용자를 삭제합니다. 2. 삭제 시 반드시 일반 사용자 디렉터리에 있어야 합니다. 아래 그림과 같이 이 권한이 없습니다. 3. 삭제 명령을 실행한 후 실제로 삭제되었는지 어떻게 판단할 수 있나요? 다음으로 아래 그림과 같이 cat 명령을 사용하여 passwd 파일을 엽니다. 4. 삭제된 사용자 정보가 더 이상 passwd 파일에 없는 것을 볼 수 있으며 이는 아래 그림과 같이 사용자가 삭제되었음을 증명합니다. 5. 그런 다음 홈 파일을 입력합니다.

이 웹사이트는 3월 7일 화웨이의 데이터 스토리지 제품 라인 사장인 Zhou Yuefeng 박사가 최근 MWC2024 컨퍼런스에 참석하여 웜 데이터(WarmData)와 콜드 데이터(ColdData)용으로 설계된 차세대 OceanStorArctic 자전 스토리지 솔루션을 구체적으로 시연했다고 보도했습니다. Huawei의 데이터 스토리지 제품 라인 사장 Zhou Yuefeng은 일련의 혁신적인 솔루션을 출시했습니다. 이미지 출처: 이 사이트에 첨부된 Huawei의 공식 보도 자료는 다음과 같습니다. 이 솔루션의 가격은 자기 테이프보다 20% 저렴하며, 전력 소비는 하드 디스크보다 90% 낮습니다. 해외 기술 매체인 blockandfiles에 따르면, Huawei 대변인은 자기전기 저장 솔루션에 대한 정보도 공개했습니다. Huawei의 자기전자 디스크(MED)는 자기 저장 매체의 주요 혁신입니다. 1세대 ME
