【数据库作业13】SQL练习8 - CHECK / CONSTRAINT / TRIGGER / PROCEDURE/ FUNCTION

本文深入解析数据库中的数据完整性概念,包括实体完整性、参照完整性和用户定义的完整性,以及如何通过SQL语句定义和修改这些完整性约束。同时,探讨了触发器、存储过程和函数在维护数据库完整性中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据的完整性:防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据。
防范对象:不合语义的、不正确的数据。
数据的安全性:保护数据库 防止恶意的破坏和非法的存取。
防范对象:非法用户和非法操作。

实体完整性:主码唯一,不能为空
关系模型的实体完整性:
CREATE TABLE中用PRIMARY KEY定义

主属性只有一个时可以使用列级完整性,将条件直接写在数据类型后面,也可以使用表级完整性,将条件单独写在最后,标明属性名。但是如果有多个属性共同组成主码,则约束条件必须写成表级完整性。
插入或更新操作时,DBMS按照实体完整性规则自动进行检查。
检查主码值是否唯一,如果不唯一则拒绝插入或修改。
检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改。
【例5.1】将Student表中的Sno属性定义为码.
(1)列级完整性

/*在列级定义主码*/
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
Sname CHAR(20) NOT NULL,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20));

(2)表级完整性

/*在表级定义主码*/
CREATE TABLE Student
(Sno CHAR(9) ,
Sname CHAR(20) NOT NULL,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
PRIMARY KEY (Sno));

【例5.2】将SC表中的Sno,Cno属性组定义为码.
有多个属性共同构成主码,只能使用表级完整性。

CREATE TABLE SC
(Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT,
PRIMARY(Sno,Cno));

Sno和Cno可以重复,但是Sno和Cno的组合不能够重复,Sno和Cno共同构成SC表的主码,主码必须唯一。
参照完整性:外码要么为空,要么来自被参照关系的主码。
关系模型的参照完整性定义:
在CREATE TABLE中用FOREIGN KEY短语定义哪些列为外码;用REFERENCES短语指明这些外码参照哪些表的主码 。

例如,关系SC中(Sno,Cno)是主码。Sno,Cno分别参照Student表的主码和Course表的主码
【例5.3】定义SC中的参照完整性

CREATE TABLE SC
(Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT,
PRIMARY KEY(Sno,Cno),/*在表级定义实体完整性*/
FOREIGN KEY(Sno) REFERENCES Student(Sno),/*在表级定义参照完整性*/
FOREIGN KEY(Cno) REFERENCES Course(Cno)/*在表级定义参照完整性*/
);

在这里插入图片描述
【例5.4】显式说明参照完整性的违约处理示例

CREATE TABLE SC
        (  Sno   CHAR(9)  NOT NULL,
           Cno   CHAR(4)  NOT NULL,
           Grade  SMALLINT,
           PRIMARY KEY(Sno,Cno),		
           FOREIGN KEY (Sno) REFERENCES Student(Sno) 
		ON DELETE CASCADE        /*级联删除SC表中相应的元组*/
             ON UPDATE CASCADE,      /*级联更新SC表中相应的元组*/
           FOREIGN KEY (Cno) REFERENCES Course(Cno)	                    
             ON DELETE NO ACTION 	
                 /*当删除course 表中的元组造成了与SC表不一致时拒绝删除*/
             ON UPDATE CASCADE   
      	  /*当更新course表中的cno时,级联更新SC表中相应的元组*/
           );

注意:在定义外码和级联删除、级联更新之间没有逗号,
测试:
1、当Student表中的Sno更新时,SC表中与之相关的数据也会同时更新。
在这里插入图片描述
2、当Student表中的Sno删除时,SC表也会跟着删除。
在这里插入图片描述
3、当修改Course中的Cno时,SC表也会变化。
4、当删除Course中的Cno时,拒绝删除。
用户定义的完整性:针对某一具体应用的数据必须满足的语义要求
属性上的约束条件
CREATE TABLE时定义属性上的约束条件:列值非空(NOT NULL)、列值唯一(UNIQUE)、检查列值是否满足一个条件表达式(CHECK)

(1)不允许取空值
【例5.5】在定义SC表时,说明Sno、Cno、Grade属性不允许取空值。

CREATE TABLE SC
(Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT NOT NULL,
PRIMARY KEY(Sno,Cno));

如果在表级定义实体完整性,隐含了Sno和Cno不允许取空值,则在列级不允许取空值的定义可以不写。
(2)列值唯一
【例5.6】建立部门表DEPT,要求部门名称Dname列取值唯一,部门编号Deptno列为主码.

CREATE TABLE DEPT
(Deptno NUMERIC(2),
Dname CHAR(9) UNIQUE NOT NULL,
/*要求Dname列值唯一,并且不能取空值*/
Location CHAR10),
PRIMARY KEY(Deptno)
);

(3)用CHECK短语指定列值应该满足的条件.
【例5.7】Student表的Ssex只允许取“男”或“女”。

CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
Sname CHAR(4) NOT NULL,
Ssex CHAR(2) CHECK (Ssex IN ('男','女')),
/*性别属性只能取“男”或“女:*/
Sage SMALLINT,
Sdept CHAR(20));

测试:
(1)

INSERT 
INTO  Student
VALUES('201215126','王武','男',19,'CS');

数据插入成功。
(2)
当性别为’F’时插入失败,出现错误。

INSERT INTO  Student (Sno,Sname,Ssex,Sdept,Sage)
VALUES ('201215129','王辉','F','IS',18);

在这里插入图片描述
因为F没有在集合{男、女}中。这个约束的默认名称为:[CK__Student__Ssex__49C3F6B7]。
在这里插入图片描述
【例5.8】SC表的Grade的值应该在0和100之间。

CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT CHECK(Grade>=0 AND Grade<=100),
/*Grade取值范围是0到100*/
PRIMARY KEY(Sno,Cno),
FOREIGN KEY(Sno) REFERENCES Student(Sno),
FOREIGN KEY(Cno) REFERENCES Course(Cno));

当成绩不在0到100之间时报错
在这里插入图片描述
属性上的约束条件检查和违约处理:插入元组或修改属性的值时,关系数据库管理系统检查属性上的约束条件是否被满足,如果不满足则操作被拒绝执行
元组上的约束条件:在CREATE TABLE时可以用CHECK短语定义元组上的约束条件,即元组级的限制

【例5.9】当学生的性别是男时,其名字不能以Ms.打头。

CREATE TABLE Student
(Sno CHAR(9), 
 Sname  CHAR(8) NOT NULL,
 Ssex    CHAR(2),
 Sage   SMALLINT,
 Sdept  CHAR(20),
 PRIMARY KEY (Sno),
 CHECK (Ssex='女'OR Sname NOT LIKE 'MS.%'));
 /*定义了元组中Sname和Ssex两个属性值之间的约束条件*/)

性别是女性的元组都能通过该项检查,因为Ssex=‘女’成立;
当性别是男性时,要通过检查则名字一定不能以Ms.打头.
测试:
(1)输入的是“女”时,通过检查成功插入。

 INSERT INTO Student
 VALUES('201215189','赵','女',20,'CS');

(2)当插入的是男且姓名不以MS.开头,插入成功

 INSERT INTO Student
 VALUES('201215188','刘','男',20,'CS');

(3)插入的是男,且姓名以MS.开头,插入失败。

 INSERT INTO Student
 VALUES('201215187','MS.JU','男',20,'CS');

在这里插入图片描述
元组上的约束条件检查和违约处理:插入元组或修改属性的值时,关系数据库管理系统检查元组上的约束条件是否被满足,如果不满足则操作被拒绝执行
完整性约束命名子句
1.完整性约束命名子句
CONSTRAINT <完整性约束条件名><完整性约束条件>
<完整性约束条件>包括NOT NULL、UNIQUE、PRIMARY KEY短语、FOREIGN KEY短语、CHECK短语等.

【例5.10】建立学生登记表Student,要求学号在90000~99999之间,姓名不能取空值,年龄小于30,性别只能是“男”或“女”。

CREATE TABLE Student
(   Sno  NUMERIC(6)
    CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),
    Sname  CHAR(20)  
    CONSTRAINT C2 NOT NULL,
    Sage  NUMERIC(3)
    CONSTRAINT C3 CHECK (Sage < 30),
    Ssex  CHAR(2)
    CONSTRAINT C4 CHECK (Ssex IN ( '男','女')),
    CONSTRAINT StudentKey PRIMARY KEY(Sno)
);

在Student表上建立了5个约束条件,包括主码约束(命名为StudentKey)以及C1、C2、C3、C4四个列级约束。
在这里插入图片描述
约束条件名可以系统默认,但是在查找修改时不容易找到和记忆。没有显示命名,系统会自动命名;有自定义显示命名,用自定义的。
C2找不到 这是因为在T-SQL:严格地说NULL/NOT NULL不算约束,因此,没有约束名。
如果输入的信息不在这些范围内会提示错误

INSERT INTO Student
VALUES('12312','wang','26','F')

在这里插入图片描述
【例5.11】建立教师表TEACHER,要求每个教师的应发工资不低于3000元。
应发工资是工资列Sal与扣除项Deduct之和。

CREATE TABLE TEACHER
(Eno NUMERIC(4) PRIMARY KEY,/*在列级定义主码*/
Ename CHAR(10),
Job CHAR(8),
Sal NUMERIC(7,2),
Deduct NUMERIC(7,2),
Deptno NUMERIC(2),
CONSTRAINT TEACHERKEY FOREIGN KEY(Deptno) REFERENCES DEPT(Deptno),
CONSTRAINT C1 CHECK(Sal+Deduct>=3000));

在这里插入图片描述
约束名不能重复,这里将约束的名改为了CC1,否则会提示C1重复的错误。
2. 修改表中的完整性限制
使用ALTER TABLE语句修改表中的完整性限制

【例5.12】去掉例5.10 Student表中对性别的限制。

ALTER TABLE Student
DROP CONSTRAINT C4;

在这里插入图片描述
删除了约束条件C4
【例5.13】修改表Student中的约束条件,要求学号改为在900000~999999之间,年龄由小于30改为小于40

/*修改时可以先删除原来的约束条件,再增加新的约束条件*/
ALTER TABLE Student
DROP CONSTRAINT C1;/*删除学号的约束条件*/
ALTER TABLE Student
ADD CONSTRAINT C1 CHECK(Sno BETWEEN 900000 AND 999999);
/*添加新的学好的约束条件,约束名还是原来的C1*/
ALTER TABLE Student
DROP CONSTRAINT C3;/*删除原来的年龄的约束条件*/
ALTER TABLE Student
ADD CONSTRAINT C3 CHECK(Sage<40);
/*添加新的年龄的而约束条件,约束名仍然为C3*/

修改时可以先删除原来的约束条件,再增加新的约束条件,约束名还是原来的。
这里就体现出了自定义约束名的好处,可以更加方便的对约束进行修改。
断言
SQL中,可以使用 CREATE ASSERTION语句,通过声明性断言来指定更具一般性的约束。

  • 可以定义比较复杂的完整性约束。
  • 断言创建以后,任何对断言中所涉及的关系的操作都会触发DBMS对断言的检查,任何使断言不为真值的操作都会被拒绝执行

    1、创建断言的语句格式
CREATE ASSERTION<断言名><CHECK 子句>

每个断言都被赋予一个名字,<CHECK 子句>中的约束条件与WHERE子句的条件表达式类似。
【例5.18】限制数据库课程最多60名学生选修

CREATE ASSERTION ASSE_SC_DB_NUM
	CHECK (60 >= (SELECT count(*)
                 	FROM Course,SC
    		    	WHERE SC.Cno=Course.Cno and 						Course.Cname ='数据库')
			   	);

【例5.19】限制每一门课程最多60名学生选修

CREATE ASSERTION ASSE_SC_CNUM1
CHECK(60 >= ALL (SELECT count(*) 
				 FROM SC		   				          				  		   
				 GROUP BY Cno)
        		  );
 		/*此断言的谓词,涉及聚集操作count 和分组函数group by的SQL语句*/
  1. 删除断言的语句格式为
DROP ASSERTION <断言名>;

注意:在T-SQL中没有ASSERTION功能。

触发器Trigger
1、定义触发器
CREATE TRIGGER语法格式:

 CREATE TRIGGER <触发器名>  
{BEFORE | AFTER} <触发事件> ON <表名>
REFERENCING NEW|OLD ROW AS<变量>
FOR EACH  {ROW | STATEMENT}
[WHEN <触发条件>]<触发动作体>
  • 触发事件:触发事件可以是INSERT、DELETE或UPDATE, 也可以是这几个事件的组合,还可以是UPDATE OF<触发列,…>,即进一步指明修改哪些列时激活触发器。
  • AFTER/BEFORE是触发的时机
    AFTER表示在触发事件的操作执行之后激活触发器
    BEFORE表示在触发事件的操作执行之前激活触发器

触发器类型:行级触发器(FOR EACH ROW)、语句级触发器(FOR EACH STATEMENT)
例如,在例5.11的TEACHER表上创建一个AFTER UPDATE触发器,触发事件是UPDATE语句:
UPDATE TEACHER SET Deptno=5;
假设表TEACHER有1000行
如果是语句级触发器,那么执行完该语句后,触发动作只发生1次
如果是行级触发器,触发动作将执行1000次
注意:不同的RDBMS产品触发器语法各不相同

【例5.21】当对表SC的Grade属性进行修改时,若分数增加了10%则将此次操作记录到下面表中:
SC_U(Sno,Cno,Oldgrade,Newgrade)
其中Oldgrade是修改前的分数,Newgrade是修改后的分数。

CREATE TRIGGER SC_T
AFTER UPDATE OF Grade ON SC
REFERENCING
OLD row AS OldTuple,
NEW row AS NewTuple
FOR EACH ROW
WHEN (NewTuple.Grade>=1.1*OldTuple.Grade)
INSERT INTO SC_U(Sno,Cno,OldGrade,NewGrade)
VALUES (OldTiple.Sno,OldTuple.Cno,OldTuple.Grade,NewTuple.Grade)

【5.22】将每次对表Student的插入操作所增加的学生个数记录到表StudentInsertLog中。

CREATE TRIGGER Student_Count
AFTER INSERT ON Student  	         
REFERENCING
NEW TABLE AS DELTA
FOR EACH STATEMENT  /*语句级触发器*/
INSERT INTO StudentInsertLog (Numbers)
SELECT COUNT(*) FROM DELTA

这里参考老师的博客:【Transact-SQL】教材 [例5.22] “触发器”(TRIGGER)
触发器使用说明:
1、 参考教材内容,新建Student表
2、新建表StudentInsertLog
存储学生人数

CREATE TABLE StudentInsertLog
(
Numbers INT
)

3、新建表StudentInsertLogUser
存储用户名和操作时间

CREATE TABLE StudentInsertLogUser
(
  UserName nchar(10),
  DateAndTime datetime
)

4、 新建触发器Student_Count
当插入新的学生记录时,触发器启动,自动在StudentInsertLog记录学生人数

CREATE TRIGGER Student_Count
ON Student  	         
AFTER
INSERT
AS 
    INSERT INTO StudentInsertLog(Numbers)
	  SELECT COUNT(*) FROM Student

5、新建触发器Student_Time
当插入新的学生记录时,触发器启动,自动在StudentInsertLogUser记录用户名和操作时间

CREATE TRIGGER Student_Time
ON Student  	         
AFTER
INSERT
AS 
	declare @UserName    nchar(10)
	declare @DateTime    datetime
/*这里相当于是定义变量名称*/
	select @UserName = system_user
	select @DateTime = CONVERT(datetime,GETDATE(),120) 
/*这里相当于给变量赋值*/
	INSERT INTO StudentInsertLogUser(UserName,DateAndTime)
	VALUES (@UserName,@DateTime)

6、测试触发器效果

INSERT
INTO  Student
VALUES ('201215135','王五','男',18,'CS');
SELECT * FROM Student
SELECT * FROM StudentInsertLog
SELECT * FROM StudentInsertLogUser

在这里插入图片描述
在这里插入图片描述
再插入一条数据时:
在这里插入图片描述
【例5.23】定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则“教授的工资不得低于4000元,如果低于4000元,自动改为4000元”。

CREATE TRIGGER Insert_Or_Update_Sal 
 BEFORE INSERT OR UPDATE ON Teacher  
/*触发事件是插入或更新操作*/
FOR EACH ROW        /*行级触发器*/
BEGIN /*定义触发动作体,是PL/SQL过程块*/
        IF (new.Job='教授') AND (new.Sal < 4000) 
        THEN  new.Sal :=4000;                
        END IF;
END;              

IF与END IF 相对应,BEGIN与END 相对应。
这些语句在SQL SERVER 中运行时可能归出现错误

sql server 创建触发器的语句格式:(参考链接)sql server 创建触发器的语句格式

CREATE TRIGGER 触发器名 ON 表名/视图名
{ FOR | AFTER | INSTEAD OF } { [DELETE] [,] [INSERT] [,] [UPDATE] }
AS
  触发器内容(SQL 语句)

2、激活触发器
触发器的执行,是由触发事件激活的,并由数据库服务器自动执行
一个数据表上可能定义了多个触发器,遵循如下的执行顺序:
(1) 执行该表上的BEFORE触发器;
(2) 激活触发器的SQL语句;
(3) 执行该表上的AFTER触发器。
3、删除触发器
删除触发器的SQL语法:

 DROP TRIGGER <触发器名> ON <表名>;

存储过程:由过程化SQL语句,经编译和优化后存储在数据库服务器中,可以被反复调用,运行速度较快。(类似C语言中的函数)
(1)创建存储过程

CREATE OR REPLACE PROCEDURE 过程名([参数1,参数2,...]) AS <过程化SQL>

(2)执行存储过程

 CALL/PERFORM  PROCEDURE 过程名([参数1,参数2,...])

使用CALL或者PERFORM等方式激活存储过程的执行
数据库服务器支持在过程体中调用其他存储过程
(3)修改存储过程

ALTER PROCEDURE 过程名1  RENAME TO 过程名2;

(4)删除存储过程

 DROP  PROCEDURE 过程名()

【例8.8】利用存储过程来实现下面的应用:从账户1转指定数额的款项到账户2中。

CREATE OR REPLACE PROCEDURE TRANSFER(inAccount INT,outAccount  INT,amount FLOAT) 
 /*定义存储过程TRANSFER,参数为转入账户、转出账户、转账额度*/
 /*这是标准SQL ,T-SQL的步骤在下面,使用@*/
	AS DECLARE		/*定义变量*/
	    totalDepositOut Float;
        totalDepositIn Float;
		inAccountnum INT;
BEGIN                         	    /*检查转出账户的余额 */
	       SELECT Total INTO totalDepositOut FROM Accout
	            WHERE accountnum=outAccount;
	       IF totalDepositOut IS NULL THEN  
            	   /*如果转出账户不存在或账户中没有存款*/
	                ROLLBACK; 	   /*回滚事务*/
	                RETURN
	       END IF;
   IF totalDepositOut< amount THEN    	/*如果账户存款不足*/
	       ROLLBACK; 				/*回滚事务*/
	       RETURN
   END IF
   SELECT Accountnum INTO inAccountnum FROM Account
      WHERE accountnum=inAccount;
   IF inAccount IS NULL THEN  		/*如果转入账户不存在*/                        
	  ROLLBACK; 	         	 		/*回滚事务*/
	  RETURN;
   END IF;
   UPDATE Account SET total=total-amount
    WHERE accountnum=outAccount; /* 修改转出账户余额,减去转出额 */
   UPDATE Account SET total=total + amount 
    WHERE   accountnum=inAccount; /* 修改转入账户余额,增加转入额 */
   COMMIT;                       	/* 提交转账事务 */
END;

在T-SQL中定义变量时加上@,如@inAccount INT
【例8.9】 从账户01003815868转10000元到01003813828账户中。

CALL PROCEDURE TRANSFER(01003813828,01003815868,10000);

步骤: 参考老师的博客:(参考博客)【Transact-SQL】教材 [例8.8] “存储过程”(PROCEDURE)
1、建立新表Account,并写入两个用户

DROP TABLE IF EXISTS Account;

CREATE TABLE Account
(
accountnum CHAR(3),	-- 账户编号
total FLOAT		-- 账户余额
);

INSERT INTO Account VALUES(101,50);
INSERT INTO Account VALUES(102,100);

SELECT * FROM Account

在这里插入图片描述
2、建立存储过程

IF (exists (select * from sys.objects where name = 'Proc_TRANSFER'))
    DROP PROCEDURE Proc_TRANSFER
GO
CREATE PROCEDURE Proc_TRANSFER 
@inAccount INT,@outAccount  INT,@amount FLOAT
 /*定义存储过程TRANSFER,参数为转入账户、转出账户、转账额度*/
AS
BEGIN TRANSACTION TRANS   
   	DECLARE		/*定义变量*/
	@totalDepositOut Float,
	@totalDepositIn Float,
	@inAccountnum INT;
	 /*检查转出账户的余额 */     
	SELECT @totalDepositOut = total FROM Account	WHERE accountnum = @outAccount;
	/*如果转出账户不存在或账户中没有存款*/
	IF @totalDepositOut IS NULL               	   
		BEGIN
			PRINT '转出账户不存在或账户中没有存款'
			ROLLBACK TRANSACTION TRANS; 	   /*回滚事务*/
			RETURN;
		END;
	/*如果账户存款不足*/
	IF @totalDepositOut < @amount     	
		BEGIN
			PRINT '账户存款不足'
			ROLLBACK TRANSACTION TRANS; 				/*回滚事务*/
			RETURN;
		END
	/*检查转入账户的状态 */  
	SELECT @inAccountnum = accountnum  FROM Account	WHERE accountnum = @inAccount;
	/*如果转入账户不存在*/ 
	IF @inAccountnum IS NULL   		                       
		BEGIN
			PRINT '转入账户不存在'
			ROLLBACK TRANSACTION TRANS; 	         	 		/*回滚事务*/
			RETURN;
		END;
	/*如果条件都没有异常,开始转账。*/ 
	BEGIN
		UPDATE Account SET total = total - @amount	WHERE	accountnum = @outAccount; /* 修改转出账户余额,减去转出额 */
		UPDATE Account SET total = total + @amount	WHERE   accountnum = @inAccount; /* 修改转入账户余额,增加转入额 */
		PRINT '转账完成,请取走银行卡'
		COMMIT TRANSACTION TRANS;                       	/* 提交转账事务 */
		RETURN;
	END

在这里插入图片描述
3. 执行存储过程
(1)正常情况:

EXEC	Proc_TRANSFER
		@inAccount = 101,	--转入账户
		@outAccount = 102,	--转出账户
		@amount = 50		--转出金额

SELECT * FROM Account

在这里插入图片描述
(2)当余额不足情况,

EXEC	Proc_TRANSFER
		@inAccount = 101,	--转入账户
		@outAccount = 102,	--转出账户
		@amount = 100		--转出金额

SELECT * FROM Account

在这里插入图片描述
(3)当转入的账户不存在情况

EXEC	Proc_TRANSFER
		@inAccount = 103,	--转入账户
		@outAccount = 102,	--转出账户
		@amount = 100		--转出金额

SELECT * FROM Account

在这里插入图片描述
(4)当转出的账户不存在的情况时

EXEC	Proc_TRANSFER
		@inAccount = 101,	--转入账户
		@outAccount = 105,	--转出账户
		@amount = 10		--转出金额

SELECT * FROM Account

在这里插入图片描述
当转账情况不合实际时都显示出原来的账户情况。

函数和存储过程的异同
同:都是持久性存储模块
异:函数必须指定返回的类型
1、函数的定义语句格式
CREATE OR REPLACE FUNCTION 函数名 ([参数1,参数2,…]) RETURNS <类型> AS <过程化SQL块>;
2、 函数的执行语句格式
CALL/SELECT 函数名 ([参数1,参数2,…]);
3、 修改函数

  • 重命名
    ALTER FUNCTION 过程名1 RENAME TO 过程名2;
  • 重新编译
    ALTER FUNCTION 过程名 COMPILE;

总结:触发器和存储过程方面理解还需要加强,基本可以看懂,但是自己写不出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值