我有这张桌子:
我正在尝试创建一个更新触发器,每当对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_on和last_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
我有一个 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) 在 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) 与 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)在 …
我有一个表格,描述了两个项目之间的某种关系。项由 引用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) 标题是不言自明的,但如果您对我为什么想要这个感到好奇;我想要这个是因为我有一个存档/日志表来存储活动表的过去值,因此我不希望数据有以任何方式受到损害的风险。唯一应该在表上插入的是我在活动表上创建的触发器以记录其更改。在极少数情况下,我们可能需要手动编辑日志表,我将关闭(如果存在)“插入锁”
我将 SQL Server 2012 Enterprise 与 SQL Management Studio 结合使用
我得到了要在 ( 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) 这是我数据库中的表之一。为清楚起见,省略了约束。
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 触发器来检查日期并在日期无效时回滚。
我和一位同事谈过,他说从技术上讲,我正在检查数据库中的业务规则,因此应该将这项检查推送到应用程序。
是否有“正确”的方法来解决这个问题,或者基本上是开发人员认为最好的方法?
似乎触发器在更改后会自动启用。如何以编程方式更改触发器而不更改其启用/禁用状态?
重现代码:
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) 好吧,幸运的是我在我的测试环境中遇到了这个错误。我非常害怕这个错误,以至于我禁用了我在生产环境中使用的所有登录触发器。
我创建了著名的登录触发器,并将数据库置于离线模式,只是为了处理其他事情。然后我发现因为触发器找不到表,所以我不能再访问实例了。有很多与此相关的问题,但即使做了我能找到的一切,我仍然无法访问该实例,即使使用 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 ×10
sql-server ×6
postgresql ×3
cursors ×1
dac ×1
dynamic-sql ×1
innodb ×1
mysql ×1
null ×1
performance ×1
permissions ×1
plpgsql ×1
t-sql ×1
view ×1