图解SQL连接:内连接、左连接、外连接、全连接与自连接详解
1. 项目概述为什么我们需要理解连接如果你写过SQL或者哪怕只是看过别人写的查询语句大概率都见过JOIN这个关键字。它就像数据库查询里的“粘合剂”能把分散在不同表里的数据按照某种规则拼凑在一起形成一个更完整、更有用的视图。但就是这个看似基础的JOIN却让不少新手甚至一些有经验的开发者感到困惑。左连接、右连接、内连接、外连接、全连接……这些名词听起来就让人头大更别提在实际业务中灵活运用了。我见过太多因为连接用错而导致的“灵异事件”查询结果莫名其妙少了几行数据明明应该有关联的数据却显示为NULL甚至因为连接条件不当产生了笛卡尔积直接把数据库查崩了。这些问题的根源往往不是SQL语法不会写而是对几种连接方式的本质区别和适用场景理解不透。所以今天我们不谈枯燥的理论定义就用最直观的“图解”方式结合具体的场景和例子把左连接、右连接、内连接、外连接和全连接掰开揉碎了讲清楚。我的目标很简单让你看完之后不仅能分清谁是谁更能像条件反射一样在遇到具体业务问题时立刻知道该用哪种连接。我们会用两个最简单的表开始一步步画图、写SQL、看结果直到你彻底搞懂为止。2. 准备我们的实验沙盘两个简单的表在深入连接之前我们得先有个“实验场地”。为了把焦点完全放在连接逻辑上我们设计两个极其简单但又足够典型的表员工表 (employees)和部门表 (departments)。这是关系型数据库中最经典的一对多关系模型。员工表 (employees)这个表记录员工的基本信息。我们假设它有3个字段emp_id: 员工ID主键。emp_name: 员工姓名。dept_id: 部门ID这是一个外键指向departments表的dept_id。注意它允许为NULL这意味着有些员工可能暂时不属于任何部门比如新入职还未分配或者某个特殊岗位。让我们插入一些示例数据这些数据将贯穿我们所有的演示-- 创建员工表 CREATE TABLE employees ( emp_id INT PRIMARY KEY, emp_name VARCHAR(50), dept_id INT ); -- 插入数据 INSERT INTO employees (emp_id, emp_name, dept_id) VALUES (1, 张三, 101), (2, 李四, 102), (3, 王五, 103), (4, 赵六, NULL), -- 赵六没有部门 (5, 钱七, 104); -- 注意部门104在部门表中不存在部门表 (departments)这个表记录部门信息。dept_id: 部门ID主键。dept_name: 部门名称。同样我们插入一些数据-- 创建部门表 CREATE TABLE departments ( dept_id INT PRIMARY KEY, dept_name VARCHAR(50) ); -- 插入数据 INSERT INTO departments (dept_id, dept_name) VALUES (101, 技术部), (102, 市场部), (103, 销售部), (105, 人事部); -- 注意没有id为104的部门但有一个id为105的部门没有员工现在让我们直观地看看这两个表里的数据员工表数据预览emp_idemp_namedept_id1张三1012李四1023王五1034赵六NULL5钱七104部门表数据预览dept_iddept_name101技术部102市场部103销售部105人事部请注意数据中故意设置的几个“坑”它们将是测试各种连接类型的绝佳案例员工“赵六”的dept_id是NULL。员工“钱七”的dept_id是104但这个部门ID在部门表中不存在。部门“人事部”的dept_id是105但没有一个员工的dept_id是105。这些不匹配的数据正是各种连接操作产生不同结果的根源。理解连接本质上就是理解数据库如何处理这些匹配和不匹配的行。接下来我们就从最常见的连接开始。3. 内连接只取“有缘人”的交集内连接是所有连接类型中最严格也最常用的一种。你可以把它想象成一次“相亲大会”只有双方都看对眼即连接条件匹配的记录才会被纳入最终的结果集。如果一方没有对应的另一方那么这条记录就会被无情地丢弃。它的语法很简单SELECT ... FROM table_a INNER JOIN table_b ON condition。INNER关键字通常可以省略直接写JOIN默认就是内连接。3.1 图解内连接逻辑让我们用维恩图来理解。假设左圆代表员工表右圆代表部门表。内连接的结果就是两个圆重叠的部分即同时满足连接条件的记录。员工表 (A) 部门表 (B) ○───────○ / \ / A ∩ B \ | (交集) | \ / \ / ○───────○连接条件我们通过employees.dept_id departments.dept_id来关联两个表。匹配过程数据库会取出员工表的第一行张三 dept_id101。拿着这个101去部门表里找发现存在dept_id101的记录技术部。匹配成功将“张三”和“技术部”的信息组合成一行放入结果集。接着处理员工表第二行李四 102在部门表找到“市场部”匹配成功。处理第三行王五 103在部门表找到“销售部”匹配成功。处理第四行赵六 NULL。NULL与任何值包括另一个NULL比较结果都是未知UNKNOWN在连接条件中视为不匹配。所以赵六被丢弃。处理第五行钱七 104。去部门表找104找不到任何记录不匹配。钱七被丢弃。部门表里剩下的“人事部”105在员工表里找不到dept_id105的人不匹配。人事部也被丢弃。3.2 实操SQL与结果分析让我们执行一下SQL验证我们的 SELECT e.emp_id, e.emp_name, e.dept_id AS emp_dept_id, d.dept_id AS dept_dept_id, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id;查询结果emp_idemp_nameemp_dept_iddept_dept_iddept_name1张三101101技术部2李四102102市场部3王五103103销售部结果只有3行这正是我们分析的那样张三、李四、王五成功匹配到了部门。赵六NULL和钱七104从员工表侧被过滤掉了。人事部105从部门表侧被过滤掉了。实操心得内连接是“过滤器”内连接的核心作用是过滤。当你只关心那些在两个表中都存在关联关系的记录时就用内连接。它是数据清洗和确保数据参照完整性的有力工具。例如在生成报表时如果你只想列出所有已分配部门的员工及其部门信息内连接是最佳选择。但务必小心它可能会 silently 丢弃数据如果你没意识到那些不匹配的记录存在可能会误以为数据是完整的。4. 左连接以左表为“基准”的包容性查询如果说内连接是严格的“双向选择”那么左连接就是“以我为主”。左连接会保留左表FROM后面的表的全部记录无论它们在右表中是否有匹配项。对于匹配成功的行它会像内连接一样组合数据对于左表中有而右表中无匹配的行它依然会保留左表数据并将来自右表的所有列用NULL值填充。它的语法是SELECT ... FROM left_table LEFT [OUTER] JOIN right_table ON condition。OUTER关键字通常可以省略。4.1 图解左连接逻辑维恩图中左连接的结果是整个左圆包括与右圆重叠的部分。员工表 (A) 部门表 (B) ○───────○ /| \ / | A ∪ (A∩B) \ | | | \ | / \| / ○───────○ (整个左圆A)匹配过程以员工表为左表处理张三101在部门表找到匹配组合数据。处理李四102找到匹配组合数据。处理王五103找到匹配组合数据。处理赵六NULL。连接条件e.dept_id d.dept_id中e.dept_id是NULL与任何值比较都是未知不匹配。但是因为这是左连接左表记录必须保留。所以结果集会生成一行赵六的所有信息照常显示而来自部门表的dept_id和dept_name全部用NULL填充。处理钱七104。在部门表找不到104不匹配。同样因为左连接保留左表所以钱七的记录被保留其对应的部门信息列填NULL。部门表的人事部105呢对不起左连接只保证左表全量不保证右表。右表中没有匹配左表的记录会被忽略。4.2 实操SQL与结果分析SELECT e.emp_id, e.emp_name, e.dept_id AS emp_dept_id, d.dept_id AS dept_dept_id, d.dept_name FROM employees e LEFT JOIN departments d ON e.dept_id d.dept_id;查询结果emp_idemp_nameemp_dept_iddept_dept_iddept_name1张三101101技术部2李四102102市场部3王五103103销售部4赵六NULLNULLNULL5钱七104NULLNULL看结果有5行和员工表的记录数一致前3行和内连接结果一样。第4行赵六。他的dept_id是NULL所以匹配不到任何部门部门信息列全部为NULL。第5行钱七。他的dept_id是104在部门表里不存在部门信息列也全部为NULL。注意事项左连接与WHERE子句的陷阱这是一个非常常见的错误。假设你想找出没有分配部门的员工。新手可能会这样写SELECT e.* FROM employees e LEFT JOIN departments d ON e.dept_id d.dept_id WHERE d.dept_id IS NULL;这个写法是正确的。因为左连接后没有部门的员工对应的d.dept_id就是NULL用WHERE过滤即可。但是如果你把条件写在ON子句里呢SELECT e.* FROM employees e LEFT JOIN departments d ON e.dept_id d.dept_id AND d.dept_id IS NULL;这几乎查不到任何东西因为ON子句是连接发生前的过滤条件它试图找到部门ID为NULL的部门记录去和员工连接这逻辑本身就是错的。记住ON决定如何连接WHERE决定连接后显示什么。对于左连接/右连接过滤右表条件通常放在WHERE里过滤左表条件可以放在ON里但会影响右表匹配逻辑。5. 右连接镜像般的左连接右连接和左连接在逻辑上是完全对称的只是“基准表”换成了右表。它会保留右表的全部记录无论它们在左表中是否有匹配。对于匹配成功的行组合数据对于右表中有而左表中无匹配的行保留右表数据左表列用NULL填充。语法SELECT ... FROM left_table RIGHT [OUTER] JOIN right_table ON condition。5.1 图解与实操因为逻辑对称我们可以直接看结果。这次我们以部门表为右表。SELECT e.emp_id, e.emp_name, e.dept_id AS emp_dept_id, d.dept_id AS dept_dept_id, d.dept_name FROM employees e RIGHT JOIN departments d ON e.dept_id d.dept_id;查询结果emp_idemp_nameemp_dept_iddept_dept_iddept_name1张三101101技术部2李四102102市场部3王五103103销售部NULLNULLNULL105人事部结果有4行和部门表的记录数一致前3行是匹配成功的。第4行人事部105。在员工表里找不到dept_id105的员工所以来自员工表的所有列emp_id,emp_name,emp_dept_id都被填为NULL。员工表中的赵六NULL和钱七104去哪了因为右连接不保证左表全量它们由于不匹配且不是右表记录被丢弃了。实操心得右连接的使用场景在实际开发中右连接的使用频率远低于左连接。这主要是因为人们的阅读和编写习惯通常是从左到右以FROM后的主表为基准。任何右连接都可以改写为左连接只需调换两个表的位置即可。例如上面的右连接查询完全等价于SELECT ... FROM departments d LEFT JOIN employees e ON d.dept_id e.dept_id;因此为了代码的一致性和可读性很多团队会约定优先使用左连接避免混用左右连接导致理解成本增加。当你发现自己在写右连接时可以停下来想想调换表顺序用左连接是否更清晰。6. 全外连接一个都不能少的“全家福”全外连接是左连接和右连接的“合集”。它会返回左表和右表中的所有记录。当某行在另一个表中没有匹配时则另一个表对应的列用NULL填充。如果两边都有匹配则正常组合数据。你可以把它理解为先把左表所有记录拿出来左连接再把右表独有的记录也拿出来右连接独有的部分然后合并在一起并去重基于连接条件同一匹配对只出现一次。语法SELECT ... FROM left_table FULL [OUTER] JOIN right_table ON condition。注意MySQL数据库不支持FULL JOIN但可以通过LEFT JOIN和RIGHT JOIN的UNION来模拟实现。6.1 图解全外连接逻辑维恩图中全外连接的结果是两个圆的全部面积。员工表 (A) 部门表 (B) ○───────○ /| |\ / | A∪B | \ | |(并集) | | \ | | / \| |/ ○───────○6.2 实操SQL与结果分析以PostgreSQL为例由于MySQL不支持我们在支持FULL JOIN的数据库如PostgreSQL, SQL Server中演示SELECT e.emp_id, e.emp_name, e.dept_id AS emp_dept_id, d.dept_id AS dept_dept_id, d.dept_name FROM employees e FULL OUTER JOIN departments d ON e.dept_id d.dept_id ORDER BY COALESCE(e.dept_id, d.dept_id), e.emp_id; -- 为了结果更清晰排序一下查询结果emp_idemp_nameemp_dept_iddept_dept_iddept_name1张三101101技术部2李四102102市场部3王五103103销售部4赵六NULLNULLNULL5钱七104NULLNULLNULLNULLNULL105人事部这个结果完美地展示了“全家福”第1-3行匹配成功的记录交集部分。第4行左表独有的记录赵六dept_id为NULL。第5行左表独有的记录钱七dept_id为104在右表不存在。第6行右表独有的记录人事部dept_id为105在左表不存在。在MySQL中如何实现全外连接使用LEFT JOIN和RIGHT JOIN的UNION。UNION会自动去重而UNION ALL会保留所有行如果左右连接有重复行则会出现重复。-- MySQL 模拟 FULL JOIN SELECT e.emp_id, e.emp_name, e.dept_id AS emp_dept_id, d.dept_id AS dept_dept_id, d.dept_name FROM employees e LEFT JOIN departments d ON e.dept_id d.dept_id UNION -- 使用 UNION 去重 SELECT e.emp_id, e.emp_name, e.dept_id AS emp_dept_id, d.dept_id AS dept_dept_id, d.dept_name FROM employees e RIGHT JOIN departments d ON e.dept_id d.dept_id WHERE e.dept_id IS NULL; -- 关键这里只取右连接中左表为NULL的部分即右表独有的记录这个查询的逻辑是先取左连接的全部结果左表全量匹配的右表再取右连接中左表为NULL的部分即右表独有且未在左连接中出现过的部分最后合并去重。结果与上面的FULL JOIN一致。常见问题什么时候用全外连接全外连接常用于数据对比和审计场景。比如你需要对比两个不同来源的客户列表找出只在A系统存在的客户、只在B系统存在的客户以及两个系统都有的客户。全外连接配合IS NULL条件判断可以一次性完成这个任务。另一个场景是生成完整的维度报告确保即使某些维度没有数据也在报告中占有一行显示为NULL或0。7. 交叉连接笛卡尔积的威力与危险交叉连接是所有连接类型中最“简单粗暴”的一种它不需要任何连接条件。它会返回左表的每一行与右表的每一行的所有可能组合。如果左表有M行右表有N行结果集就是M x N行。这被称为笛卡尔积。语法SELECT ... FROM table_a CROSS JOIN table_b 或者使用老式的逗号语法SELECT ... FROM table_a, table_b。7.1 图解与实操我们的员工表有5行部门表有4行交叉连接的结果将是 5 x 4 20 行。-- 显式 CROSS JOIN 语法 SELECT e.emp_name, d.dept_name FROM employees e CROSS JOIN departments d ORDER BY e.emp_name, d.dept_name; -- 等价于隐式语法不推荐易混淆 -- SELECT e.emp_name, d.dept_name FROM employees e, departments d;查询结果节选emp_namedept_name张三技术部张三市场部张三销售部张三人事部李四技术部李四市场部......钱七人事部你会看到“张三”和每一个部门都组合了一次其他员工亦然。这在大多数业务场景下是没有意义的因为它产生了大量无效数据。严重警告交叉连接的陷阱交叉连接极其危险尤其是在表数据量大的时候。一个1000行的表和一个1000行的表做交叉连接会产生100万行结果这很容易耗尽数据库内存和临时空间导致查询性能急剧下降甚至服务崩溃。最常见的错误是忘记写连接条件。如果你本意是想写内连接INNER JOIN ... ON ...却不小心漏掉了ON子句数据库会将其解释为交叉连接产生灾难性后果。-- 危险这是一个交叉连接不是内连接 SELECT * FROM employees e JOIN departments d; -- 正确写法 SELECT * FROM employees e JOIN departments d ON e.dept_id d.dept_id;因此务必养成使用显式JOIN ... ON ...语法的习惯避免使用老式的逗号连接这能大幅降低写错的风险。交叉连接的正确用途虽然危险但它并非一无是处。在需要生成所有可能组合的场景下很有用例如生成测试数据需要测试所有产品类型和所有颜色组合的价格。制作日历或矩阵将日期列表和门店列表交叉生成每个门店每天的空白销售记录模板。8. 自连接自己与自己对话自连接不是一种新的连接语法而是连接技巧的一种应用。它指的是同一个表与自己进行连接。为了区分“左表”和“右表”你必须使用表别名。8.1 经典场景查找员工的上级经理假设我们的employees表增加一个manager_id字段指向该员工上级的emp_id。ALTER TABLE employees ADD COLUMN manager_id INT; UPDATE employees SET manager_id CASE emp_id WHEN 2 THEN 1 -- 李四的经理是张三 WHEN 3 THEN 1 -- 王五的经理是张三 WHEN 5 THEN 2 -- 钱七的经理是李四 ELSE NULL END;现在表数据如下emp_idemp_namedept_idmanager_id1张三101NULL2李四10213王五10314赵六NULLNULL5钱七1042我们想查询每个员工及其经理的名字。这就需要自连接SELECT e.emp_id AS 员工ID, e.emp_name AS 员工姓名, m.emp_id AS 经理ID, m.emp_name AS 经理姓名 FROM employees e -- 员工视角的表 LEFT JOIN employees m ON e.manager_id m.emp_id; -- 经理视角的同一个表查询结果员工ID员工姓名经理ID经理姓名1张三NULLNULL2李四1张三3王五1张三4赵六NULLNULL5钱七2李四这里我们使用了左连接因为不是所有员工都有经理如张三本人。通过给employees表赋予两个不同的别名e和m我们将其虚拟成两个独立的表进行连接从而实现了层级关系的查询。实操心得自连接与性能自连接在处理层次结构数据如组织架构、分类树、评论回复链时非常有用。但要注意自连接本质上是对同一张大表做两次扫描和关联在数据量巨大时可能产生性能问题。对于深度不确定的多层树状结构递归公共表表达式是更现代、更高效的解决方案。9. 连接的综合应用与避坑指南理解了每种连接的区别后我们来看看如何在实际复杂查询中组合使用它们以及必须警惕的那些“坑”。9.1 组合查询找出所有“孤儿”数据一个常见的需求是找出所有没有部门的员工和所有没有员工的部门。这其实就是求左表独有和右表独有的并集。我们已经知道全外连接可以做到。用FULL JOIN加WHERE过滤-- 使用 FULL JOIN (非MySQL) SELECT 员工 AS 类型, e.emp_id, e.emp_name, NULL AS dept_id, NULL AS dept_name FROM employees e FULL JOIN departments d ON e.dept_id d.dept_id WHERE d.dept_id IS NULL -- 右表为空即员工没有部门 AND e.emp_id IS NOT NULL -- 确保是员工记录排除全NULL行如果有 UNION ALL SELECT 部门 AS 类型, NULL, NULL, d.dept_id, d.dept_name FROM employees e FULL JOIN departments d ON e.dept_id d.dept_id WHERE e.dept_id IS NULL -- 左表为空即部门没有员工 AND d.dept_id IS NOT NULL -- 确保是部门记录 ORDER BY 类型, emp_id, dept_id;在MySQL中我们可以用左右连接组合来模拟-- 找出没有部门的员工 (左连接中右表为NULL) SELECT 员工 AS 类型, e.emp_id, e.emp_name, NULL, NULL FROM employees e LEFT JOIN departments d ON e.dept_id d.dept_id WHERE d.dept_id IS NULL UNION ALL -- 找出没有员工的部门 (右连接中左表为NULL但用左连接写法更清晰) SELECT 部门 AS 类型, NULL, NULL, d.dept_id, d.dept_name FROM departments d LEFT JOIN employees e ON d.dept_id e.dept_id WHERE e.dept_id IS NULL;9.2 多表连接顺序与逻辑业务查询往往涉及三张或更多的表。例如我们再加一个projects项目表记录每个项目由哪个部门的哪位员工负责。CREATE TABLE projects ( project_id INT PRIMARY KEY, project_name VARCHAR(50), emp_id INT -- 负责员工 ); INSERT INTO projects VALUES (1, 项目A, 1), (2, 项目B, 3), (3, 项目C, 9); -- 注意员工9不存在现在想查询所有项目并显示项目名、负责人姓名、负责人部门名。这需要连接三张表。SELECT p.project_name, e.emp_name, d.dept_name FROM projects p LEFT JOIN employees e ON p.emp_id e.emp_id -- 先连接项目和员工 LEFT JOIN departments d ON e.dept_id d.dept_id; -- 再用员工连接部门查询结果project_nameemp_namedept_name项目A张三技术部项目B王五销售部项目CNULLNULL这里使用了两个连续的左连接。逻辑链条是以项目表为驱动找到对应的员工可能为NULL再通过找到的员工找到对应的部门也可能为NULL。这种链式连接非常普遍。避坑指南多表连接的顺序与类型选择驱动表选择通常应该将数据量小、过滤条件明确的表作为驱动表放在FROM后或作为左连接的主表这可以减少后续连接需要处理的数据量。连接类型一致在链式连接中如果第一个连接用了左连接后续的连接通常也需要用左连接否则第一个连接产生的NULL行可能会在后续的内连接中被过滤掉违背了“保留所有项目”的初衷。试着把上面第二个LEFT JOIN改成INNER JOIN看看“项目C”会不会消失ON与WHERE的优先级记住ON条件在连接时发生WHERE在连接后发生。在多表连接中ON条件只作用于它所属的那一对表而WHERE作用于最终的结果集。错误放置条件会导致完全不同的结果。9.3 性能考量连接不是免费的午餐连接操作尤其是涉及大数据表的连接是数据库中最耗资源的操作之一。索引是连接的性能之魂确保连接条件ON子句中的字段上建有索引。例如employees.dept_id和departments.dept_id上都应该有索引。没有索引的连接会导致全表扫描性能呈灾难性下降。避免SELECT *只选择你需要的列。特别是在多表连接时SELECT *会传输大量冗余数据浪费网络和内存资源。小心笛卡尔积再次强调永远检查你的连接是否都有有效的ON条件。理解执行计划对于复杂的多表连接使用EXPLAIN命令在MySQL/PostgreSQL中查看数据库的执行计划了解它是否使用了正确的索引以及连接的顺序是否高效。10. 总结回顾与核心口诀让我们回到最初的起点用一张终极对比表来总结这几种连接的核心区别连接类型关键字核心逻辑结果集包含维恩图类比内连接INNER JOIN或JOIN只返回两个表中连接条件匹配的行。两表的交集部分。两圆重叠部分左连接LEFT JOIN返回左表全部行即使右表无匹配。右表无匹配则填NULL。左表全集 右表匹配部分。整个左圆右连接RIGHT JOIN返回右表全部行即使左表无匹配。左表无匹配则填NULL。右表全集 左表匹配部分。整个右圆全外连接FULL OUTER JOIN返回左表和右表中的所有行。无匹配侧填NULL。两表的并集。两个圆的全部交叉连接CROSS JOIN返回两表的笛卡尔积无需条件。左表每行与右表每行的组合。不适用最后分享一个我用了很多年的快速决策口诀帮助你在写SQL时瞬间做出选择“要谁的全集就以谁为基准。”如果你只要两者匹配的结果 → 用INNER JOIN。如果你要左表的全集并带上右表的匹配信息 → 用LEFT JOIN。如果你要右表的全集→ 用RIGHT JOIN但通常改用LEFT JOIN并调换表顺序。如果你两者全集都要→ 用FULL OUTER JOINMySQL中用LEFT JOIN UNION RIGHT JOIN模拟。如果你想生成所有组合或做笛卡尔积→ 用CROSS JOIN并清楚知道你在做什么。记住连接的本质是集合操作。理解你的数据之间是哪种集合关系交集、左集、并集是写出正确、高效SQL查询的第一步。多画图多实验这些概念很快就会从你的知识负担变成你手中游刃有余的数据查询利器。

相关新闻

YOLOv5-seg实例分割实战:从数据标注到模型训练与部署全流程

YOLOv5-seg实例分割实战:从数据标注到模型训练与部署全流程

1. 项目概述:从目标检测到实例分割的实战跨越 如果你已经用YOLOv5玩转过目标检测,看着模型在图片里框出一个个物体觉得挺酷,那么是时候进入下一个阶段了:让模型不仅能框出物体,还能精确地勾勒出物体的轮廓。这就是YOL…

2026/10/17 12:03:10 阅读更多 →
AI安全攻防:红队视角下的无违禁词攻击与防御策略

AI安全攻防:红队视角下的无违禁词攻击与防御策略

1. 从“红队攻击”到“AI安全”:一次关于边界的探索最近在和一些做安全研究的朋友聊天,大家不约而同地提到了一个词:“红队”。在网络安全领域,红队扮演着攻击者的角色,他们的核心任务不是搞破坏,而是通过模…

2026/10/20 10:09:02 阅读更多 →
Platinum-MD终极指南:免费开源工具让复古MiniDisc设备重获新生

Platinum-MD终极指南:免费开源工具让复古MiniDisc设备重获新生

Platinum-MD终极指南:免费开源工具让复古MiniDisc设备重获新生 【免费下载链接】platinum-md Minidisc NetMD Conversion and Upload 项目地址: https://gitcode.com/gh_mirrors/pl/platinum-md 还在为20年前的MiniDisc设备找不到合适的现代管理软件而烦恼吗…

2026/10/17 12:03:44 阅读更多 →

最新新闻

Delphi System.JSON 封装实践:从链式读写到RTTI映射的工程化设计

Delphi System.JSON 封装实践:从链式读写到RTTI映射的工程化设计

1. 为什么要在 System.JSON 外面再做一层封装1.1 原生 API 用起来最别扭的三个地方先说说我的真实感受。我在一个跨平台工具项目里频繁处理接口数据,第一版直接拿System.JSON裸写,写着写着就发现效率极低。原生库的功能其实都在:TJSONObject、…

2026/10/20 10:08:50 阅读更多 →
openTCS源码解析:构建、调度内核与AGV通信适配器

openTCS源码解析:构建、调度内核与AGV通信适配器

简介:openTCS 是一套开源的运输控制系统,用于控制自动导引车等物料搬运设备,这份压缩包面向希望深入学习其源码、进行二次开发的工程师与研究者,内含 openTCS 4.16.1 版本的原始码、示例原始码、官方文档及个人学习笔记。资源包采…

2026/10/20 10:08:50 阅读更多 →
CMake大型工程组织:多模块目录分层与依赖管理实战

CMake大型工程组织:多模块目录分层与依赖管理实战

简介:这份资源面向具备一定C基础、希望掌握大型工程构建管理的开发者,围绕CMakeLists.txt这一核心工具,讲解如何用统一方式组织多目录、多模块的项目结构。内容涵盖项目初始化、子目录管理、目标属性设置、外部依赖查找、CTest测试集成、安装…

2026/10/20 10:08:50 阅读更多 →
Delphi JSON封装:告别System.JSON繁琐API,打造优雅对象映射库

Delphi JSON封装:告别System.JSON繁琐API,打造优雅对象映射库

作为一个常年用 Delphi 写业务系统的老手&#xff0c;我太清楚原生System.JSON用起来有多别扭了。明明只是一个简单的“取字段值”操作&#xff0c;却要写出一长串FindValue、GetValue<string>&#xff0c;还得小心翼翼处理可能存在的Access Violation——JSON 里少个字段…

2026/10/20 10:08:50 阅读更多 →
国产ZXDoc源码包替代商业SDK:基于OXML规范的文档解析与渐进式替换指南

国产ZXDoc源码包替代商业SDK:基于OXML规范的文档解析与渐进式替换指南

简介&#xff1a;面向新能源车研发与汽车电子工具链从业者&#xff0c;这份项目代码包聚焦国产ZXDoc如何打破Vector CANoe垄断&#xff0c;以网页形式呈现技术突围背景与功能亮点。代码包含HTML页面及配套inscode配置、gitignore规则&#xff0c;文件仅3个、压缩后6KB&#xff…

2026/10/20 10:08:50 阅读更多 →
国产ZXDoc突围Vector垄断:文件解析与SDK替换实战解析

国产ZXDoc突围Vector垄断:文件解析与SDK替换实战解析

简介&#xff1a;面向汽车电子与嵌入式研发工程师、新能源车总线测试人员&#xff0c;围绕国产ZXDoc突围Vector垄断主题整理的项目代码资源&#xff0c;可帮助快速了解其在四大车载总线协议支持、DBC智能解析、ECU刷写与XCP标定等方面的技术特性与市场定位。ZIP压缩包体积仅6KB…

2026/10/20 10:07:49 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →