我在工作中陷入了争论,我需要一些关于我可能忽略的可能陷阱的建议。
想象一下使用触发器将删除的记录复制到审计表的场景。触发器使用 SELECT *。每个人都指指点点,大喊大叫,告诉我们这有多糟糕。
但是,如果对主表的结构进行了修改,而忽略了审计表,那么触发器将产生一个错误,让人们知道审计表也需要修改。
该错误将在我们的 DEV 服务器上进行测试时被捕获。但是我们需要确保生产与 DEV 匹配,因此我们允许在生产系统中使用 SELECT * (仅限触发器)。
所以我的问题是:我被要求删除 SELECT *,但我不确定如何确保我们自动捕获这种性质的开发错误,任何想法或这是最佳实践?
我在下面整理了一个例子:
--Create Test Table
CREATE TABLE dbo.Test(ID INT IDENTITY(1,1), Person VARCHAR(255))
--Create Test Audit Table
CREATE TABLE dbo.TestAudit(AuditID INT IDENTITY(1,1),ID INT, Person VARCHAR(255))
--Create Trigger on Test
CREATE TRIGGER [dbo].[trTestDelete] ON [dbo].[Test] AFTER DELETE
NOT FOR REPLICATION
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.TestAudit([ID], [Person])
SELECT *
FROM deleted
END
--Insert Test Data into Test
INSERT INTO dbo.Test VALUES
('Scooby')
,('Fred')
,('Shaggy')
--Perform a delete
DELETE dbo.Test WHERE Person = 'Scooby'
Run Code Online (Sandbox Code Playgroud)
更新(改写问题):
我是一名 DBA,需要通过为我们的最佳实践文档做出贡献来确保开发人员不会提供经过深思熟虑的部署脚本。当开发人员忽略审计表(这是一个安全网)时,SELECT * 会在 DEV 中导致错误,因此错误会在开发过程的早期被捕获。但在 SQL 宪法的某处 - 第二修正案中写着“你不得使用 SELECT *”。因此,现在正在推动摆脱安全网。
你会如何替换安全网,或者我应该认为这是触发器的最佳实践?
更新2:(解决方案)
感谢您的所有意见,我不确定我是否有明确的答案,因为这似乎是一个非常灰色的主题。但总的来说,你们提供的讨论要点可以帮助我们的开发人员继续定义他们的最佳实践。
感谢Daevin您的贡献,您的回答为我们的开发人员可以实施的一些测试机制奠定了基础。+1
谢谢CM_Dayton,您对最佳实践的建议对开发审计触发器的任何人都有益。+1
非常感谢ypercube,您对有关经历不同形式的定义更改的表的问题提出了很多想法。+1
综上所述:
Is Select * ok in a tigger? 是的,这是一个灰色地带,不要盲目遵循“选择*不好”的意识形态”。
Am I asking for Trouble? 是的,我们所做的不仅仅是向表中添加新列。
CaM*_*CaM 10
通常,它被认为是“惰性”编程。
鉴于您在此处专门将两个值插入到您的TestAudit表中,我会小心确保您的选择也恰好获得两个值。因为如果由于某种原因,该Test表具有或曾经获得第三列,则此触发器将失败。
与您的问题没有直接关系,但如果您要设置审核表,我还会在您的TestAudit表中添加一些额外的列以...
因此会产生如下查询:
INSERT dbo.TestAudit([ID], [Person], [AuditAction], [ChangedOn], [ChangedBy])
SELECT [ID], [Person],
'Delete', -- or a 'D' or a numeric lookup to an audit actions table...
GetDate(), -- or SYSDATETIME() for greater precision
SYSTEM_USER -- or some other value for WHO made the deletion
FROM deleted
Run Code Online (Sandbox Code Playgroud)
这样,您将获得所需的确切列,并审核审核事件的内容/时间/原因/谁。
提示触发器的语句将会失败,触发器也会失败。更好的做法是记录触发器和审计跟踪,以便您知道修改查询以添加列而不是指定 *。
至少您应该修改触发器,以便在将错误记录到表时它可以正常失败,并且可能在触发器正在记录错误的表上发出警报。
这也让人想起,当有人更改表并添加更多列或删除列时,您可以放置触发器或警报,以通知您附加触发器。
就性能而言,我相信 * 不会改变任何东西,它只会增加事情发生变化时发生故障的可能性,并且当您需要时通过网络提取更多信息时,还会导致网络延迟。* 有一个时间和地点,但我觉得如上所述,你有更好的解决方案和工具可以尝试。