首页 > 其他分享 >存储过程与触发器

存储过程与触发器

时间:2024-05-09 21:12:21浏览次数:18  
标签:触发器 -- SNO 数据库 存储 SQL 过程 OUT

存储过程与触发器

  合集 - 数据库知识(5)   1.SQL Server实战一:创建、分离、附加、删除、备份数据库04-242.SQL Server实战二:创建、修改、复制、删除数据库表并加以数据处理04-263.SQL Server实战三:数据库表完整性约束及索引、视图的创建、编辑与删除04-294.SQL Server实战四:查询数据库的数据05-06 5.SQL Server实战五:存储过程与触发器05-08 收起  

  本文介绍基于Microsoft SQL Server软件,实现数据库存储过程触发器的创建、执行、修改与删除等操作。

 

目录

 

  系列文章中示例数据来源于《 SQL Server实验指导(2005版)》一书。依据本系列文章的思想与对操作步骤、代码的详细解释,大家用自己手头的数据,可以将相关操作与分析过程加以完整重现。

1 交互式创建并执行——存储过程一

(1) 启动Microsoft SQL Server 2008 R2软件;

(2) 在“对象资源管理器”窗格中,在“数据库”处右键,在弹出的菜单中选择“附加”选项;

(3) 选择需要加以附加的jxsk数据库物理文件,选择定位文件夹“G:\sql\chutianjia sql”并选择对应数据库jxsk的物理文件并选择“确定”按钮,再次选择“确定”即可;

(4) 在“对象资源管理器”中选择“数据库”→“jxsk”→“可编程性”→“存储过程”;右击,在弹出的窗口中选择“新建存储过程”选项;如下图;

image

(5) 将原有模板语句:

-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<Author,,Name>
-- Create date: <Create Date,,>
-- Description:	<Description,,>
-- =============================================
CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName> 
	-- Add the parameters for the stored procedure here
	<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>, 
	<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;
    -- Insert statements for procedure here
	SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
END
GO

修改为:

CREATE PROCEDURE Pro_Qsinf
@SNO_IN CHAR(8)='S2',@SNAME_OUT CHAR(8) OUTPUT,
@SAGE_OUT INT OUTPUT, @DEPT_OUT CHAR(10) OUTPUT
AS SELECT @SNAME_OUT=SN,@SAGE_OUT=AGE,@DEPT_OUT=DEPT
FROM S WHERE SNO=@SNO_IN

(6) 单击对勾按钮进行语法检查,如下图;单击“工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(7) 在“对象资源管理器”中选择“数据库”→“jxsk”→“可编程性”→“存储过程”;看到已存在通过上述步骤建立的存储过程;

2 交互式创建并执行——存储过程二

(1) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
DECLARE @SNO_IN CHAR(8),
@SNAME_OUT CHAR(8),
@SAGE_OUT INT,
@SDEPT_OUT CHAR(10)
EXEC Pro_Qsinf DEFAULT, @SNAME_OUT OUTPUT,@SAGE_OUT OUTPUT,@SDEPT_OUT OUTPUT
PRINT @SNAME_OUT
PRINT @SAGE_OUT
PRINT @SDEPT_OUT
SELECT @SNO_IN='S4'
EXEC PRO_QSINF @SNO_IN, @SNAME_OUT OUTPUT,@SAGE_OUT OUTPUT,@SDEPT_OUT OUTPUT
PRINT @SNAME_OUT
PRINT @SAGE_OUT
PRINT @SDEPT_OUT
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

3 用T-SQL创建——存储过程一

(1) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

CREATE PROCEDURE Pro_Qscore
@SNAME_IN CHAR(8), @CNAME_IN CHAR(10),@SCORE_OUT TINYINT OUTPUT
AS SELECT @SCORE_OUT=SCORE FROM S,C,SC
WHERE S.SNO=SC.SNO AND C.CNO=SC.CNO
AND SN=@SNAME_IN AND CN=@CNAME_IN

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(3) 在“对象资源管理器”中选择“数据库”→“jxsk”→“可编程性”→“存储过程”;看到已存在通过上述步骤建立的存储过程;

4 用T-SQL创建——存储过程二

(1) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
DECLARE @SNAME_IN CHAR(8),
@CNAME_IN CHAR(8),
@SCORE_OUT TINYINT
SELECT @SNAME_IN='李思'
SELECT @CNAME_IN='程序设计'
EXEC PRO_QSCORE @SNAME_IN,@CNAME_IN,@SCORE_OUT OUTPUT PRINT RTRIM(@SNAME_IN)+'='+LTRIM (STR(@SCORE_OUT))
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

5 交互式修改存储过程

(1) 在“对象资源管理器”中选择“数据库”→“jxsk”→“可编程性”→“存储过程”;右击存储过程Pro_Qsinf,在弹出的窗口中选择“修改”选项,如下图;

(2) 将原有模板语句修改为

USE [jxsk]
GO
/****** Object:  StoredProcedure [dbo].[Pro_Qsinf]    Script Date: 04/26/2019 15:04:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Pro_Qsinf]
@SNO_IN CHAR(2)='S2',@SNAME_OUT CHAR(8) OUTPUT,
@SAGE_OUT TINYINT OUTPUT, @DEPT_OUT CHAR(10) OUTPUT
AS SELECT @SNAME_OUT=SN,@SAGE_OUT=AGE,@DEPT_OUT=DEPT
FROM S WHERE SNO=@SNO_IN

(3) 单击对勾按钮进行语法检查,如下图;单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

6 用T-SQL修改存储过程

(1) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
ALTER PROCEDURE PRO_QSINF
@SNO_IN CHAR(2)='S1',@SNAME_OUT CHAR(8) OUTPUT,
@SSEX_OUT CHAR(2) OUTPUT,@DEPT_OUT CHAR(10) OUT
AS 
SELECT @SNAME_OUT=SN,@SSEX_OUT=SEX,@DEPT_OUT=DEPT
FROM S WHERE SNO=@SNO_IN
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(3) 在“对象资源管理器”中选择“数据库”→“jxsk”→“可编程性”→“存储过程”;点击存储过程Pro_Qsinf,选择“参数”,可发现其定义发生变化;

7 交互式删除存储过程

(1) 在“对象资源管理器”中选择“数据库”→“jxsk”→“可编程性”→“存储过程”;右击存储过程Pro_Qsinf,在弹出的窗口中选择“删除”选项;

(2) 选择确定按钮,存储过程即被删除;如下图;

8 用T-SQL删除存储过程

(1) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
DROP PROCEDURE PRO_QSCORE
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;删除后结果如下下图;

9 交互式为数据库表S创建一级联更新触发器——创建触发器

(1) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.c”;右击触发器,在弹出的窗口中选择“新建触发器”选项;如下图;

(2) 窗口内原有语句为:

-- ================================================
-- Template generated from Template Explorer using:
-- Create Trigger (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- See additional Create Trigger templates for more
-- examples of different Trigger statements.
--
-- This block of comments will not be included in
-- the definition of the function.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<Author,,Name>
-- Create date: <Create Date,,>
-- Description:	<Description,,>
-- =============================================
CREATE TRIGGER <Schema_Name, sysname, Schema_Name>.<Trigger_Name, sysname, Trigger_Name> 
   ON  <Schema_Name, sysname, Schema_Name>.<Table_Name, sysname, Table_Name> 
   AFTER <Data_Modification_Statements, , INSERT,DELETE,UPDATE>
AS 
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;
    -- Insert statements for trigger here
END
GO

需将其更改为:

CREATE TRIGGER TRIGGER_S
ON S FOR UPDATE AS IF UPDATE(SNO)
BEGIN
DECLARE @SNO_NEW CHAR(2),@SNO_OLD CHAR(2)
SELECT @SNO_NEW=SNO FROM inserted
SELECT @SNO_OLD=SNO FROM deleted
UPDATE SC SET SNO=@SNO_NEW WHERE SNO=@SNO_OLD
END

(3) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

10 交互式为数据库表S创建一级联更新触发器——验证触发器

(1) 查看数据库表S与SC,如下图;

(2) 删除原有S与SC之间的外键关系;修改S表中S1为S9,执行操作,如下图;

(3) 查看SC表中数据,发现其S1已改变为S9,且位置也发生相应变化,如下图;

11 交互式为数据库表SC创建一限制更新触发器——创建触发器

(1) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.SC”;右击触发器,在弹出的窗口中选择“新建触发器”选项;如下图;

(2) 窗口内原有语句为:

-- ================================================
-- Template generated from Template Explorer using:
-- Create Trigger (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- See additional Create Trigger templates for more
-- examples of different Trigger statements.
--
-- This block of comments will not be included in
-- the definition of the function.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<Author,,Name>
-- Create date: <Create Date,,>
-- Description:	<Description,,>
-- =============================================
CREATE TRIGGER <Schema_Name, sysname, Schema_Name>.<Trigger_Name, sysname, Trigger_Name> 
   ON  <Schema_Name, sysname, Schema_Name>.<Table_Name, sysname, Table_Name> 
   AFTER <Data_Modification_Statements, , INSERT,DELETE,UPDATE>
AS 
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;
    -- Insert statements for trigger here
END
GO 

需将其更改为:

CREATE TRIGGER TRIGGER_SC
ON SC FOR UPDATE AS IF UPDATE(SNO)
BEGIN
DECLARE @SNO_NEW CHAR(2),@SNO_OLD CHAR(2),@SNO_CNT INT
SELECT @SNO_OLD=SNO FROM deleted
SELECT @SNO_CNT=COUNT(*) FROM S WHERE SNO=@SNO_OLD
IF @SNO_CNT<>0
ROLLBACK TRANSACTION
END

(3) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(4) 查看数据库表S与SC,可发现在SC中有两条S9学号学生的记录如下两图;此时将SC中的第一条S9记录改为S1,发现修改后其数据再次恢复原有状态;如以下第三幅图;

12 用T-SQL为数据库表SC创建触发器

(1) 点击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
CREATE TRIGGER SCORE_SC_TRI
ON SC FOR INSERT,UPDATE
AS DECLARE @SCORE_READ TINYINT
SELECT @SCORE_READ=SCORE FROM inserted
IF @SCORE_READ >=0 AND @SCORE_READ<=100
BEGIN PRINT'操作完成!'
return
end
PRINT '成绩超出0-100之间,请重新输入。'
ROLLBACK TRANSACTION
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(3) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.SC”→“触发器”,可看到通过上述步骤生成的触发器已存在;如下图;

(4) 查看数据库表SC,如下图;

(5) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

INSERT INTO SC VALUES('S1','C5',190)
GO
INSERT INTO SC VALUES('S1','C5',100)
GO
UPDATE SC SET SCORE=130 WHERE SNO='S2'AND CNO='C5'
GO
UPDATE SC SET SCORE =60 WHERE SNO='S2' AND CNO='C5'
GO

(6) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(7) 可以在下方窗口中看到4条系统信息,表示:第1条INSERT语句因成绩为190超出范围,而要求重新输入;第2条INSERT语句因成绩为100在正常范围内,而插入表中;第3条UPDATE语句因成绩为130超出范围,而要求重新输入;第4条UPDATE语句因成绩为60在正常范围内,修改成功;查看数据库表SC的数据。在数据库表SC数据窗口中,单击感叹号按钮,更新表SC中的数据,如下图;可以看到增加了一个记录('S9”,“C5’,100),修改了一条记录('S2',C5',60),即是步骤中SQL语句执行的结果。

13 用T-SQL为数据库表C创建级联删除触发器

(1) 点击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
CREATE TRIGGER TRIGGER_DC
ON C FOR DELETE
AS DECLARE @CNO_DEL CHAR(2)
SELECT @CNO_DEL=CNO FROM deleted
DELETE FROM SC WHERE CNO=@CNO_DEL
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句;

(3) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.C”→“触发器”,可看到通过上述步骤生成的触发器已存在;

(4) 打开数据库表C与SC,发现在SC表中有三条关于C1的记录,如下图;

(5) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
DELETE FROM C WHERE CNO='C1'
GO

(6) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(7) 在数据库表SC中发现课程C1有关的数据已经被删除;

14 交互式修改数据库表S的触发器

(1) 点击“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.S”→“触发器”,右击选择“修改”选项,如下图;

(2) 窗口内原有语句为:

USE [jxsk]
GO
/****** Object:  Trigger [dbo].[TRIGGER_S]    Script Date: 04/26/2019 16:25:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRIGGER_S]
ON [dbo].[S] FOR UPDATE AS IF UPDATE(SNO)
BEGIN
DECLARE @SNO_NEW CHAR(2),@SNO_OLD CHAR(2)
SELECT @SNO_NEW=SNO FROM inserted
SELECT @SNO_OLD=SNO FROM deleted
UPDATE SC SET SNO=@SNO_NEW WHERE SNO=@SNO_OLD
END

需将其更改为:

ALTER TRIGGER TRIGGER_S
ON S FOR DELETE
AS DECLARE @SNO_DEL CHAR(2)
SELECT @SNO_DEL=SNO FROM deleted
WHERE SNO=@SNO_DEL

(3) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(4) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.S”→“触发器”,双击原有触发器,发现其已被修改;

15 用T-SQL修改数据库表C的触发器

(1) 点击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
ALTER TRIGGER TRIGGER_DC
ON C FOR DELETE
AS DECLARE @CNO_DEL CHAR(2)
SELECT @CNO_DEL=CNO FROM deleted
DELETE FROM SC WHERE CNO=@CNO_DEL
DELETE FROM TC WHERE CNO=@CNO_DEL
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(3) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.C”→“触发器”,双击原有触发器,发现其已被修改;

(4) 在数据库表C中删除任意一条记录,发现数据库表SC与TC中记录也随之改变;

16 交互式删除数据库表S的触发器

(1) 点击“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.S”→“触发器”,右击原有触发器,在弹出的菜单中选择“删除”,点击确定;

(2) 在原有位置已看不到原有触发器;

17 用T-SQL删除数据库表C的触发器

(1) 单击屏幕上方 “工具栏”菜单中的“新建查询”按钮,打开“查询编辑器”窗口,并在“查询编辑器”窗口中输入以下T-SQL语句:

USE jxsk
GO
DROP TRIGGER TRIGGER_DC
GO

(2) 单击 “工具栏”中的“执行(x)”按钮,即可执行上述T-SQL语句,如下图;

(3) 在“对象资源管理器”中选择“数据库”→“jxsk”→“表”→“dbo.C”→“触发器”,已看不到原有触发器,如下图;

  至此,大功告成。

标签:触发器,--,SNO,数据库,存储,SQL,过程,OUT
From: https://www.cnblogs.com/Leo_wl/p/18183078

相关文章

  • 5.9 T2 推式子的过程
    和题解的做法有些不同,不知道为什么,但是能够通过。首先按题解的做法先将式子除以\(z^2\)。令\(\frac{y}{z}=a,\frac{x}{z}=b\)。有:\[\begin{aligned}\frac{x^2}{z^2}-\frac{xy}{z^2}-\frac{y^2}{z^2}+\frac{y}{z}+1-\frac{x}{z}=0\\-a^2-ab+b^2+a+1-b=0\end{aligned}\]题解......
  • 云服务器遭到黑客入侵植入木马病毒排查过程
    1、问题说明在一个安静的下午,突然手机上面接收到云服务器厂商发的一条短信。短信内容为服务器疑似被木马病毒入侵,监测到病毒文件。然后我就使用FinalShell登录服务器准备进去看一看,刚登陆进去FinalShell左边监控程序显示cpu占用100%。服务器正常来说cpu只会在3%~9%之间,突然这个CP......
  • kettle从入门到精通 第五十七课 ETL之kettle调用存储过程
    1、之前有个同学说他使用kettle执行一坨sql语句时,kettle直接卡死掉了。我给出的建议是使用存储过程,果不其然使用存储过程顺利解决问题。今天我们一起来学习下kettle如何调用存储过程,这里基于mysql进行演示。调用存储过程有两种方法:使用步骤【调用DB存储过程】或者步骤【执行SQL脚......
  • 软件测试过程中的痛点思考
    前几天无意中看到了TesterHome发起的《2023年度软件质量保障行业调查报告》,文中提到了几点调查结果和分析结论让我很感兴趣。针对这份调查报告,我想就下述三点结论谈谈我的一些理解和思考。 一、测试参与度分析在这一调查报告结论中,提到了需求评审、测试计划和测试评审是整个......
  • 测试答疑助手:从需求文档到设计文档、测试用例的完整测试过程
    本文将基于LangChain实现一个mini的实战案例。这次实战主要完成的任务,就是设计一个测试答疑助手,这个测试答疑助手的主要功能为基于本地的文档和数据,回答给出的自然语言问题,比如一些数据的统计,查找、组合。示例使用数据测试用例文档设计文档需求文档实践演练实战设......
  • Kafka存储机制
    Kafka之所以有那么高的吞吐量,很大程度取决于它的存储机制,一个主题可以有多个partition,每个partition有一个leader和多个副本,读写主要通过leader,副本的主要功能还是为了保证数据的安全性和保证可靠性,当某个partition的leader出现异常后,剩余副本可以选举出新的leader;每个partition......
  • 面向对象、面向过程、类与对象
    【一】人狗大战【1】人狗大战小游戏描述人可以打狗,狗掉血,狗可以咬人,人掉血【2】人狗大战小游戏实现(0)分析人的属性人的名字人的类型人的年龄人的攻击力人的生命值狗的属性狗的名字狗的类型狗的攻击值狗的生命值(1)定义人和狗的参数方式一:使用字典定义属......
  • 银弹:为了避免项目的成员为了一些问题争执不休,公司发明了银弹(Silver Bullet)这一工具。
    我的答案:【第二组】答:银弹作为一种工具,其目的是为了在项目团队中解决争议,确保项目能够继续前进。然而,是否真的有用,需要从多个角度进行考量:团队沟通与协作:银弹提供了一种强制性的解决方案,可以在一定程度上减少无休止的争论,促使团队成员快速做出决策。这在某些情况下可以提......
  • 1992年,姜万勐 看到 MPEG芯片Epiphany – 用MPEG1 把图像和声音同时存储在一张
    如果我穿越到1993年,发现万燕公司在VCD市场中面临激烈竞争,我会提出一些建议来帮助他们应对挑战并保持竞争力:产品创新与差异化:鉴于竞争对手大量仿制VCD机,我会建议万燕公司通过产品创新和差异化来区别于竞争对手。这可能包括提高VCD机的性能、功能和外观设计,以及增加附加功能如更好......
  • Spring SpringMVC——前端控制器初始化过程
     创建完DispatcherServlet对象时,会执行类中的init方法 如果不配置load-on-startup,那么DispatcherServlet将在第一次收到请求时才会被实例化和初始化。这意味着DispatcherServlet不会在服务器启动时立即执行创建和初始化的操作。当第一个请求到达时,Servlet容器(如Tomca......