标签: trigger

如何在 AFTER UPDATE 触发器中仅引用受影响的行

我有这张桌子:

在此处输入图片说明

我正在尝试创建一个更新触发器,每当对or列执行更新时,该触发器就会更新last_updated_on = GETDATE()last_updated_by = SYSTEM_USER列。step_numberstep_name

我开始创建它

ALTER TRIGGER tr_app_bread_crumbs_afterupdate
ON [dbo].[app_bread_crumbs]
AFTER UPDATE
AS
BEGIN 
    UPDATE [dbo].[app_bread_crumbs]
    SET last_updated_by = SYSTEM_USER,
    last_updated_on = GETDATE()
END
Run Code Online (Sandbox Code Playgroud)

但这将一次更新所有行。我正在尝试弄清楚如何指定仅更新last_updated_onlast_updated_by由正在更新的特定行的触发器。

例如,如果他们更新:

UPDATE [dbo].[app_bread_crumbs]
    SET step_name = 'DAMAGE' WHERE step_number = 1
Run Code Online (Sandbox Code Playgroud)

触发器应该只更新第一行

trigger sql-server t-sql sql-server-2012 row-modification-time

6
推荐指数
2
解决办法
4万
查看次数

SQL Server 在通过游标更新具有 INSTEAD OF UPDATE 触发器的视图时使用索引扫描而不是搜索

我有一个 3rd 方应用程序,它使用一个游标来更新我的 SQL Server 2014 表中的行。我无法修改此代码,因此设计了一种方案,将光标指向具有INSTEAD OF UPDATE触发器的视图,我可以在其中拦截并完全控制更新。我很清楚游标是邪恶的,但我不得不使用它们,因为我无法修改源程序。

UPDATE ... WHERE CURRENT OF语句执行,它执行聚集索引扫描,而不是寻求以定位光标当前所指向的记录。我无法确定优化器在可能进行搜索时为什么要进行扫描。我相信它是导致问题的光标 + 视图 + 而不是更新触发器的组合,因为如果我从我的测试中删除这 3 个变量中的任何一个,索引查找就会被正确使用。

请注意,表中有多少行并不重要;优化器总是根据执行计划使用扫描。我什至删除了触发器中的所有逻辑以进一步简化测试。

下面是一些简单的代码来重现这个问题:

CREATE TABLE [dbo].[Person](
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [Name] [varchar](40) NULL,
  CONSTRAINT [PK_Person_Id] PRIMARY KEY CLUSTERED ( [Id] ASC )
  WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
        ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])
  ON [PRIMARY]
GO

CREATE VIEW [dbo].[vPerson]
AS SELECT Id, Name FROM dbo.Person …
Run Code Online (Sandbox Code Playgroud)

trigger performance sql-server cursors sql-server-2014

6
推荐指数
1
解决办法
1063
查看次数

postgresql:从视图中删除

在 Postgresql 9.4 中,我们将视图作为表 A 和 B 的联合进行处理,并且当我们“删除”底层表中的记录时(通过 aa 触发器上的看法)。

这里有更详细的信息。我们的观点看起来像,

A
--
id, name
1, afoo
2, abar

B
--
id, name
3, bfoo
4, bbar
Run Code Online (Sandbox Code Playgroud)

所以我们的视图 C 看起来像

C
--
1, afoo
2, abar
3, bfoo
4, bbar
Run Code Online (Sandbox Code Playgroud)

我们做了一个CREATE TRIGGER delete_trigger INSTEAD OF DELETE C FOR EACH ROW DO delete_trigger(),它通过 id 删除行,这基本上就像

-- our function trigger():
$$
delete from A where id=old.id;
GET DIAGNOSTICS deletedA = ROW_COUNT;

delete from B where id=old.id;
GET DIAGNOSTICS deletedB = …
Run Code Online (Sandbox Code Playgroud)

postgresql trigger view postgresql-9.4

5
推荐指数
1
解决办法
2351
查看次数

InnoDB 复合键上的 AUTO_INCREMENT 技巧

与 MySQL MyISAM-Engine 相比,InnoDB-Engine 无法处理复合主键的一列声明为AUTO_INCREMENT. 例如,考虑下表:

CREATE TABLE `ExampleTable` (
     `KeyPartA` mediumint(8) unsigned NOT NULL,
     `KeyPartB` smallint(5) unsigned NOT NULL,
     `Data` text NOT NULL,
     PRIMARY KEY (`KeyPartA`,`KeyPartB`)
) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

现在模拟AUTO_INCREMENT,我了解到,可以创建以下触发器

DELIMITER $$

CREATE TRIGGER ExampleAutoIncrement BEFORE INSERT ON ExampleTable
FOR EACH ROW BEGIN
        SET NEW.KeyPartB = (
             SELECT IFNULL(MAX(KeyPartB), 0) + 1
             FROM ExampleTable
             WHERE KeyPartA  = NEW.KeyPartA
        );
END $$

DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

现在插入工作正常,生成自动递增的值。不幸的是,我想不出一种明智的方法来获取新创建的键值。

由于LAST_INSERT_ID()没有实际的AUTO_INCREMENT列,因此它的 C 对应项都不会返回它。也不能LAST_INSERT_ID(IFNULL(MAX(KeyPartB), 0) + 1)在 …

mysql innodb trigger auto-increment

5
推荐指数
1
解决办法
7707
查看次数

触发以创建对称行

我有一个表格,描述了两个项目之间的某种关系。项由 引用ID。我想创建一个触发器,所以每当你创建一行时(a,b),就会创建一个对称的行(b,a)。我试过在触发器之后创建,但它超过了堆栈深度,因为它在插入时调用了它自己。什么是正确的方法呢?

表看起来有点像这样:

CREATE TABLE MY_RELATION(
ID SERIAL,
THING1 INT NOT NULL,
THING2 INT NOT NULL,
PRIMARY KEY (ID)
);

CREATE TABLE MY_THING(
ID SERIAL,
VAL INT NOT NULL
PRIMARY KEY(ID)
);
ALTER TABLE MY_RELATION ADD FOREIGN KEY (THING1) REFERENCES MY_THING(ID);
ALTER TABLE MY_RELATION ADD FOREIGN KEY (THING2) REFERENCES MY_THING(ID);
Run Code Online (Sandbox Code Playgroud)

postgresql trigger database-design

5
推荐指数
1
解决办法
408
查看次数

SQL Server 中有没有办法使表只能通过触发器插入?

标题是不言自明的,但如果您对我为什么想要这个感到好奇;我想要这个是因为我有一个存档/日志表来存储活动表的过去值,因此我不希望数据有以任何方式受到损害的风险。唯一应该在表上插入的是我在活动表上创建的触发器以记录其更改。在极少数情况下,我们可能需要手动编辑日志表,我将关闭(如果存在)“插入锁”

我将 SQL Server 2012 Enterprise 与 SQL Management Studio 结合使用

trigger sql-server permissions sql-server-2012

5
推荐指数
2
解决办法
2287
查看次数

分配具有动态列名的列

我得到了要在 ( BEFORE UPDATE) 触发器中设置的列的名称,我想将其设置为该OLD值并忽略传入的任何内容。我尝试了以下操作:

CREATE OR REPLACE FUNCTION prevent_column_update() RETURNS TRIGGER AS $$
  DECLARE
    col TEXT := TG_ARGV[0];
  BEGIN
    EXECUTE format('SELECT ($1).%I INTO ($2).%I', col, col) USING OLD, NEW;
    RETURN NEW;
  END;
  $$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

并使用如下:

CREATE TRIGGER request_protect_date_price_value
  BEFORE UPDATE OF date_price ON requests
  FOR EACH ROW EXECUTE PROCEDURE prevent_column_update('date_price');
Run Code Online (Sandbox Code Playgroud)

但是当更新它失败时:

ERROR:  syntax error at or near "("
LINE 1: SELECT ($1).date_price INTO ($2).date_price
                                    ^
QUERY:  SELECT ($1).date_price INTO ($2).date_price
Run Code Online (Sandbox Code Playgroud)

postgresql trigger dynamic-sql plpgsql postgresql-9.5

5
推荐指数
1
解决办法
6392
查看次数

检查可空数据的约束,如何处理?

这是我数据库中的表之一。为清楚起见,省略了约束。

CREATE TABLE [Person].[Person]
(
    [ID]                     INT           NOT NULL IDENTITY,       
    [Forename]               VARCHAR(16)   NOT NULL,
    [Surname]                VARCHAR(32)   NOT NULL,
    [Gender]                 CHAR(1)       NOT NULL DEFAULT 'U',
    [DateOfBirth]            DATETIME      NULL,
    [HobbiesAndInterests]    VARCHAR(256)  NULL,
    [AdditionalInformation]  VARCHAR(512)  NULL,
    [LocalCentreID]          INT           NOT NULL DEFAULT 0,
    [EmergencyContactID]     INT           NULL, 
)
Run Code Online (Sandbox Code Playgroud)

我的问题涉及出生日期字段。如果提供了值,我需要对日期进行检查。如果未提供值,则无需运行检查。

我基本上需要根据出生日期检查这个人是否年满 18 岁。如果未提供出生日期,则无需对其进行检查。

我想了几种不同的方法来解决这个问题:

第一个显然是在出生日期字段上设置检查约束,但我认为如果日期为空,这将失败。

另一种选择是在检查约束内使用标量 UDF。

我想到的最后一个选项是使用 AFTER INSERT/UPDATE 触发器来检查日期并在日期无效时回滚。

我和一位同事谈过,他说从技术上讲,我正在检查数据库中的业务规则,因此应该将这项检查推送到应用程序。

是否有“正确”的方法来解决这个问题,或者基本上是开发人员认为最好的方法?

trigger null sql-server check-constraints

5
推荐指数
1
解决办法
4843
查看次数

在 SQL Server 中更改禁用的触发器而不启用它

似乎触发器在更改后会自动启用。如何以编程方式更改触发器而不更改其启用/禁用状态?

重现代码:

create trigger trig
on MyTable
after insert
as select 0

go

disable trigger trig on MyTable

go

select is_disabled from sys.triggers where name = 'trig'

go

alter trigger trig
on MyTable
after insert
as select 1

go

select is_disabled from sys.triggers where name = 'trig'
Run Code Online (Sandbox Code Playgroud)

trigger sql-server

5
推荐指数
1
解决办法
734
查看次数

在 SQL Server Express 上启用管理员连接以修复登录触发器

好吧,幸运的是我在我的测试环境中遇到了这个错误。我非常害怕这个错误,以至于我禁用了我在生产环境中使用的所有登录触发器。

我创建了著名的登录触发器,并将数据库置于离线模式,只是为了处理其他事情。然后我发现因为触发器找不到表,所以我不能再访问实例了。有很多与此相关的问题,但即使做了我能找到的一切,我仍然无法访问该实例,即使使用 SQLCMD 也无法访问。

我这样做:

sqlcmd -S server\instance -U sa -P <pass>  -A
Run Code Online (Sandbox Code Playgroud)

如果我不使用,-A我会收到著名的错误:

logon failed for sa due trigger execution.
Run Code Online (Sandbox Code Playgroud)

如果我使用-A

Sqlcmd:错误:Microsoft ODBC Driver 11 for SQL Server:SQL Server 网络接口:获取专用管理员连接 (DAC) 端口时出错。确保 SQL Browser 正在运行,或检查端口号 [xFFFFFFFF] 的错误日志。. Sqlcmd:错误:用于 SQL Server 的 Microsoft ODBC 驱动程序 11:登录超时已过期。Sqlcmd:错误:Microsoft ODBC Driver 11 for SQL Server:建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。检查实例名称是否正确以及 SQL Server 是否配置为允许远程连接。有关详细信息,请参阅 SQL Server 联机丛书。

为什么我无法连接到sql server

sql server express 在这里。

我可以启用 SQL Browser,但我仍然无法访问它。

我不认为这个问题是重复的,因为不是关于触发器,而是关于为什么我无法使用 SQLCMD 访问服务器。我几乎知道如何解决这个问题。我只是不知道如何在不触发触发器的情况下访问 sql server。

trigger sql-server sql-server-express dac

5
推荐指数
1
解决办法
778
查看次数