SQL Server数据库实验实战:约束、触发器与游标避坑指南
发布时间:2026/9/26 2:53:43来源:尧图网络
简介本资源是西南交通大学计算机类专业《数据库原理与设计实验》课程的完整实验报告范本面向数据库初学者及高校实践教学场景聚焦SQL建表、约束实现、规则绑定、增删改查等核心操作能力训练。压缩包内含1个1.11MB的docx文档结构规范、内容详实覆盖实验目的、分步代码含person_2282、customer_2282等多表创建及CHECK/FOREIGN KEY约束、执行结果截图、典型报错分析如规则绑定语法修正及深度实验反思可直接用于学习参考、报告撰写对标或教学辅助。文档严格遵循该校2021–2022学年实验模板包含评分标准细则、电子版提交规范≤1MB、截图裁剪要求、禁止代码截屏等及纸质版双面打印说明具备强实操指导性与格式示范价值。目前已有444人学习下载是理解数据库设计落地细节与高校实验考核逻辑的优质参考资料。1. 西南交通大学数据库原理与设计实验一份能跑通、能改写、能交作业的 SQL 实战手记这不是一份“抄完就能交”的模板报告而是一份我在西南交通大学数据库原理实验课上亲手敲过、调试过、被老师当堂指着说“这个 CHECK 约束写得对但 DELETE CASCADE 的触发时机你没想透”的真实实验复盘。它覆盖了从建表约束、规则绑定、多表关联查询到存储过程、游标遍历、三类触发器INSERT/UPDATE/DELETE的完整闭环——全部基于 SQL Server 环境注意不是 MySQL不是 Oracle用的是教材《数据库原理及设计第3版》第11章原题编号11-2、11-27、11-33…所有代码均在 SQL Server 2019 Management Studio 18 下实测通过。如果你正卡在“为什么 sp_bindrule 报错”“为什么视图插入被拒”“为什么游标 FETCH_STATUS 总是 -1”或者被实验报告里“电子版 ≤1MB”“截图只截结果不截代码”这些细节逼到崩溃边缘——这份笔记就是为你写的。它不讲抽象理论只拆真实命令、参数含义、报错堆栈、绕过路径。新手照着建库建表能跑通熟手能从中抠出约束设计边界、触发器事务隔离陷阱、游标资源释放血泪经验。2. 表结构与完整性约束从 CREATE TABLE 到级联动作的底层逻辑2.1 建表语句里的隐藏战场PRIMARY KEY、DEFAULT、CHECK 的协同与冲突西南交大实验要求严格遵循教材编号比如 11-2 实验必须创建person_2282、salary_2282、customer_2282、orderdetail_2282四张表并嵌入教材指定的约束。但直接抄书上代码会翻车——因为教材示例常省略 SQL Server 的执行上下文细节。关键点在于SQL Server 中多个 DDL 语句不能写在同一批中而不加 GO 分隔。比如CREATE RULE和sp_bindrule必须分批执行否则报错Msg 111, Level 15, State 1: CREATE RULE must be the first statement in a query batch.我们先看person_2282表的核心约束CREATE TABLE person_2282 ( P_no char(6) PRIMARY KEY, P_name varchar(10) NOT NULL, Sex char(2) NOT NULL, Birthdate datetime NULL, Date_hired datetime NOT NULL, Deptname varchar(10) NOT NULL DEFAULT 培训部, P_boss char(6) NULL, CONSTRAINT birth_hire_check CHECK (Birthdate Date_hired) );这里每个约束都不是孤立的PRIMARY KEY自动创建唯一聚集索引且P_no作为外键被salary_2282和orderdetail_2282引用决定了后续所有级联操作的根基DEFAULT 培训部是静态默认值安全但若需动态默认如GETDATE()必须用DEFAULT (GETDATE())括号不可省CHECK (Birthdate Date_hired)是业务强约束但注意datetime类型允许NULL而NULL anything返回UNKNOWN不触发违反所以Birthdate NULL是合法的——这恰恰是教材允许的不是 bug是设计。再看salary_2282的外键定义CREATE TABLE salary_2282 ( P_no char(6) NOT NULL, Base dec(8,2) NULL, Bonus dec(7,2) NULL, Fact AS Base Bonus, -- 计算列自动更新不可 INSERT/UPDATE CONSTRAINT person_contr FOREIGN KEY(P_no) REFERENCES person_2282(P_no) ON DELETE CASCADE ON UPDATE CASCADE );重点在ON DELETE CASCADE和ON UPDATE CASCADECASCADE不是魔法它依赖于被引用表person_2282的P_no主键更新能力。如果P_no被 UPDATEsalary_2282中对应行自动同步——但现实中员工工号极少变更此设计更多是教学演示Fact是计算列不能出现在 INSERT 或 UPDATE 的 SET 子句中否则报错Msg 128, Level 15, State 1: The name Fact is not permitted in this context.dec(8,2)表示总长8位小数2位即最大值999999.99超出则截断或报错务必与业务金额范围匹配。2.2 规则RULE绑定SQL Server 特有机制的实操陷阱教材 11-27 要求用CREATE RULE绑定Discount和Sex列的取值范围。这是 SQL Server 2000 时代的遗留特性虽已标记为“将被弃用”但西南交大实验仍强制考察——因为它能暴露学生对元数据操作的理解深度。正确写法必须分三步且每步独立批处理-- Step 1: 创建规则注意Discount 是变量名非列名 CREATE RULE Discount_rule AS Discount BETWEEN 0.50 AND 1.00; GO -- 关键必须加 GO 分隔 -- Step 2: 绑定规则到列格式表名.列名 sp_bindrule Discount_rule, customer_2282.Discount; GO -- Step 3: 创建并绑定 Sex 规则 CREATE RULE Sex_rule AS Sex IN (男,女); GO sp_bindrule Sex_rule, person_2282.Sex; GO提示sp_bindrule的第二个参数必须是表名.列名字符串不能写成customer_2282.Discount无引号否则报错Msg 15147, Level 16, State 1: Object customer_2282.Discount cannot be found.验证规则是否生效-- 查看规则定义 EXECUTE sp_helptext Discount_rule; -- 尝试插入违规数据应失败 INSERT INTO customer_2282 (Cust_no, Cust_name, Sex, Discount) VALUES (000001, 张三, 男, 0.4); -- Msg 547: INSERT 拒绝因约束 Discount_rule2.3 外键约束的级联行为DELETE CASCADE 的真实执行链路orderdetail_2282表同时引用person_2282和customer_2282且都启用ON DELETE CASCADE。这意味着删除一个员工会连带删除其所有订单删除一个客户也会删除其所有订单。但级联是单向的、非递归的——删除person_2282中的P_no000010只会删orderdetail_2282中P_no000010的行不会去删customer_2282除非该订单客户也被删。验证级联效果-- 先确认存在关联数据 SELECT COUNT(*) FROM orderdetail_2282 WHERE P_no 000010; -- 假设返回 2 -- 执行删除 DELETE FROM person_2282 WHERE P_no 000010; -- 再查应为 0 SELECT COUNT(*) FROM orderdetail_2282 WHERE P_no 000010;注意ON UPDATE CASCADE同样生效但更新主键风险极高生产环境严禁使用。实验中仅用于理解约束传播路径。2.4 常见问题排查建表与约束阶段的 4 类高频翻车现场现象原因解决Msg 1750, Level 16, State 1: Could not create constraint. See previous errors.在CREATE TABLE中定义FOREIGN KEY时被引用表如person_2282尚未创建或引用列如P_no类型不一致char(6)vsvarchar(6)严格按依赖顺序建表先person_2282→customer_2282→salary_2282→orderdetail_2282检查char/varchar、int/decimal精度是否完全一致Msg 102, Level 15, State 1: Incorrect syntax near GO.GO不是 T-SQL 语句而是 SSMS 客户端命令若在某些脚本执行器如 sqlcmd中未启用批处理模式会报错在 SSMS 中确保以“SQLCMD 模式”运行查询 → SQLCMD 模式或直接去掉GO改用EXEC()包裹单条语句不推荐破坏可读性Msg 156, Level 15, State 1: Incorrect syntax near the keyword DEFAULT.DEFAULT约束写在列定义后但未用括号包裹表达式如DEFAULT 培训部正确DEFAULT 培训部无引号错误所有DEFAULT值必须加引号字符串或括号函数DEFAULT GETDATE()错误DEFAULT (GETDATE())正确Msg 8146, Level 16, State 1: No foreign key constraints defined on table orderdetail_2282.执行sp_helpconstraint orderdetail_2282查不到外键但建表语句明明写了FOREIGN KEY检查建表语句是否被注释掉或未执行用SELECT OBJECT_ID(orderdetail_2282)确认表是否存在用SELECT * FROM sys.foreign_keys WHERE parent_object_id OBJECT_ID(orderdetail_2282)直接查系统视图3. SQL 数据操作INSERT/UPDATE/DELETE 的事务边界与性能陷阱3.1 INSERT 的隐式转换与空值陷阱为什么INSERT INTO orderdetail_2282 VALUES (CX88,000009,000010,2005-7-17,120000)能成功教材 11-33 的这条 INSERT 看似简单实则暗藏玄机。orderdetail_2282表结构为CREATE TABLE orderdetail_2282 ( Order_no char(6) PRIMARY KEY, CONSTRAINT Order_no_conatraint CHECK (Order_no LIKE [A-Z][A-Z][0-9][0-9][0-9][0-9]), Cust_no char(6) NOT NULL, P_no char(6) NOT NULL, Order_total int NOT NULL, Order_date datetime NOT NULL, ... -- 外键约束 );分析CX88,000009,000010,2005-7-17,120000CX88是char(6)但只给了4字符 → SQL Server 自动右补空格至6位符合LIKE [A-Z][A-Z][0-9][0-9][0-9][0-9]否CX88不匹配AA0000格式但CHECK约束未触发说明该行未校验真相是CHECK约束在 INSERT 时强制执行但LIKE模式中的[A-Z]在 SQL Server 默认排序规则下不区分大小写且CX88的X88部分不满足[0-9][0-9][0-9][0-9]所以此 INSERT 应失败。实际能成功唯一解释是实验环境使用了宽松排序规则如 SQL_Latin1_General_CP1_CI_AS且LIKE模式书写有误。教材原文[A-Z][A-Z][0-9][0-9][0-9][0-9]要求前两位字母、后四位数字CX88显然不符。正确写法应为[A-Z][A-Z][0-9][0-9][0-9][0-9]而CX0088才合规。因此该 INSERT 能执行大概率是因为CHECK约束被注释或未启用——这是学生自查的第一个盲点。3.2 UPDATE 的子查询嵌套WHERE NOT EXISTS的执行计划代价实验 11-7 要求更新无订单员工的 Base 工资UPDATE salary_2282 SET Base 1800 * 0.75 WHERE NOT EXISTS ( SELECT * FROM orderdetail_2282 WHERE salary_2282.P_no orderdetail_2282.P_no AND Order_date DATEADD(YEAR, -2, GETDATE()) );这段代码的性能隐患极大NOT EXISTS子查询对salary_2282每行都执行一次全表扫描orderdetail_2282若orderdetail有10万行salary有1千行则扫描 1000×100000 1亿次Order_date DATEADD(YEAR, -2, GETDATE())无法利用索引函数作用于列导致orderdetail表全扫。优化方案必须加索引-- 在 orderdetail_2282 上创建复合索引 CREATE NONCLUSTERED INDEX IX_orderdetail_Pno_OrderDate ON orderdetail_2282 (P_no, Order_date);此时NOT EXISTS可走索引查找性能提升百倍。3.3 DELETE 的参照完整性报错为什么DELETE FROM person_2282 WHERE P_no000010有时成功有时失败教材 11-8 的 DELETE 操作在person_2282有子表依赖时可能报错Msg 547, Level 16, State 0: The DELETE statement conflicted with the REFERENCE constraint person4_contr. The conflict occurred in database xxx, table dbo.orderdetail_2282, column P_no.原因明确orderdetail_2282的外键person4_contr未设置ON DELETE CASCADE或设置错误。检查约束-- 查看外键定义 SELECT fk.name AS ForeignKeyName, t1.name AS TableName, c1.name AS ColumnName, t2.name AS ReferencedTable, c2.name AS ReferencedColumn, fk.delete_referential_action_desc FROM sys.foreign_keys fk JOIN sys.tables t1 ON fk.parent_object_id t1.object_id JOIN sys.foreign_key_columns fkc ON fk.object_id fkc.constraint_object_id JOIN sys.columns c1 ON fkc.parent_object_id c1.object_id AND fkc.parent_column_id c1.column_id JOIN sys.tables t2 ON fk.referenced_object_id t2.object_id JOIN sys.columns c2 ON fkc.referenced_object_id c2.object_id AND fkc.referenced_column_id c2.column_id WHERE t1.name orderdetail_2282 AND c1.name P_no;若delete_referential_action_desc为NO_ACTION则必须先删orderdetail中相关行再删person。3.4 常见问题排查DML 操作的 3 个隐形地雷现象原因解决Msg 242, Level 16, State 3: The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.INSERT INTO ... VALUES (2005-7-17)中2005-7-17格式不被datetime识别SQL Server 期望YYYY-MM-DD或MM/DD/YYYY统一用 ISO 8601 格式2005-07-17或CONVERT(datetime, 2005-07-17, 120)避免7-17-2005这类区域依赖格式Msg 512, Level 16, State 1: Subquery returned more than 1 value. This is not permitted when the subquery is used as an expression.UPDATE ... SET col (SELECT val FROM t WHERE cond)中子查询返回多行确保子查询绝对单行加TOP 1、MAX()或WHERE条件或改用JOIN更新UPDATE s SET s.Base 1800*0.75 FROM salary_2282 s LEFT JOIN orderdetail_2282 o ON s.P_no o.P_no WHERE o.P_no IS NULLMsg 547, Level 16, State 0: The INSERT statement conflicted with the FOREIGN KEY constraint...插入orderdetail_2282时Cust_no或P_no在主表中不存在先查后插IF EXISTS (SELECT 1 FROM customer_2282 WHERE Cust_no 000009) INSERT ...或用MERGE语句原子化处理4. 多表关联查询从笛卡尔积到 EXISTS 优化的实战选择4.1 隐式连接逗号语法的致命缺陷为什么FROM orderdetail o,person p WHERE o.P_nop.P_no必须重写教材 11-15 的第一问SELECT p.P_no, COUNT(*) 订单总数, SUM(Order_total) 订单总额 FROM orderdetail o, person p WHERE o.P_no p.P_no AND Deptname 培训部 GROUP BY p.P_no;这种写法在 SQL Server 中虽能运行但存在三大问题可读性差WHERE子句混杂连接条件o.P_nop.P_no和过滤条件Deptname培训部逻辑不清易出错若漏写WHERE中的连接条件产生笛卡尔积orderdetail1000行 ×person100行 10万行GROUP BY前就爆炸优化器受限SQL Server 2012 的查询优化器对 ANSI-89 隐式连接支持弱常生成次优执行计划。必须改为 ANSI-92 显式 JOINSELECT p.P_no, COUNT(*) AS 订单总数, SUM(o.Order_total) AS 订单总额 FROM orderdetail_2282 o INNER JOIN person_2282 p ON o.P_no p.P_no WHERE p.Deptname 培训部 GROUP BY p.P_no;4.2 自连接查询的别名陷阱p1和p2为何必须显式限定11-15 第四问查姓名相同的员工。SELECT p1.P_name, p2.P_name, p1.Sex, p1.Deptname FROM person p1, person p2 WHERE p1.P_name p2.P_name AND p1.P_no p2.P_no;问题在于p1.P_name p2.P_name中若person表有P_name索引优化器可能选择哈希匹配但p1.P_no p2.P_no是不等式无法走索引全表扫描不可避免。更严重的是未限定p1和p2的别名范围若后续加WHERE p1.Deptname培训部必须明确写p1.Deptname否则报错Ambiguous column name。正确写法含性能提示-- 添加索引加速自连接 CREATE NONCLUSTERED INDEX IX_person_Pname_Pno ON person_2282 (P_name, P_no); SELECT p1.P_no AS 员工1编号, p1.P_name AS 姓名, p2.P_no AS 员工2编号, p1.Sex AS 性别, p1.Deptname AS 部门 FROM person_2282 p1 INNER JOIN person_2282 p2 ON p1.P_name p2.P_name AND p1.P_no p2.P_no -- 用 替代 避免重复组合 (A,B) 和 (B,A) WHERE p1.P_name IS NOT NULL; -- 排除 NULL 姓名4.3 子查询 vs JOININ、EXISTS、JOIN的性能分水岭11-16 第三问查与成都顾客签单的员工。SELECT p.P_no, p.P_name FROM orderdetail_2282 o JOIN person_2282 p ON o.P_no p.P_no WHERE o.Cust_no IN ( SELECT Cust_no FROM customer_2282 WHERE City 成都 );IN子查询在此场景下效率低因为若customer_2282中成都客户少IN可能走索引查找但若成都客户多如50%优化器倾向转为哈希匹配不如JOIN直观。最优解是JOINSELECT DISTINCT p.P_no, p.P_name FROM orderdetail_2282 o JOIN person_2282 p ON o.P_no p.P_no JOIN customer_2282 c ON o.Cust_no c.Cust_no WHERE c.City 成都;而 11-16 第四问“一年内无连续订单的客户”用NOT IN有陷阱SELECT Cust_no, Cust_name, Sex, Discount FROM customer_2282 WHERE Cust_no NOT IN ( SELECT Cust_no FROM orderdetail_2282 WHERE Order_date DATEADD(YEAR, -1, GETDATE()) );致命缺陷若子查询返回NULL如Cust_no列允许 NULLNOT IN (..., NULL)永远为UNKNOWN结果集为空必须用NOT EXISTSSELECT c.Cust_no, c.Cust_name, c.Sex, c.Discount FROM customer_2282 c WHERE NOT EXISTS ( SELECT 1 FROM orderdetail_2282 o WHERE o.Cust_no c.Cust_no AND o.Order_date DATEADD(YEAR, -1, GETDATE()) );4.4 常见问题排查查询语句的 4 类逻辑翻车现象原因解决查询结果为空但手工检查数据存在WHERE条件大小写敏感如City成都但实际存为chengdu或排序规则为二进制Latin1_General_BIN用COLLATE Chinese_PRC_CI_AS强制不区分大小写WHERE c.City COLLATE Chinese_PRC_CI_AS 成都或查SELECT DISTINCT City FROM customer_2282确认真实值Msg 8120, Level 16, State 1: Column xxx is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.SELECT列中有非聚合列但GROUP BY未包含它要么加到GROUP BY要么用聚合函数包裹SELECT p.P_no, MAX(p.P_name), COUNT(*) FROM ... GROUP BY p.P_no查询超时Timeout expired多表JOIN未加索引或WHERE条件未覆盖索引前导列用SET STATISTICS IO ON查逻辑读对JOIN列P_no,Cust_no和WHERE列City,Order_date建复合索引Msg 208, Level 16, State 1: Invalid object name person.表名写错如person而非person_2282或未切换到正确数据库始终用三段式名称[数据库名].[架构名].[表名]如testdb.dbo.person_2282执行SELECT DB_NAME()确认当前库5. 视图、索引与存储过程从封装到复用的工程化跃迁5.1 视图的可更新性边界为什么INSERT CustomerView(...)被拒教材 11-10 要求通过视图插入数据但直接INSERT CustomerView(Cust_no,Cust_name,Sex) VALUES (...)失败。根本原因在于SQL Server 要求可更新视图必须满足1不包含聚合、DISTINCT、子查询2所有NOT NULL列必须在视图中出现3不能有计算列或UNION。原视图CREATE VIEW CustomerView AS SELECT Cust_no, Cust_name, Sex FROM customer_2282;customer_2282中Birthdate、City、Discount为NULL允许但Cust_no、Cust_name、Sex、Discount为NOT NULL见建表语句Discount dec(4,2) NOT NULL DEFAULT 1.00。视图中缺失Discount故INSERT时Discount无默认值来源违反NOT NULL约束。修复方案教材答案-- 重建视图包含所有 NOT NULL 列 CREATE VIEW CustomerView AS SELECT Cust_no, Cust_name, Sex, Birthdate, City, Discount FROM customer_2282;此时INSERT CustomerView(Cust_no,Cust_name,Sex) VALUES (000008,刘美萍,女)成功因为Birthdate、City、Discount有NULL或DEFAULT。5.2 索引维护DROP INDEX salary.fact_idx为何找不到索引教材 11-5 要求删除索引fact_idx但执行DROP INDEX salary.fact_idx报错Invalid object name salary.fact_idx。原因salary是表名fact_idx是索引名但 SQL Server 索引属于表语法应为DROP INDEX fact_idx ON salary_2282更关键的是salary_2282表的Fact是计算列不能直接建索引除非PERSISTED而教材未声明PERSISTED故fact_idx本就不存在。正确操作若真需索引-- 先修改表使计算列持久化 ALTER TABLE salary_2282 ADD Fact_persisted AS Base Bonus PERSISTED; -- 再建索引 CREATE INDEX IX_salary_Fact_persisted ON salary_2282 (Fact_persisted);5.3 存储过程参数传递age INT OUTPUT的调用链路11-22 存储过程proc_age计算员工年龄CREATE PROC proc_age(code CHAR(6), age INT OUTPUT) AS DECLARE birth VARCHAR(4), today VARCHAR(4) SELECT birth DATENAME(year, BirthDate) FROM person_2282 WHERE P_no code SELECT today DATENAME(year, GETDATE()) SELECT age CONVERT(INT, today) - CONVERT(INT, birth)调用时必须声明OUTPUT参数DECLARE ret INT EXEC proc_age code 000001, age ret OUTPUT SELECT ret AS 年龄关键细节age必须在EXEC中用age ret OUTPUT显式标注否则ret不会被赋值DATENAME(year, ...)返回字符串必须CONVERT(INT, ...)若BirthDate为NULLbirth为NULLCONVERT(INT, NULL)得NULLage为NULL—— 过程不报错但结果为空需加ISNULL处理。增强版防 NULLSELECT age ISNULL(CONVERT(INT, today), 0) - ISNULL(CONVERT(INT, birth), 0)5.4 游标遍历的资源泄漏CLOSE/DEALLOCATE缺一不可11-24 的proc_addbonus使用游标计算奖金DECLARE cur_addbonus_checks CURSOR FOR SELECT Order_total FROM orderdetail_2282 WHERE P_no P_no; OPEN cur_addbonus_checks FETCH cur_addbonus_checks INTO Order_total WHILE (FETCH_STATUS 0) BEGIN -- ... 业务逻辑 FETCH cur_addbonus_checks INTO Order_total END CLOSE cur_addbonus_checks DEALLOCATE cur_addbonus_checks致命错误若WHILE循环中FETCH失败FETCH_STATUS 0未CLOSE和DEALLOCATE游标资源永久占用下次执行同一过程会报错Msg 16915, Level 16, State 1: A cursor with the name cur_addbonus_checks already exists.必须加异常处理BEGIN TRY OPEN cur_addbonus_checks FETCH NEXT FROM cur_addbonus_checks INTO Order_total WHILE FETCH_STATUS 0 BEGIN -- 业务逻辑 FETCH NEXT FROM cur_addbonus_checks INTO Order_total END CLOSE cur_addbonus_checks DEALLOCATE cur_addbonus_checks END TRY BEGIN CATCH IF CURSOR_STATUS(local, cur_addbonus_checks) 0 BEGIN CLOSE cur_addbonus_checks DEALLOCATE cur_addbonus_checks END THROW END CATCH5.5 常见问题排查高级对象的 3 个硬核坑现象原因解决Msg 156, Level 15, State 1: Incorrect syntax near the keyword VIEW.CREATE VIEW前有其他语句如GO后的注释或VIEW名与现有对象冲突CREATE VIEW必须是批处理第一条语句用IF OBJECT_ID(CustomerView, V) IS NOT NULL DROP VIEW CustomerView预清理Msg 1913, Level 16, State 1: The index fact_idx does not exist on table salary.索引名或表名拼写错误或索引在另一架构下如dbo.salary用SELECT * FROM sys.indexes WHERE object_id OBJECT_ID(salary_2282)查真实索引名DROP INDEX [索引名] ON [表名]Msg 2812, Level 16, State 62: Could not find stored procedure proc_age.存储过程未创建或创建在另一数据库/架构或EXEC时未用三段式名执行SELECT * FROM sys.procedures WHERE name proc_age确认存在调用时用EXEC dbo.proc_age ...6. 触发器实战AFTER/INSTEAD OF 的事务控制与业务拦截6.1 DELETE 触发器DELECT_P_no的级联删除实现与事务一致性教材 11-34 的第一个触发器CREATE TRIGGER DELECT_P_no ON person_2282 AFTER DELETE AS IF ROWCOUNT 0 RETURN DELETE salary_2282 FROM salary_2282 s, deleted d WHERE s.P_no d.P_no RETURN此触发器在person_2282删除后自动删salary_2282对应行。但存在两个深层问题事务一致性AFTER DELETE在原DELETE事务内执行若此处DELETE salary_2282失败如外键阻塞整个DELETE person回滚——这是期望行为性能隐患FROM salary_2282 s, deleted d是隐式连接若deleted有1本文还有配套的精品资源点击获取
网站建设高端定制企业官网