我想制作一个触发器来记录任何更新的时间:
CREATE TRIGGER col_update
AFTER UPDATE ON col
FOR EACH ROW BEGIN
UPDATE col SET updated=NOW() WHERE id=NEW.id; // or OLD.id
END
Run Code Online (Sandbox Code Playgroud)
问题是当这个触发器尝试更新updated列时,它也是另一个更新事件,它运行触发器。这将创建一个无限循环,这是行不通的。
如何将更新时间存储在相应的列中?
我希望使用触发器,因为表中有很多列。如果我尝试手动设置更新时间,则需要修改许多查询。
我有一个包含产品描述的表格,每个产品描述都有一个product_id和language_id。我想要做的是用 a language_idof更新所有字段,2使其product_id与language_idis相同1。
到目前为止,我已经尝试了以下查询,但是我收到的错误表明 MySQL 不想更新在子查询中也使用了该表的表。
UPDATE
products_description AS pd
SET
pd.products_seo = (
SELECT
pd2.products_seo
FROM
products_description AS pd2
WHERE
pd2.language_id = 1
AND pd2.products_id = pd.products_id
)
WHERE
pd.language_id <> 1
Run Code Online (Sandbox Code Playgroud)
在 MySQL 中是否有“简单”的方法来解决这个限制?还是有什么“技巧”?我有点惊讶我的查询不起作用,因为这似乎是合乎逻辑的。
所以今天一位教授告诉我们,当数据库必须进行更新时,在内部(在低级别)它会进行删除,然后使用更新的字段进行插入。然后他说这是跨所有数据库制作的,然后我开始讨论,说我认为这没有意义,但我没有足够的资源来支持我的立场。他似乎知道很多,但我不明白为什么 dbs 会这样做。
我的意思是,我知道如果您更新一个字段并且该行需要更多空间,那么它可能会物理删除该行并将其放在新数据的末尾。但是,如果例如您减少了使用的空间,为什么它会在最后删除并重新插入呢?
这是真的吗?有什么好处?
给定下表、唯一聚集索引和统计信息:
CREATE TABLE dbo.Banana
(
pk integer NOT NULL,
c1 char(1) NOT NULL,
c2 char(1) NOT NULL
);
CREATE UNIQUE CLUSTERED INDEX pk ON dbo.Banana (pk);
CREATE STATISTICS c1 ON dbo.Banana (c1);
CREATE STATISTICS c2 ON dbo.Banana (c2);
INSERT dbo.Banana
(pk, c1, c2)
VALUES
(1, 'A', 'W'),
(2, 'B', 'X'),
(3, 'C', 'Y'),
(4, 'D', 'Z');
-- Populate statistics
UPDATE STATISTICS dbo.Banana;
Run Code Online (Sandbox Code Playgroud)
在任何更新之前,统计行修改计数器显然显示为零:
-- Show statistics modification counters
SELECT
stats_name = S.[name],
DDSP.stats_id,
DDSP.[rows],
DDSP.modification_counter
FROM sys.stats AS S
CROSS …Run Code Online (Sandbox Code Playgroud) sql-server statistics execution-plan update unique-constraint
在过去的几天里,我们已经 3 次遇到这个奇怪的错误,在 8 周没有错误之后,我被难住了。
这是错误消息:
Run Code Online (Sandbox Code Playgroud)Executing the query "EXEC dbo.MergeTransactions" failed with the following error: "Cannot insert duplicate key row in object 'sales.Transactions' with unique index 'NCI_Transactions_ClientID_TransactionDate'. The duplicate key value is (1001, 2018-12-14 19:16:29.00, 304050920).".
我们拥有的索引不是唯一的。如果您注意到,错误消息中的重复键值甚至与索引不一致。奇怪的是,如果我重新运行 proc,它会成功。
这是我能找到的最新链接,但我没有看到解决方案。
关于我的场景的一些事情:
每个表有45个字段,我主要列出了索引中用到的字段。我正在更新更新语句中的 TransactionID(集群键)(不必要)。奇怪的是,直到上周我们几个月都没有遇到任何问题。它只是通过 SSIS 偶尔发生。
桌子
USE [DB]
GO
/****** Object: Table [sales].[Transactions] Script Date: 5/29/2019 1:37:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * …Run Code Online (Sandbox Code Playgroud) 我正在编写一个应用程序,它需要在很长一段时间内刷新对数据库的大量更新,但我一直在研究如何优化查询。目前我正在使用INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE,它可以将所有值批处理到一个查询中,但在大表上执行速度非常慢。我实际上不需要插入行。
我见过的其他方法是更新使用SET value = CASE WHEN...(由于我构建查询的方式,这将很难生成,而且我不确定CASE数百/数千个键的性能),并且只是多个连接更新。这些中的任何一个会比我目前的方法更快吗?
令我困惑的是,据我所知,在 MySQL 中没有惯用的、有效的方法来做到这一点。如果真的没有比 更快的方法,ON DUPLICATE KEY那么切换到 PostgreSQL 并使用其UPDATE FROM语法是否值得?
任何其他建议也非常感谢!
编辑:这是经常更新的表之一。我删除了列名,因为它们不相关。
CREATE TABLE IF NOT EXISTS `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`a` bigint(20) unsigned NOT NULL DEFAULT '0',
`b` bigint(20) unsigned NOT NULL DEFAULT '0',
`c` enum('0','1','2') NOT NULL DEFAULT '0',
`d` char(32) NOT NULL,
-- trimmed --
PRIMARY KEY (`id`),
KEY …Run Code Online (Sandbox Code Playgroud) 我正在处理复杂的问题,但我会将其简化为这个问题。
我有两张桌子
A [ID, column1, column2, column3]
B [ID, column1, column2, column3, column4]
Run Code Online (Sandbox Code Playgroud)
我想更新第三个:
C [ID, column1, column2,column3]
Run Code Online (Sandbox Code Playgroud)
我正在使用此查询更新另一个第三个表。
UPDATE C
set column1=t.firstTab, column2=t.secondTab, column3=t.thirdTab
from (select A.column1 as firstTab, B.column2 as secTab,
(A.column1 + B.column2) thirdTab
from A, B limit 1; ) as t ;
Run Code Online (Sandbox Code Playgroud)
我有:
UPDATE 0
Run Code Online (Sandbox Code Playgroud)
当我运行此查询时:
select A.column1 as firstTab, B.column2 as secTab, (A.column1 + B.column2) thirdTab
from A, B limit 1;
Run Code Online (Sandbox Code Playgroud)
我得到了结果。我错过了什么吗?
示例数据:http : //sqlfiddle.com/#!15/e4d08/5
我需要从另一个表更新一个表,我需要更新所有列。除了列出SET子句中的每一列之外,有没有办法一次更新它们?像这样:
update tableA
set * = tableB.*
from tableB where tableA.id = tableB.id
Run Code Online (Sandbox Code Playgroud)
我在 psql 中尝试过,它不起作用。我必须像这样列出每一列:
update tableA
set c1 = tableB.c1, c2 = tableB.c2, ...
from tableB where tableA.id = tableB.id
Run Code Online (Sandbox Code Playgroud)
tableB创建使用create .. like tableA. 所以它们基本上是相同的。我这样做的原因是我需要将 .csv 数据加载到临时表tableB,然后tableA根据.csv 中的新数据进行更新tableB。tableA需要尽量少加锁,tableA需要保持完整性。我不确定“删除然后插入”是否是一个不错的选择?
是否可以通过在引用它的所有外键之间级联更新来更新主键列值?
# EDIT 1: 当我运行 followinq 查询
select * from sys.foreign_keys where referenced_object_id=OBJECT_ID('myTable')
Run Code Online (Sandbox Code Playgroud)
,我看到 update_referential_action 设置为 0。因此更新我的主键列后没有采取任何操作。如何更新外键以使其ON CASCADE UPDATE?
# EDIT 2:
为了编写或删除架构中所有外键的脚本,请运行以下脚本(取自此处)
DECLARE @schema_name sysname;
DECLARE @table_name sysname;
DECLARE @constraint_name sysname;
DECLARE @constraint_object_id int;
DECLARE @referenced_object_name sysname;
DECLARE @is_disabled bit;
DECLARE @is_not_for_replication bit;
DECLARE @is_not_trusted bit;
DECLARE @delete_referential_action tinyint;
DECLARE @update_referential_action tinyint;
DECLARE @tsql nvarchar(4000);
DECLARE @tsql2 nvarchar(4000);
DECLARE @fkCol sysname;
DECLARE @pkCol sysname;
DECLARE @col1 bit;
DECLARE @action char(6);
DECLARE @referenced_schema_name sysname;
DECLARE FKcursor …Run Code Online (Sandbox Code Playgroud) sql-server-2008 foreign-key sql-server referential-integrity update
将 BIGSERIAL 列添加到大表(约 3 Bil. 行,约 174Gb)的最快方法是什么?
编辑:
NOT NULL) 的递增值。update ×10
mysql ×3
postgresql ×3
sql-server ×3
foreign-key ×1
join ×1
performance ×1
sequence ×1
statistics ×1
trigger ×1