存储过程的设计_第1页
存储过程的设计_第2页
存储过程的设计_第3页
存储过程的设计_第4页
存储过程的设计_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、CREATE PROCEDURE创建存储过程,存储过程是保存起来的可以接受和返回用户提供的参数的 Transact-SQL 语句的集合。可以创建一个过程供永久使用,或在一个会话中临时使用(局部临时过程),或在所有会话中临时使用(全局临时过程)。也可以创建在 Microsoft SQL Server启动时自动运行的存储过程。语法CREATE PROC EDURE procedure_name ; number     parameter data_type          VARYING = default OUT

2、PUT     ,.n WITH    RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION FOR REPLICATION AS sql_statement .n 参数procedure_name    新存储过程的名称。过程名必须符合标识符规则,且对于数据库及其所有者必须唯一。有关更多信息,请参见使用标识符。    要创建局部临时过程,可以在 procedure_name 前面加一个编号符 (#procedure_name),要创建全局临时过程,可以在 procedur

3、e_name 前面加两个编号符 (#procedure_name)。完整的名称(包括 # 或 #)不能超过 128 个字符。指定过程所有者的名称是可选的。;number    是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。par

4、ameter过程中的参数。在 CREATE PROCEDURE 语句中可以声明一个或多个参数。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2.100 个参数。使用 符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。有关更多信息,请参见 EXECUTE。 data_type参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数

5、据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。有关 SQL Server 提供的数据类型及其语法的更多信息,请参见数据类型。 说明  对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。VARYING指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。default参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(*、_、 和 )。O

6、UTPUT表明参数是返回参数。该选项的值可以返回给 EXECUTE。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。n表示最多可以指定 2.100 个参数的占位符。RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTIONRECOMPILE 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。ENCRYPTION 表示 S

7、QL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。说明  在升级过程中,SQL Server 利用存储在 syscomments 中的加密注释来重新创建加密过程。FOR REPLICATION指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。AS指定过程要执行的操作。sql_

8、statement过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。n是表示此过程可以包含多条 Transact-SQL 语句的占位符。注释存储过程的最大大小为 128 MB。用户定义的存储过程只能在当前数据库中创建(临时过程除外,临时过程总是在 tempdb 中创建)。在单个批处理中,CREATE PROCEDURE 语句不能与其它 Transact-SQL 语句组合使用。 默认情况下,参数可为空。如果传递 NULL 参数值并且该参数在 CREATE 或 ALTER TABLE 语句中使用,而该语句中引用的列又不允许使用 NULL,则 SQL Server 会产生

9、一条错误信息。为了防止向不允许使用 NULL 的列传递 NULL 参数值,应向过程中添加编程逻辑或为该列使用默认值(使用 CREATE 或 ALTER TABLE 的 DEFAULT 关键字)。建议在存储过程的任何 CREATE TABLE 或 ALTER TABLE 语句中都为每列显式指定 NULL 或 NOT NULL,例如在创建临时表时。ANSI_DFLT_ON 和 ANSI_DFLT_OFF 选项控制 SQL Server 为列指派 NULL 或 NOT NULL 特性的方式(如果在 CREATE TABLE 或 ALTER TABLE 语句中没有指定的话)。如果某个连接执行的存储过程

10、对这些选项的设置与创建该过程的连接的设置不同,则为第二个连接创建的表列可能会有不同的为空性,并且表现出不同的行为方式。如果为每个列显式声明了 NULL 或 NOT NULL,那么将对所有执行该存储过程的连接使用相同的为空性创建临时表。在创建或更改存储过程时,SQL Server 将保存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的设置。执行存储过程时,将使用这些原始设置。因此,所有客户端会话的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 设置在执行存储过程时都将被忽略。在存储过程中出现的 SET QUOTED_IDENTIF

11、IER 和 SET ANSI_NULLS 语句不影响存储过程的功能。其它 SET 选项(例如 SET ARITHABORT、SET ANSI_WARNINGS 或 SET ANSI_PADDINGS)在创建或更改存储过程时不保存。如果存储过程的逻辑取决于特定的设置,应在过程开头添加一条 SET 语句,以确保设置正确。从存储过程中执行 SET 语句时,该设置只在存储过程完成之前有效。之后,设置将恢复为调用存储过程时的值。这使个别的客户端可以设置所需的选项,而不会影响存储过程的逻辑。说明  SQL Server 是将空字符串解释为单个空格还是解释为真正的空字符串,由兼容级别设置

12、控制。如果兼容级别小于或等于 65,SQL Server 就将空字符串解释为单个空格。如果兼容级别等于 70,则 SQL Server 将空字符串解释为空字符串。有关更多信息,请参见 sp_dbcmptlevel。 获得有关存储过程的信息若要显示用来创建过程的文本,请在过程所在的数据库中执行 sp_helptext,并使用过程名作为参数。 说明  使用 ENCRYPTION 选项创建的存储过程不能使用 sp_helptext 查看。若要显示有关过程引用的对象的报表,请使用 sp_depends。 若要为过程重命名,请使用 sp_rename。 引用对象SQL Server

13、允许创建的存储过程引用尚不存在的对象。在创建时,只进行语法检查。执行时,如果高速缓存中尚无有效的计划,则编译存储过程以生成执行计划。只有在编译过程中才解析存储过程中引用的所有对象。因此,如果语法正确的存储过程引用了不存在的对象,则仍可以成功创建,但在运行时将失败,因为所引用的对象不存在。有关更多信息,请参见延迟名称解析和编译。 延迟名称解析和兼容级别SQL Server 允许 Transact-SQL 存储过程在创建时引用不存在的表。这种能力称为延迟名称解析。不过,如果 Transact-SQL 存储过程引用了该存储过程中定义的表,而兼容级别设置(通过执行 sp_dbcmptlevel 来设置

14、)为 65,则在创建时会发出警告信息。而如果在运行时所引用的表不存在,将返回错误信息。有关更多信息,请参见 sp_dbcmptlevel 和延迟名称解析和编译。 执行存储过程成功执行 CREATE PROCEDURE 语句后,过程名称将存储在 sysobjects 系统表中,而 CREATE PROCEDURE 语句的文本将存储在 syscomments 中。第一次执行时,将编译该过程以确定检索数据的最佳访问计划。使用 cursor 数据类型的参数存储过程只能将 cursor 数据类型用于 OUTPUT 参数。如果为某个参数指定了 cursor 数据类型,也必须指定 VARYING 和 OUT

15、PUT 参数。如果为某个参数指定了 VARYING 关键字,则数据类型必须是 cursor,并且必须指定 OUTPUT 关键字。说明  cursor 数据类型不能通过数据库 API(例如 OLE DB、ODBC、ADO 和 DB-Library)绑定到应用程序变量上。因为必须先绑定 OUTPUT 参数,应用程序才可以执行存储过程,所以带有 cursor OUTPUT 参数的存储过程不能通过数据库 API 调用。只有将 cursor OUTPUT 变量赋值给 Transact-SQL 局部 cursor 变量时,才可以通过 Transact-SQL 批处理、存储过程或触发器调

16、用这些过程。Cursor 输出参数在执行过程时,以下规则适用于 cursor 输出参数: 对于只进游标,游标的结果集中返回的行只是那些存储过程执行结束时处于或超出游标位置的行,例如: 在过程中的名为 RS 的 100 行结果集上打开一个非滚动游标。 过程提取结果集 RS 的头 5 行。过程返回到其调用者。返回到调用者的结果集 RS 由 RS 的第 6 到 100 行组成,调用者中的游标处于 RS 的第一行之前。 对于只进游标,如果存储过程完成后,游标位于第一行的前面,则整个结果集将返回给调用批处理、存储过程或触发器。返回时,游标将位于第一行的前面。对于只进游标,如果存储过程完成后,游标的位置超

17、出最后一行的结尾,则为调用批处理、存储过程或触发器返回空结果集。 说明  空结果集与空值不同。对于可滚动游标,在存储过程执行结束时,结果集中的所有行均会返回给调用批处理、存储过程或触发器。返回时,游标保留在过程中最后一次执行提取时的位置。对于任意类型的游标,如果游标关闭,则将空值传递回调用批处理、存储过程或触发器。如果将游标指派给一个参数,但该游标从未打开过,也会出现这种情况。 说明  关闭状态只有在返回时才有影响。例如,可以在过程中关闭游标,稍后再打开游标,然后将该游标的结果集返回给调用批处理、存储过程或触发器。临时存储过程SQL Server 支持两

18、种临时过程:局部临时过程和全局临时过程。局部临时过程只能由创建该过程的连接使用。全局临时过程则可由所有连接使用。局部临时过程在当前会话结束时自动除去。全局临时过程在使用该过程的最后一个会话结束时除去。通常是在创建该过程的会话结束时。临时过程用 # 和 # 命名,可以由任何用户创建。创建过程后,局部过程的所有者是唯一可以使用该过程的用户。执行局部临时过程的权限不能授予其他用户。如果创建了全局临时过程,则所有用户均可以访问该过程,权限不能显式废除。只有在 tempdb 数据库中具有显式 CREATE PROCEDURE 权限的用户,才可以在该数据库中显式创建临时过程(不使用编号符命名)。可以授予或

19、废除这些过程中的权限。 说明  频繁使用临时存储过程会在 tempdb 中的系统表上产生争用,从而对性能产生负面影响。建议使用 sp_executesql 代替。sp_executesql 不在系统表中存储数据,因此可以避免这一问题。自动执行存储过程SQL Server 启动时可以自动执行一个或多个存储过程。这些存储过程必须由系统管理员创建,并在 sysadmin 固定服务器角色下作为后台过程执行。这些过程不能有任何输入参数。 对启动过程的数目没有限制,但是要注意,每个启动过程在执行时都会占用一个连接。如果必须在启动时执行多个过程,但不需要并行执行,则可以指定一个过程作为启

20、动过程,让该过程调用其它过程。这样就只占用一个连接。在启动时恢复了最后一个数据库后,即开始执行存储过程。若要跳过这些存储过程的执行,请将启动参数指定为跟踪标记 4022。如果以最低配置启动 SQL Server(使用 -f 标记),则启动存储过程也不会执行。有关更多信息,请参见跟踪标记。 若要创建启动存储过程,必须作为 sysadmin 固定服务器角色的成员登录,并在 master 数据库中创建存储过程。使用 sp_procoption 可以: 将现有存储过程指定为启动过程。停止在 SQL Server 启动时执行过程。查看 SQL Server 启动时执行的所有过程的列表。 存储过程嵌套存储

21、过程可以嵌套,即一个存储过程可以调用另一个存储过程。在被调用过程开始执行时,嵌套级将增加,在被调用过程执行结束后,嵌套级将减少。如果超出最大的嵌套级,会使整个调用过程链失败。可用 NESTLEVEL 函数返回当前的嵌套级。若要估计编译后的存储过程大小,请使用下列性能监视计数器。 性能监视器对象名 性能监视计数器名称 SQLServer:缓冲区管理器 高速缓存大小(页面数) SQLServer:高速缓存管理器 高速缓存命中率   高速缓存页   高速缓存对象计数* * 各种分类的高速缓存对象均可以使用这些计数器,包括特殊 sql、准备 sql、过程、触发器

22、等。有关更多信息,请参见 SQL Server:Buffer Manager 对象和 SQL Server:Cache Manager 对象。 sql_statement 限制除了 SET SHOWPLAN_TEXT 和 SET SHOWPLAN_ALL 之外(这两个语句必须是批处理中仅有的语句),任何 SET 语句均可以在存储过程内部指定。所选择的 SET 选项在存储过程执行过程中有效,之后恢复为原来的设置。 如果其他用户要使用某个存储过程,那么在该存储过程内部,一些语句使用的对象名必须使用对象所有者的名称限定。这些语句包括: ALTER TABLECREATE INDEXCREATE TA

23、BLE所有 DBCC 语句DROP TABLEDROP INDEXTRUNCATE TABLEUPDATE STATISTICS 权限CREATE PROCEDURE 的权限默认授予 sysadmin 固定服务器角色成员和 db_owner 和 db_ddladmin 固定数据库角色成员。sysadmin 固定服务器角色成员和 db_owner 固定数据库角色成员可以将 CREATE PROCEDURE 权限转让给其他用户。执行存储过程的权限授予过程的所有者,该所有者可以为其它数据库用户设置执行权限。示例A. 使用带有复杂 SELECT 语句的简单过程下面的存储过程从四个表的联接中返回所有作者

24、(提供了姓名)、出版的书籍以及出版社。该存储过程不使用任何参数。USE pubsIF EXISTS (SELECT name FROM sysobjects          WHERE name = 'au_info_all' AND type = 'P')   DROP PROCEDURE au_info_allGOCREATE PROCEDURE au_info_allASSELECT au_lname, au_fname, title, pub_name  

25、0;FROM authors a INNER JOIN titleauthor ta      ON a.au_id = ta.au_id INNER JOIN titles t      ON t.title_id = ta.title_id INNER JOIN publishers p      ON t.pub_id = p.pub_idGOau_info_all 存储过程可以通过以下方法执行:EXECUTE au_info_all- OrEXEC au_info_a

26、ll如果该过程是批处理中的第一条语句,则可使用:au_info_allB. 使用带有参数的简单过程下面的存储过程从四个表的联接中只返回指定的作者(提供了姓名)、出版的书籍以及出版社。该存储过程接受与传递的参数精确匹配的值。USE pubsIF EXISTS (SELECT name FROM sysobjects          WHERE name = 'au_info' AND type = 'P')   DROP PROCEDURE au_infoGOUSE pubsGOCR

27、EATE PROCEDURE au_info    lastname varchar(40),    firstname varchar(20) AS SELECT au_lname, au_fname, title, pub_name   FROM authors a INNER JOIN titleauthor ta      ON a.au_id = ta.au_id INNER JOIN titles t      ON t.title_id =

28、ta.title_id INNER JOIN publishers p      ON t.pub_id = p.pub_id   WHERE  au_fname = firstname      AND au_lname = lastnameGOau_info 存储过程可以通过以下方法执行:EXECUTE au_info 'Dull', 'Ann'- OrEXECUTE au_info lastname = 'Dull', f

29、irstname = 'Ann'- OrEXECUTE au_info firstname = 'Ann', lastname = 'Dull'- OrEXEC au_info 'Dull', 'Ann'- OrEXEC au_info lastname = 'Dull', firstname = 'Ann'- OrEXEC au_info firstname = 'Ann', lastname = 'Dull'如果该过程是批处理中的第一条语句,则可使

30、用:au_info 'Dull', 'Ann'- Orau_info lastname = 'Dull', firstname = 'Ann'- Orau_info firstname = 'Ann', lastname = 'Dull'C. 使用带有通配符参数的简单过程下面的存储过程从四个表的联接中只返回指定的作者(提供了姓名)、出版的书籍以及出版社。该存储过程对传递的参数进行模式匹配,如果没有提供参数,则使用预设的默认值。USE pubsIF EXISTS (SELECT name FROM s

31、ysobjects       WHERE name = 'au_info2' AND type = 'P')   DROP PROCEDURE au_info2GOUSE pubsGOCREATE PROCEDURE au_info2   lastname varchar(30) = 'D*',   firstname varchar(18) = '*'AS SELECT au_lname, au_fname, title, pu

32、b_nameFROM authors a INNER JOIN titleauthor ta   ON a.au_id = ta.au_id INNER JOIN titles t   ON t.title_id = ta.title_id INNER JOIN publishers p   ON t.pub_id = p.pub_idWHERE au_fname LIKE firstname   AND au_lname LIKE lastnameGOau_info2 存储过程可以用多种组合执行。下面只列出了部分

33、组合:EXECUTE au_info2- OrEXECUTE au_info2 'Wh*'- OrEXECUTE au_info2 firstname = 'A*'- OrEXECUTE au_info2 'CKarsOEn'- OrEXECUTE au_info2 'Hunter', 'Sheryl'- OrEXECUTE au_info2 'H*', 'S*'D. 使用 OUTPUT 参数OUTPUT 参数允许外部过程、批处理或多条 Transact-SQL 语句访问在过程执行期

34、间设置的某个值。下面的示例创建一个存储过程 (titles_sum),并使用一个可选的输入参数和一个输出参数。首先,创建过程:USE pubsGOIF EXISTS(SELECT name FROM sysobjects      WHERE name = 'titles_sum' AND type = 'P')   DROP PROCEDURE titles_sumGOUSE pubsGOCREATE PROCEDURE titles_sum TITLE varchar(40) = '*

35、9;, SUM money OUTPUTASSELECT 'Title Name' = titleFROM titles WHERE title LIKE TITLE SELECT SUM = SUM(price)FROM titlesWHERE title LIKE TITLEGO接下来,将该 OUTPUT 参数用于控制流语言。 说明  OUTPUT 变量必须在创建表和使用该变量时都进行定义。参数名和变量名不一定要匹配,不过数据类型和参数位置必须匹配(除非使用 SUM = variable 形式)。 DECLARE TOTALCOST moneyEXECU

36、TE titles_sum 'The*', TOTALCOST OUTPUTIF TOTALCOST < 200 BEGIN   PRINT ' '   PRINT 'All of these titles can be purchased for less than $200.'ENDELSE   SELECT 'The total cost of these titles is $'          

37、+ RTRIM(CAST(TOTALCOST AS varchar(20)下面是结果集:Title Name                                                         

38、;      - The Busy Executive's Database GuideThe Gourmet MicrowaveThe Psychology of Computer Cooking(3 row(s) affected)Warning, null value eliminated from aggregate.All of these titles can be purchased for less than $200.E. 使用 OUTPUT 游标参数OUTPUT 游标参数用来将存储过程的局部游标传递回调用批处理、存储过程或触发

39、器。首先,创建以下过程,在 titles 表上声明并打开一个游标:USE pubsIF EXISTS (SELECT name FROM sysobjects       WHERE name = 'titles_cursor' and type = 'P')DROP PROCEDURE titles_cursorGOCREATE PROCEDURE titles_cursor titles_cursor CURSOR VARYING OUTPUTASSET titles_cursor = CURSORFORWARD_ON

40、LY STATIC FORSELECT *FROM titlesOPEN titles_cursorGO接下来,执行一个批处理,声明一个局部游标变量,执行上述过程以将游标赋值给局部变量,然后从该游标提取行。USE pubsGODECLARE MyCursor CURSOREXEC titles_cursor titles_cursor = MyCursor OUTPUTWHILE (FETCH_STATUS = 0)BEGIN   FETCH NEXT FROM MyCursorENDCLOSE MyCursorDEALLOCATE MyCursorGOF. 使用 WITH

41、 RECOMPILE 选项如果为过程提供的参数不是典型的参数,并且新的执行计划不应高速缓存或存储在内存中,WITH RECOMPILE 子句会很有帮助。USE pubsIF EXISTS (SELECT name FROM sysobjects      WHERE name = 'titles_by_author' AND type = 'P')   DROP PROCEDURE titles_by_authorGOCREATE PROCEDURE titles_by_author LNAME_PAT

42、TERN varchar(30) = '*'WITH RECOMPILEASSELECT RTRIM(au_fname) + ' ' + RTRIM(au_lname) AS 'Authors full name',   title AS TitleFROM authors a INNER JOIN titleauthor ta    ON a.au_id = ta.au_id INNER JOIN titles t   ON ta.title_id = t.title_idWHERE

43、au_lname LIKE LNAME_PATTERNGOG. 使用 WITH ENCRYPTION 选项WITH ENCRYPTION 子句对用户隐藏存储过程的文本。下例创建加密过程,使用 sp_helptext 系统存储过程获取关于加密过程的信息,然后尝试直接从 syscomments 表中获取关于该过程的信息。IF EXISTS (SELECT name FROM sysobjects      WHERE name = 'encrypt_this' AND type = 'P')   DROP

44、PROCEDURE encrypt_thisGOUSE pubsGOCREATE PROCEDURE encrypt_thisWITH ENCRYPTIONASSELECT * FROM authorsGOEXEC sp_helptext encrypt_this下面是结果集:The object's comments have been encrypted.接下来,选择加密存储过程内容的标识号和文本。SELECT c.id, c.text FROM syscomments c INNER JOIN sysobjects o   ON c.id = o.idWHER

45、E = 'encrypt_this'下面是结果集:说明  text 列的输出显示在单独一行中。执行时,该信息将与 id 列信息出现在同一行中。id         text                                    

46、60;                   - -1413580074 ?e?(1 row(s) affected)H. 创建用户定义的系统存储过程下面的示例创建一个过程,显示表名以 emp 开头的所有表及其对应的索引。如果没有指定参数,该过程将返回表名以 sys 开头的所有表(及索引)。IF EXISTS (SELECT name FROM sysobjects      WHERE name = 'sp_showi

47、ndexes' AND type = 'P')   DROP PROCEDURE sp_showindexesGOUSE masterGOCREATE PROCEDURE sp_showindexes   TABLE varchar(30) = 'sys*'AS SELECT AS TABLE_NAME,    AS INDEX_NAME,    indid AS INDEX_IDFROM sysindexes i INNER JOIN sysobj

48、ects o   ON o.id = i.id WHERE LIKE TABLEGO         USE pubsEXEC sp_showindexes 'emp*'GO下面是结果集:TABLE_NAME       INDEX_NAME       INDEX_ID - - -employee         employee_ind     1employee         PK_emp_id  &#

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论