sql触发器 递归 问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql触发器 递归 问题相关的知识,希望对你有一定的参考价值。
例: A表 触发器 中 delete from A where id =@id (这个是静态表名) 可以执行
由于我的表是动态表所以 改成 Exec('delete from ['+@A+'] where id=‘’+@ID+''') 就提示
Instead of 触发器不支持直接递归。 触发器 执行失败
而且经过我测试 改成exec 后删除表自身不能用动态的静态可以,触发其他表可以用改写成exec 形式
我用的是后置触发器 ,
我只说主要部分
我的问题是 是不是 改写exec 语句 就不能执行 执行自身删除 的触发器 还是???
这个 A 是动态表 也就是 @strTable 所以 我用 exec() 或者 set @Sql=‘’ 来 写
1.直接递归
当触发器被激活并执行一个操作时,该操作又使用同一个触发器再次执行操作,被称为直接递归。
例利用触发器的直接递归,当在表中删除一条记录时,通过触发器删除表中所有编号相同的记录。
2.间接递归
更改表1中的数据时,触发器被激活并执行一个操作,而该操作又使另一个表2中的某个触发器被激活。表2中的这个触发器使表1得到更新,从而再次激活表1中的触发器,被称为间接递归。
例如,一应用程序更新了表TA,并引发触发器Trigger_A。Trigger_A更新表TB,从而使触发器Trigger_B被引发。Trigger_B转而更新表TA,从而使Trigger_A再次被引发间接递归。
可以利用系统存储过程sp_dboption关闭直接递归,但这又会开启间接递归。若要把这两种类型的递归都禁止,需要使用系统存储过程sp_configure。
参考资料:明日系列编程词典--SQL Server 编程词典体验版
参考资料:百度一下
参考技术A 建议将 结果生成到字条变量中set @sql = 'delete from ['+@A+'] where id=‘’+@ID+'''
然后再执行 exec (@sql)
SQL 中的递归
【中文标题】SQL 中的递归【英文标题】:RECURSIVE in SQL 【发布时间】:2013-09-21 08:51:38 【问题描述】:我正在学习 SQL,并且很难理解以下递归 SQL 语句。
WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
SELECT sum(n) FROM t;
中的 n 和 t 是什么?据我所知,n 是 t 的一个集合。我说的对吗?
还有这个语句中的递归是如何触发的?
【问题讨论】:
不是。 MySQL 不支持with
或递归。你在考虑什么数据库?
MySQL 不支持WITH RECURSIVE
语法,因此我稍微扩大了问题范围以避免该问题。 (它被其他各种数据库支持。)
t
是一个表,n
是该表的一列。它使用CTE (Common Table Expression) to create recursion。基本上,它从1
(UNION
中的第一个选择)开始,然后对于每次迭代,它选择最后一个结果 + 1,直到n
等于 100(UNION
的第二部分)。然后,最后一个SELECT
(在 CTE 之外)对所有结果求和。不要被这个例子所迷惑,表被称为RECURSIVE
,那里没有魔法。这只是名字。
@GordonLinoff 感谢您指出这个问题。它应该在 PostgreSQL,而不是 MySQL。我犯了一个错误。
@duskwuff 感谢您纠正我的帖子。
【参考方案1】:
您使用的语法类似于 Postgres。 SQL 中的“递归”并不是真正的递归,而是迭代。你的说法是:
WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
t
的语句被评估为:
-
评估非自引用部分 (
select 1
)。
然后评估自引用部分。 (最初这给出 2。)
然后再次评估自引用部分。 (3)。
在条件仍然有效时以此类推 (n < 100
)。
完成后,t
子查询完成,可以评估最终语句。
【讨论】:
【参考方案2】:这称为Common Table Expression 或 CTE。
查询中的RECURSIVE
没有任何意义:它只是另一个名称,例如n
或t
。使事情递归的是名为 t
的 CTE 在表达式中引用自身。因此,要生成表达式的结果,查询引擎必须递归地构建结果,每次计算都会触发下一次计算。它到达这一点:SELECT n+1 FROM t...
并且必须停止并评估t
。为此,它必须再次调用自己,依此类推,直到条件 (n < 100
) 不再成立。 SELECT 1
提供了一个起点,WHERE n < 100
使查询不会永远重复。
至少,它在概念上应该是这样工作的。通常真正发生的是查询引擎迭代地构建结果,而不是递归地构建结果,如果可以的话,但那是另一回事了。
【讨论】:
recursive
确实意味着什么(它不是“另一个名字”)。如果您想要“递归”CTE,SQL 标准要求它。对于常规(非递归)CTE,您必须省略该关键字。【参考方案3】:
让我们分开:
WITH RECURSIVE t(n) AS (
一个公用表表达式 (CTE),它应该包括一个种子查询和一个递归查询。 CTE 称为 t 并返回 1 列:n
种子查询:
SELECT 1
返回 ans 答案集(在本例中只有一行:1)并将其副本放入最终答案集
现在开始递归部分:
UNION ALL
现在处理从种子查询返回的行,返回 n+1(同样是单行答案集:2)并复制到最终答案集中:
SELECT n+1 FROM t WHERE n < 100
如果此步骤返回非空答案集 (activity_count > 0),则会重复(永远)。
像 n+1 这样的计算中的 WHERE 条件通常用于避免无限递归。人们通常会根据数据知道可能的最大级别,对于复杂的查询,很容易把某些条件弄错;-)
最后返回答案集:
)
SELECT sum(n) FROM t;
当您简单地执行 SELECT * FROM t; 时,您会看到从 1 到 100 的所有数字,这不是生成此列表的一种非常有效的方法。
要记住的最重要的事情是,每个步骤都会产生最终结果的一部分,并且只有上一步中的那些行会在下一个递归级别中处理。
【讨论】:
以上是关于sql触发器 递归 问题的主要内容,如果未能解决你的问题,请参考以下文章