AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题

问题[trigger](dba)

Martin Hope
Doug Hills
Asked: 2024-10-17 06:55:03 +0800 CST

让表忽略琐碎更新

  • 6

场景:我拥有一个 ETL 流程。该流程涉及从不同来源提取数据并使我的数据库与最新数据同步。

假设我有一个名为 [catalog] 的表。它包含我公司的产品目录。此表的可信来源每四个小时向我发送一个 CSV。我提取该 CSV 并确保我的 [catalog] 表与其同步。我使用如下更新:

UPDATE mc 
SET
      [field1] = tc.[field1]
    , [field2] = tc.[field2]
FROM [my].[catalog] as mc  
INNER JOIN [their].[catalog] as tc
    ON mc.id = tc.id
WHERE mc.[field1] <> tc.[field1]
OR mc.[field2] <> tc.[field2]

此命令将比较每个匹配项,并仅筛选出那些将看到有意义更改的行,然后仅更新这些行。我不想不必要地触碰任何行——这是 ETL 开发人员的长期任务。

不会执行任何琐碎更新(所谓琐碎更新,我指的是对某一行的更新,但该行中的任何字段均未发生改变)。未发生改变的行将保持原样,不受干扰。

这里用“不受干扰”这个词很贴切,因为更新一行而不影响值会产生不必要的成本。在内存和磁盘中,对行的更新会从物理上删除包含旧值的行,并插入包含新值的新行。所有这些更新都必须记录!因此,在什么都不做的过程中,我们已经在内存和磁盘上对表的索引和数据页进行了碎片化和分割。而且我们正在通过日志进行不必要的流量。

如果我们不做任何更改,那么简单的更新仍会导致内存和磁盘的混乱。为表提供一种自动忽略简单更新的方法,对于许多场景来说都是一大优势。

现在,假设某个笨手笨脚的开发人员通过某个客户端或程序更改进行了更新,该更新对大型表执行了类似操作,但没有包括任何措施来忽略“真正”不需要更新的行。我可以对表执行什么操作,让它表现得好像知道传递琐碎的更新一样?

trigger
  • 3 个回答
  • 72 Views
Martin Hope
C C
Asked: 2024-06-19 01:37:00 +0800 CST

DB2 TRIGGER“FOR EACH STATEMENT”,带有“AFTER UPDATE OR INSERT”给出SQL代码-104,SQL状态42601

  • 5

IBM DB2 on Cloud,版本 11.5.9.0

尝试在表上创建触发器(为了简化,对象名称是虚构的):

CREATE OR REPLACE TRIGGER MY_TRIGGER
AFTER UPDATE OR INSERT ON MY_TABLE
REFERENCING NEW TABLE AS NEW_STUFF
FOR EACH STATEMENT
BEGIN ATOMIC
    DELETE FROM TABLE_A WHERE P_N IN (SELECT DISTINCT P_N FROM NEW_STUFF);
    INSERT INTO TABLE_A SELECT * FROM VIEW_B WHERE P_N IN (SELECT DISTINCT P_N FROM NEW_STUFF);
END;

视图 VIEW_B 在其定义中确实有 TABLE_A 作为引用。

我收到此错误:

SQL Error [42601]: An unexpected token "OR INSERT" was found following "".  
Expected tokens may include:  "".. 
SQLCODE=-104, SQLSTATE=42601

如果我创建仅使用AFTER UPDATE ON MY_TABLE或仅使用AFTER INSERT ON MY_TABLE 的相同触发器,它会正常工作。当我同时指定AFTER UPDATE 或 INSERT时,它会失败。

如果我尝试BEGIN而不是BEGIN ATOMIC我会得到不同的错误:

SQL Error [42898]: The definition of trigger "MY_SCHEMA.MY_TRIGGER" includes an 
invalid use of correlation name or transition table name "NEW_STUFF".
Reason code="4".. SQLCODE=-696, SQLSTATE=42898

我研究了文档和我能找到的几个例子。如果有人知道为什么 UPDATE 或 INSERT 的组合会导致它失败,我将不胜感激。

trigger
  • 1 个回答
  • 22 Views
Martin Hope
Sranda
Asked: 2024-01-02 22:34:44 +0800 CST

DMV sys.dm_exec_trigger_stats - 重复条目

  • 5

我正在运行以下选择:

SELECT tstats.object_id, tstats.database_id, tstats.sql_handle, 
DB_NAME(tstats.database_id) AS [db_name], OBJECT_NAME(tstats.object_id) AS      
trigger_name, tstats.execution_count, tstats.total_worker_time,     
tstats.total_logical_reads, tstats.total_logical_writes, OBJECT_NAME(trgs.parent_id) AS  
trigger_parent, getdate() AS [timestamp] FROM sys.dm_exec_trigger_stats tstats INNER 
JOIN  sys.triggers trgs ON tstats.object_id = trgs.object_id ORDER BY object_id asc

SQL Server 版本是 2019 (RTM-CU24) 标准。

问题是,某些触发器返回两次(相同的对象 ID、不同的执行计数和其他统计信息):

触发统计 DMV 的重复输出

我正在尝试对这个sys.dm_exec_trigger_statsDMV 进行采样并每分钟生成增量,以查看哪些触发器正在影响应用程序性能 - 我认为数据库名称、触发器的父名称和触发器名称(或 object_id)的组合是唯一的。它们多次返回,具有不同的运行时统计信息,我无法理解。提示表示赞赏。

trigger
  • 1 个回答
  • 40 Views
Martin Hope
U. Windl
Asked: 2023-08-16 21:30:43 +0800 CST

插入触发器以自动设置复合主键的关键字段

  • 6

基本上,复合主键错误“UNIQUE约束失败”的下一步是:我在插入后创建了一个触发器,如果​​它小于一,则将其设置SEQ为最高加一。SEQ基本上:

CREATE TRIGGER TRG_NAMES_ADD2 AFTER INSERT ON NAMES FOR EACH ROW
WHEN NEW.SEQ < 1
BEGIN
    UPDATE NAMES SET
        SEQ = (SELECT IFNULL(MAX(SEQ), 0) + 1 FROM NAMES WHERE TYPE = NEW.TYPE)
    WHERE TYPE = NEW.TYPE AND SEQ = NEW.SEQ;
END;

不过,我想TYPE独立于做同样的事情SEQ。我发现的问题是每个触发器只能有一个UPDATE,并且AFTER INSERT触发器可以按任何顺序执行。

我尝试了第二个触发器,如下所示:

CREATE TRIGGER TRG_NAMES_ADD1 AFTER INSERT ON NAMES FOR EACH ROW
WHEN NEW.TYPE < 1
BEGIN
    UPDATE NAMES SET
        TYPE = (SELECT IFNULL(MAX(TYPE), 0) + 1 FROM NAMES),
        SEQ = 1
    WHERE TYPE = NEW.TYPE AND SEQ = NEW.SEQ;
END;

但是为了完整性,TRG_NAMES_ADD2应该在 后运行TRG_NAMES_ADD1,否则我必须将两个操作(设置TYPE为可能的新值(如果< 1),然后使用该新值也可能为SEQ(如果< 1)设置新值)放入一个触发器。

不幸的是,这超出了我的能力范围。

为了方便起见,这里是表创建和一些示例插入:

CREATE TABLE NAMES (
TYPE INTEGER NOT NULL, SEQ INTEGER NOT NULL, NAME VARCHAR(20),
PRIMARY KEY (TYPE, SEQ)
);

insert into NAMES (type, seq, name) values (2, 3, "T1");
insert into NAMES (type, seq, name) values (2, 0, "T2");
insert into NAMES (type, seq, name) values (2, 0, "T3");
insert into NAMES (type, seq, name) values (0, 1, "T4");
insert into NAMES (type, seq, name) values (0, 0, "T5");

所以任务应该是这样的:

T|S|N
-----
2|3|T1  # T,S set manually
2|4|T2  # S set automatically
2|5|T3  # S set automatically
3|1|T4  # T set automatically
4|1|T5  # T,S set automatically
trigger
  • 1 个回答
  • 18 Views
Martin Hope
U. Windl
Asked: 2023-08-16 16:06:19 +0800 CST

复合主键出现“UNIQUE 约束失败”错误

  • 5

通过小 SQL(ite) 实践,我尝试创建一个具有复合主键的表:

CREATE TABLE NAMES (
  TYPE INTEGER NOT NULL,
  SEQ INTEGER NOT NULL,
  NAME VARCHAR(20),
  PRIMARY KEY (TYPE, SEQ)
);

这个想法是存储从数字到名称的关联,即:SEQ往返NAME。由于此类“类”的数量可变,因此我添加了一TYPE列,即SEQ数字(和NAMEs)在特定的TYPE.

我还尝试创建一个触发器,该触发器将自动分配SEQ特定中的“下一个空闲”号码,TYPE如下所示:

CREATE TRIGGER TRG_NAMES_ADD AFTER INSERT ON NAMES
FOR EACH ROW BEGIN
    UPDATE NAMES SET SEQ = (SELECT COUNT(1) FROM NAMES WHERE TYPE = NEW.TYPE)
    WHERE TYPE = NEW.TYPE;
END;

当我插入第一个条目时,它似乎有效,但是当我尝试添加第二个条目时,它失败了

运行时错误:UNIQUE 约束失败:NAMES.TYPE、NAMES.SEQ (19)

像这样:

sqlite> select * from NAMES;
sqlite> insert into NAMES (type, seq, name) values (0, -1, "test");             sqlite> select * from NAMES;
0|1|test
sqlite> insert into NAMES (type, seq, name) values (0, -1, "test2");
Runtime error: UNIQUE constraint failed: NAMES.TYPE, NAMES.SEQ (19)
sqlite> insert into NAMES (type, seq, name) values (1, -1, "test2");
sqlite> select * from NAMES;
0|1|test
1|1|test2

所以触发器似乎对每个TYPE都只工作一次,但也许不起作用,因为第一个SEQ应该是 0 而不是 1。

我也尝试过使用BEFORE而不是AFTER触发器,但这不会改变SEQ一切(使用-1)。

触发器有什么问题,还是表定义有问题?

trigger
  • 1 个回答
  • 45 Views
Martin Hope
Lando_
Asked: 2023-04-20 13:58:19 +0800 CST

审计触发器仅在特定列更改时跟踪,并且仅记录已更改列的旧值和新值

  • 5

我有一个包含 75 列的表,并且需要跟踪其中大约 15 列,以便在这 15 列中的任何列中的任何数据发生变化(仅更新,无插入或删除)时注销旧值和新值。例外情况是我们只想跟踪这 15 个列中更新的列。如果旧值和新值均为 NULL 或两者相同,我们只想将 NULL 记录到这些列的审计表中。

多列可以为空,并且是整数、小数和 nvarchar 数据类型的组合。

这一切都在 Azure SQL 数据库上运行。

我写了一个初始的更新后触发器,它有一个插入语句到一个有 30 列的审计表中,一个“旧”和“新”列用于我们希望跟踪的所有 15 个列。当旧值和新值都不为 NULL 时,这一切都很好,但如果旧值或新值之一恰好为 NULL,我们就会丢失数据。

为了解决这个问题,我开始为每一列编写 case 语句,以及一堆 where 子句,但我觉得这不是正确的方法。基本上,有 15 种不同的语句变体,例如:

CREATE OR ALTER TRIGGER [dbo].[trg_Stuff_Audit]
ON [dbo].[Stuff]
AFTER UPDATE
AS
BEGIN

insert into dbo.audit (id, OldDecimalValue, NewDecimalValue)

select i.id,

case when d.DecimalValue is null and i.DecimalValue is not null then d.DecimalValue
when d.DecimalValue is not null and i.DecimalValue is null then d.DecimalValue
when d.DecimalValue <> i.DecimalValue then d.DecimalValue
else NULL end as OldDecimalValue,

case when d.DecimalValue is null and i.DecimalValue is not null then i.DecimalValue
when d.DecimalValue is not null and i.DecimalValue is null then i.DecimalValue
when d.DecimalValue <> i.DecimalValue then i.DecimalValue
else NULL end as NewDecimalValue

from inserted i inner join deleted d on i.id = d.id

where d.DecimalValue is null and i.DecimalValue is not null
OR d.DecimalValue is not null and i.DecimalValue is null
OR d.DecimalValue <> i.DecimalValue

END;

我觉得必须有更好的方法来解决这个问题,我是走在正确的道路上还是需要改变方向?

trigger
  • 3 个回答
  • 39 Views
Martin Hope
Dimitrios Desyllas
Asked: 2022-12-20 13:30:35 +0800 CST

如何在 sqlite3 中为创建和更新创建一个触发器?

  • 5

我制作了下表:

CREATE table IF NOT EXISTS redirect (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            url_from TEXT not null,
            url_to TEXT not null,
            method TEXT not null,
            http_status_code INTEGER not null CHECK( http_status_code IN (300,301,302,304,304,308,307) ) DEFAULT 301,
            use_in_https INTEGER not null CHECK(use_in_https IN (0,1)) DEFAULT 0,
            use_in_http INTEGER not null CHECK(use_in_http IN (0,1)) DEFAULT 1,
            exact_match INTEGER not null CHECK(exact_match IN (0,1)) DEFAULT 1
        );

我做了以下触发器:


        CREATE TRIGGER remove_http_https BEFORE INSERT ON redirect BEGIN 
           SELECT CASE WHEN NEW.url_from THEN REPLACE(REPLACE(NEW.url_from,"http:\/\/",""),"https:\/\/","")   END;
        END;

但是我希望触发器在我更新值或插入值时同时运行。有没有办法将插入和更新定义为 sqlite3 的单个触发器?

trigger
  • 1 个回答
  • 17 Views
Martin Hope
c.jungc
Asked: 2022-10-07 17:26:42 +0800 CST

一次触发多行

  • 0

所以我有这三张桌子。订单表是现有订单的列表,而订单详细信息由订单中的项目组成(因为 1 个订单可以有多个目录)。我正在使用 mysql

客户订单

订单编号 姓名 电子邮件 发货状态
1 布莱恩 [email protected] 已发货

订单项

奇数 订单编号 目录_id 数量
1. 1 1 5
2. 1 2 5

存货

目录_id 数量库存
1 10
2 10

我想创建一个触发器,如果​​订单表中的 shipping_status 为“已发货”,那么它将更新库存中的库存。

我已经创建了这个触发器

create trigger update_inventory
after update on cust_order
for each row 
begin
if new.shipping_status="Shipped" then
update inventory 
set inStock = inStock - (select quantity from order_item where order_id=new.order_id)
where catalog_id in (select catalog_id from order_item where order_id=new.order_id);
end if;
end;
//

但它不起作用并转为 #1242 - 子查询返回超过 1 行

如何创建一次更新多行的触发器?

mysql trigger
  • 2 个回答
  • 39 Views
Martin Hope
Alex Jenkins
Asked: 2022-08-24 06:32:52 +0800 CST

简化重复的 INSERT 命令,为未找到的值放置 NULL

  • 0

我有许多用 PL/pgSQL 编写的触发函数,它们遵循以下逻辑:

SELECT my_name
INTO l_my_name
FROM data
WHERE data.my_number = NEW.test_num;

IF NOT FOUND THEN
   INSERT INTO test_event
   VALUES (NEW.test_num, NULL, NEW.event_one, NEW.event_two);
ELSE                                                                                            
   INSERT INTO test_event
   VALUES (NEW.test_num, l_my_name, NEW.event_one, NEW.event_two);
END IF;

一些插入具有超过 15 个以上的值,我试图将它们简化为仅 1 个插入,因为上面的代码一遍又一遍地重复存储过程中的不同检查,不必要地使过程有数百行代码长。我的想法是这样的:

INSERT INTO test_event
VALUES (NEW.test_num, NULLIF(l_my_name,''), NEW.event_one, NEW.event_two);

我不确定如果没有找到它是否l_my_name会正常工作,或者我是否必须做一些不同的事情。''NULLIF

postgresql trigger
  • 1 个回答
  • 29 Views
Martin Hope
PRAMOD MANN
Asked: 2022-07-30 09:21:36 +0800 CST

如果特定数据在另一个表中可用,MySQL 触发器以防止在一个表中更新

  • 0

如果某些特定数据在另一个表中可用,我需要一个可以防止更新特定列数据的 MySQL 触发器。

我有两张表产品和销售。

产品

在此处输入图像描述

销售

在此处输入图像描述

如果 product_id 在销售表中可用,我需要防止更新产品表中的 updated_at 列。

mysql trigger
  • 1 个回答
  • 49 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve