有没有办法制作一个 mysqldump 来保存指定数据库中的所有触发器和过程?
前段时间我读到这mysqldump也将保存我的触发器,但它看起来不像。我的第二个相关问题是如果触发器存在,我如何检入 sql 文件?
我在表上有一个 UPDATE 触发器,用于监视从一个特定值更改为任何其他值的特定列。发生这种情况时,它会通过单个 UPDATE 语句更新另一个表中的一些相关数据。
触发器所做的第一件事是检查是否有任何更新的行的该列的值与相关值发生了变化。它只是将 INSERTED 连接到 DELETED 并比较该列中的值。如果没有任何条件,它会提前退出,因此 UPDATE 语句不会运行。
IF NOT EXISTS (
SELECT TOP 1 i.CUSTNMBR
FROM INSERTED i
INNER JOIN DELETED d
ON i.CUSTNMBR = d.CUSTNMBR
WHERE d.CUSTCLAS = 'Misc'
AND i.CUSTCLAS != 'Misc'
)
RETURN
Run Code Online (Sandbox Code Playgroud)
在这种情况下,CUSTNMBR 是基础表的主键。如果我对此表进行大量更新(例如 5000 多行),即使我没有触及 CUSTCLAS 列,该语句也需要 AGES。我可以在 Profiler 中看到它在这个语句上停滞了几分钟。
执行计划很奇怪。它显示了具有 3,714 次执行和约 1,850 万行输出的插入扫描。它通过 CUSTCLAS 列上的过滤器运行。它将这个(通过嵌套循环)连接到一个删除扫描(也在 CUSTCLAS 上过滤),它只执行一次并且有 5000 个输出行。
我在这里做了什么愚蠢的事情来导致这种情况?请注意,触发器绝对必须正确处理多行更新。
编辑:
我也尝试过这样写(以防 EXISTS 做了一些不愉快的事情),但它仍然一样糟糕。
DECLARE @CUSTNMBR varchar(31)
SELECT TOP 1 @CUSTNMBR = i.CUSTNMBR
FROM INSERTED i
INNER …Run Code Online (Sandbox Code Playgroud) 在设置审计跟踪时,跟踪谁在表中更新或插入记录没有问题,但是,跟踪谁删除记录似乎更成问题。
我可以通过在插入/更新字段中包含“UpdatedBy”来跟踪插入/更新。这允许 INSERT/UPDATE 触发器通过inserted.UpdatedBy. 但是,使用删除触发器不会插入/更新数据。有没有办法将信息传递给删除触发器,以便它知道谁删除了记录?
这是一个插入/更新触发器
ALTER TRIGGER [dbo].[trg_MyTable_InsertUpdate]
ON [dbo].[MyTable]
FOR INSERT, UPDATE
AS
INSERT INTO AuditTable (IdOfRecordedAffected, UserWhoMadeChanges)
VALUES (inserted.ID, inserted.LastUpdatedBy)
FROM inserted
Run Code Online (Sandbox Code Playgroud)
使用 SQL Server 2012
我真的很少使用触发器。所以我第一次遇到了一个问题。我有很多带有触发器的表(每个表有 2 个或更多)。我想知道并更改每个表的触发顺序。是否有可能获得这些信息?
添加:
这是我发现的关于 mssqltips 的一篇很好的文章。
我知道变异表错误是由设计缺陷或有问题的查询引起的。
最近将一个旧查询投入生产,它引发了一个变异表错误。我们的 DBA 解决了这个问题,但我们不知道如何解决。
究竟是什么导致了变异表错误,我们的 DBA 将如何解决这个问题?
我知道FOR EACH STATEMENT当我执行一个UPDATE t ....
现在,什么时候用t定义FOREIGN KEY ... REFERENCES a ... ON UPDATE CASCADE,我更新 N 行a,这会导致触发器被调用一次还是 N 次?
换句话说,对由 FK 约束级联的表的更改更像是单个UPDATE,还是更像是一系列UPDATEs?
我有一个 PostgreSQL (9.4) 数据库,它根据当前用户限制对记录的访问,并跟踪用户所做的更改。这是通过视图和触发器实现的,并且在大多数情况下效果很好,但是我在需要INSTEAD OF触发器的视图上遇到了问题。我试图减少问题,但我提前道歉,这仍然很长。
到数据库的所有连接都是通过单个帐户从 Web 前端建立的dbweb。连接后,角色将通过SET ROLEWeb 界面更改为对应的人,所有此类角色都属于组角色dbuser。(有关详细信息,请参阅此答案)。让我们假设用户是alice。
我的大部分表都放置在一个架构中,在这里我将调用该架构private并属于dbowner. 这些表不能直接dbuser被其他角色访问,但可以被其他角色访问dbview。例如:
SET SESSION AUTHORIZATION dbowner;
CREATE TABLE private.incident
(
incident_id serial PRIMARY KEY,
incident_name character varying NOT NULL,
incident_owner character varying NOT NULL
);
GRANT ALL ON TABLE private.incident TO dbview;
Run Code Online (Sandbox Code Playgroud)
特定行对当前用户的可用性alice由其他视图确定。一个简化的例子(可以减少,但需要以这种方式来支持更一般的情况)是:
-- Simplified case, but in principle could join multiple tables to determine allowed ids …Run Code Online (Sandbox Code Playgroud) 背景
我为大型健康记录数据库编写了很多大型报告,并且通常维护大型健康记录数据库(编写 SP、函数、作业等)。原始模式和使用它的软件来自不同的供应商,因此我无法在结构上对其进行太多更改。有许多记录需要跟踪,例如实验室、程序、疫苗等,它们分散在几十个表中,其中许多表臃肿且索引不佳(我已经能够稍微解决这个问题)。
问题
问题是,因为我们对数据库几乎没有控制,而且由于它可以从任何给定的更新或补丁中更改,这使得编写和维护这些报告变得困难和乏味——尤其是当存在大量重叠时。只需要一个补丁,我就不得不重写十多份报告的大部分内容。此外,随着连接、嵌套选择和应用堆积,查询很快变得模糊和缓慢。
我的“解决方案”
我的计划是将所有这些记录写入一个“全能”表,并在原始表上写入触发器以维护该聚合表中的记录。当然,我需要确保我的触发器在更新后完好无损,但从可维护性的角度来看,这会容易得多,只需引用数据。
表会又细又长,只存储所需的数据,如下所示:
CREATE TABLE dbo.HCM_Event_Log (
id INT IDENTITY,
type_id INT NULL,
orig_id VARCHAR(36) NULL,
patient_id UNIQUEIDENTIFIER NOT NULL,
visit_id UNIQUEIDENTIFIER NULL,
lookup_id VARCHAR(50) NULL,
status VARCHAR(15) NULL,
ordered_datetime DATETIME NULL,
completed_datetime DATETIME NULL,
CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)
Run Code Online (Sandbox Code Playgroud)
然后我会有各种关系表,比如 type_id 和项目分组。
我开始重新猜测这个想法,因为其中有几个表被写入了相当多的内容,我要编写的 SP 和报告也会引用很多数据。所以我担心这个表会成为具有如此多 I/O 的记录锁定和性能噩梦。
我的问题
是坏主意还是好主意?我意识到 SQL Server(2008 r2 标准版 BTW)和“有时”规则中的每种情况都不同,但我真的只是在寻找一般建议。
我开始考虑使用服务代理,但我只会执行简单的更新/插入(请参阅已接受答案的替代方法)。在许多情况下,数据需要是实时的,因此使用备份 DB 不会真正起作用。性能对我们来说已经是一个问题,但其中大部分与硬件相关,很快就会得到解决。
当然,我可以像这样对每一列进行比较:
if (old.column1 = new.column1 and old.column2 = new.column2...)
Run Code Online (Sandbox Code Playgroud)
但是,例如,如果我将来添加另一列,它将是硬编码的并且难以维护。
有没有办法检查所有列是否保持不变而无需手动检查每个单独的列?
当触发器被触发时,是否有任何方法可以从触发器内部判断它是由于另一个特定触发器中发生的 DML 操作而被触发的?
有关调用堆栈的任何信息是否有可能在函数中公开EVENTDATA()?或者其他功能?我宁愿不必分解 XML。
理想情况下,我希望从第二个触发器的范围内获取执行导致第二个触发器触发的 DML 的原始触发器的名称。但我也愿意接受类似的识别来源的方法。
我可以完全控制有问题的两个触发器的代码。
trigger ×10
sql-server ×4
postgresql ×3
audit ×1
backup ×1
foreign-key ×1
mysql ×1
mysqldump ×1
oracle ×1
plsql ×1
ssrs ×1
t-sql ×1
view ×1