SQL 触发器中如何正确使用事务锁
在 MySQL 和 SQL Server 里,DML 触发器并不会开启独立事务,而是直接运行在父事务上下文中。要减少死锁和锁等待,关键不在触发器里“补事务”,而在主事务开头预加锁、让触发器内 DML 只走唯一索引,并把非核心跨表操作尽量移出事务边界。
在 MySQL 和 SQL Server 里,DML 触发器并不会开启独立事务,而是直接运行在父事务上下文中。要减少死锁和锁等待,关键不在触发器里“补事务”,而在主事务开头预加锁、让触发器内 DML 只走唯一索引,并把非核心跨表操作尽量移出事务边界。

MySQL 的 `UPDATE ... JOIN` 一旦遇到非唯一匹配,往往不会报错,而是让同一行被多次命中,最终只保留最后一次结果。这类问题常由临时表重复、过滤条件缺失或误用 `LEFT JOIN` 引起。本文从成因、排查、改写方式和上线前校验四个方面,梳理一套更稳妥的处理方法。

查询 SQL JSON 数组时,最常见的问题不是函数失效,而是字段类型、路径表达式和元素类型没对上。本文用 MySQL 与 PostgreSQL 两套写法,梳理 JSON_CONTAINS、JSON_EXTRACT、JSON_TABLE 与 jsonb 操作符的适用场景、坑点和性能差异。 很多人第一次查 SQL 里的 JSON 数组,都会遇到同一个现象:语句看起来没错,结果却始终查不到。

窗口函数适合给结果集编号,却不能承担游标分页的“从上一条继续取”的职责。本文拆开常见误区、正确 SQL 写法、窗口函数在分页中的辅助用法,以及 PostgreSQL、MySQL、SQLite、SQL Server 的实现差异。 很多 SQL 教程会把“窗口函数编号”和“游标分页”混在一起,结果写出来的语句不是直接报错,就是翻页时重复、漏数。

SQL 里用 CONCAT 拼接多个字段,看起来是基础操作,真正容易出错的却是不同数据库对 NULL 和参数数量的处理差异。本文按 MySQL、PostgreSQL、SQL Server、Oracle 分别梳理写法、版本要求和避坑点,帮助你快速判断该用 CONCAT、`||`、`+` 还是 LISTAGG。 在 SQL 里拼接多个字段,最容易被忽略的不是语法本身,而是数据库之间对 NULL 、参数数量和版本支持的不同处理。

SQL 存储过程里的死循环,往往不是语法不会写,而是退出机制、计数保护和调试手段没统一。本文结合 MySQL 与 PostgreSQL 的典型场景,梳理合法退出方式、硬性上限写法,以及排查挂起过程时更有效的检查路径。

SQL 触发器最容易踩坑的场景之一,就是在触发器内部再次改动自己监听的表。不同数据库对这类递归的处理方式完全不同:有的直接报错,有的默认允许但要求手动拦截。本文按 MySQL、SQL Server、PostgreSQL 与 SQLite 分别梳理限制、报错和可行替代方案。

SQL 查重常见分成两类:先找出哪些值重复,再定位到具体重复行。本文按查询目标和数据库版本拆开说明,分别给出 GROUP BY + HAVING、ROW_NUMBER() 以及 MySQL 5.7 自连接方案,并补上删除前最容易忽略的保留策略与复核要点。

SQL 的 SELECT 查不出结果,很多时候不是数据没了,而是查询条件把目标行悄悄排除了。本文围绕 MySQL 中最常见的 4 类原因展开:NULL 比较、LEFT JOIN 过滤、隐形字符以及字段名与别名误用,并给出可直接套用的排查写法。

用 LEFT JOIN 做“零数量统计”时,最常见的坑有三个:把 COUNT(*) 当作关联记录数、GROUP BY 写错分组键、以及把左表过滤条件误塞进 ON 子句。本文用订单与商品示例拆开说明这些问题,并给出在 MySQL、PostgreSQL 等数据库里更稳妥的写法与性能判断依据。

在 SQL 里,`WHERE` 和 `HAVING` 都能“筛选”,但作用阶段完全不同:一个面向原始行,一个面向聚合后的分组结果。本文结合 MySQL 5.7+ 的 `ONLY_FULL_GROUP_BY` 规则、常见报错和 `NULL` 场景,梳理 `GROUP BY` 后筛选结果时最容易写错的边界。 写分组统计时,最容易混淆的不是聚合函数本身,而是条件到底该放在 WHERE 还是 HAVING 。

统计“每周新增用户”时,真正容易出错的不是 SQL 语法,而是周定义、首活口径和跨年分组。本文按 MySQL、PostgreSQL、SQL Server 分别说明 ISO 周写法,并给出新增用户统计、跨年周处理与索引优化的实操要点。 很多人写“每周新增用户”统计时,都会直接对时间字段套上 WEEK() ,但这一步很可能已经把结果做偏了。
