[{"data":1,"prerenderedAt":2187},["ShallowReactive",2],{"post:\u002Fposts\u002Fmysql\u002Fmysql-learning-05":3,"posts:ordered":1897},{"id":4,"title":5,"body":6,"category":1881,"cover":1882,"date":1883,"description":1884,"extension":1885,"featured":1886,"meta":1887,"navigation":254,"path":1888,"seo":1889,"series":1890,"seriesOrder":264,"stem":1891,"tags":1892,"__hash__":1896},"posts\u002Fposts\u002Fmysql\u002Fmysql-learning-05.md","MySQL 学习笔记 05：DDL 概览",{"type":7,"value":8,"toc":1872},"minimark",[9,16,21,26,29,77,80,102,105,211,214,390,393,410,413,417,420,443,445,557,559,582,584,595,597,601,604,607,624,626,711,713,753,756,832,835,938,941,965,967,987,989,993,996,1010,1012,1077,1080,1102,1105,1149,1152,1171,1173,1187,1189,1200,1202,1206,1209,1229,1231,1297,1300,1329,1331,1355,1357,1368,1370,1374,1377,1380,1453,1455,1554,1556,1590,1593,1688,1690,1717,1723,1768,1771,1802,1804,1818,1820,1831,1833,1837,1845,1848,1868],[10,11,12],"blockquote",{},[13,14,15],"p",{},"本文是《SQL 学习笔记》系列的一篇：示例数据和 SQL 都是我整理并在 MySQL 8 上跑过的，讲解部分按自己的理解写的。",[17,18,20],"h1",{"id":19},"_8-data-definition-languageddl数据定义语言","8 Data Definition Language（DDL，数据定义语言）",[22,23,25],"h2",{"id":24},"_81-ddl-概述","8.1 DDL 概述",[13,27,28],{},"DDL 用于定义和管理数据库对象的结构，而不是直接操作表中的数据。",[30,31,32,36,53],"ul",{},[33,34,35],"li",{},"定义数据的结构、组织方式以及数据项之间的关系。",[33,37,38,39],{},"数据库对象包括：\n",[30,40,41,44,47,50],{},[33,42,43],{},"Tables：表",[33,45,46],{},"Views：视图",[33,48,49],{},"Indexes：索引",[33,51,52],{},"Schemas：模式",[33,54,55,56],{},"DDL 核心命令：\n",[30,57,58,65,71],{},[33,59,60,64],{},[61,62,63],"code",{},"CREATE","：创建新对象。",[33,66,67,70],{},[61,68,69],{},"DROP","：删除对象。",[33,72,73,76],{},[61,74,75],{},"ALTER","：修改对象特征。",[13,78,79],{},"注释：",[30,81,82,85,99],{},[33,83,84],{},"DDL 管“结构”，例如建表、改列、删表。",[33,86,87,88,91,92,91,95,98],{},"DML 管“数据”，例如 ",[61,89,90],{},"INSERT","、",[61,93,94],{},"UPDATE",[61,96,97],{},"DELETE","。",[33,100,101],{},"DDL 语句通常会自动提交，但不同数据库行为可能不同。",[13,103,104],{},"常见对象与命令对应关系：",[106,107,108,127],"table",{},[109,110,111],"thead",{},[112,113,114,118,121,124],"tr",{},[115,116,117],"th",{},"对象",[115,119,120],{},"创建",[115,122,123],{},"修改",[115,125,126],{},"删除",[128,129,130,149,169,193],"tbody",{},[112,131,132,136,141,144],{},[133,134,135],"td",{},"Schema",[133,137,138],{},[61,139,140],{},"CREATE SCHEMA",[133,142,143],{},"通常较少修改",[133,145,146],{},[61,147,148],{},"DROP SCHEMA",[112,150,151,154,159,164],{},[133,152,153],{},"Table",[133,155,156],{},[61,157,158],{},"CREATE TABLE",[133,160,161],{},[61,162,163],{},"ALTER TABLE",[133,165,166],{},[61,167,168],{},"DROP TABLE",[112,170,171,174,179,188],{},[133,172,173],{},"View",[133,175,176],{},[61,177,178],{},"CREATE VIEW",[133,180,181,184,185],{},[61,182,183],{},"CREATE OR REPLACE VIEW"," \u002F ",[61,186,187],{},"ALTER VIEW",[133,189,190],{},[61,191,192],{},"DROP VIEW",[112,194,195,198,203,206],{},[133,196,197],{},"Index",[133,199,200],{},[61,201,202],{},"CREATE INDEX",[133,204,205],{},"通常删除后重建",[133,207,208],{},[61,209,210],{},"DROP INDEX",[13,212,213],{},"示例：",[215,216,221],"pre",{"className":217,"code":218,"language":219,"meta":220,"style":220},"language-sql shiki shiki-themes github-light github-dark","-- 创建模式\nCREATE SCHEMA Sales;\n\n-- 创建表\nCREATE TABLE Sales.Customers (\n    Id INT PRIMARY KEY,\n    Name VARCHAR(50) NOT NULL\n);\n\n-- 修改表\nALTER TABLE Sales.Customers\nADD Email VARCHAR(100);\n\n-- 删除表\nDROP TABLE Sales.Customers;\n","sql","",[61,222,223,232,249,256,262,275,290,312,318,323,329,344,363,368,374],{"__ignoreMap":220},[224,225,228],"span",{"class":226,"line":227},"line",1,[224,229,231],{"class":230},"sJ8bj","-- 创建模式\n",[224,233,235,238,241,245],{"class":226,"line":234},2,[224,236,63],{"class":237},"szBVR",[224,239,240],{"class":237}," SCHEMA",[224,242,244],{"class":243},"sScJk"," Sales",[224,246,248],{"class":247},"sVt8B",";\n",[224,250,252],{"class":226,"line":251},3,[224,253,255],{"emptyLinePlaceholder":254},true,"\n",[224,257,259],{"class":226,"line":258},4,[224,260,261],{"class":230},"-- 创建表\n",[224,263,265,267,270,272],{"class":226,"line":264},5,[224,266,63],{"class":237},[224,268,269],{"class":237}," TABLE",[224,271,244],{"class":243},[224,273,274],{"class":247},".Customers (\n",[224,276,278,281,284,287],{"class":226,"line":277},6,[224,279,280],{"class":247},"    Id ",[224,282,283],{"class":237},"INT",[224,285,286],{"class":237}," PRIMARY KEY",[224,288,289],{"class":247},",\n",[224,291,293,296,299,302,306,309],{"class":226,"line":292},7,[224,294,295],{"class":237},"    Name",[224,297,298],{"class":237}," VARCHAR",[224,300,301],{"class":247},"(",[224,303,305],{"class":304},"sj4cs","50",[224,307,308],{"class":247},") ",[224,310,311],{"class":237},"NOT NULL\n",[224,313,315],{"class":226,"line":314},8,[224,316,317],{"class":247},");\n",[224,319,321],{"class":226,"line":320},9,[224,322,255],{"emptyLinePlaceholder":254},[224,324,326],{"class":226,"line":325},10,[224,327,328],{"class":230},"-- 修改表\n",[224,330,332,334,336,338,341],{"class":226,"line":331},11,[224,333,75],{"class":237},[224,335,269],{"class":237},[224,337,244],{"class":304},[224,339,340],{"class":247},".",[224,342,343],{"class":304},"Customers\n",[224,345,347,350,353,356,358,361],{"class":226,"line":346},12,[224,348,349],{"class":237},"ADD",[224,351,352],{"class":247}," Email ",[224,354,355],{"class":237},"VARCHAR",[224,357,301],{"class":247},[224,359,360],{"class":304},"100",[224,362,317],{"class":247},[224,364,366],{"class":226,"line":365},13,[224,367,255],{"emptyLinePlaceholder":254},[224,369,371],{"class":226,"line":370},14,[224,372,373],{"class":230},"-- 删除表\n",[224,375,377,379,381,383,385,388],{"class":226,"line":376},15,[224,378,69],{"class":237},[224,380,269],{"class":237},[224,382,244],{"class":304},[224,384,340],{"class":247},[224,386,387],{"class":304},"Customers",[224,389,248],{"class":247},[13,391,392],{},"作用：",[30,394,395,400,405],{},[33,396,397,399],{},[61,398,63],{}," 建立数据库结构。",[33,401,402,404],{},[61,403,75],{}," 调整已有结构。",[33,406,407,409],{},[61,408,69],{}," 删除结构及其定义。",[411,412],"hr",{},[22,414,416],{"id":415},"_82-schema模式","8.2 Schema（模式）",[13,418,419],{},"Schema 是逻辑容器，用于组织数据库对象。",[30,421,422,425,440],{},[33,423,424],{},"可以把 Schema 理解为一个命名空间。",[33,426,427,428],{},"不同 Schema 中可以存在同名表，例如：\n",[30,429,430,435],{},[33,431,432],{},[61,433,434],{},"Sales.Customers",[33,436,437],{},[61,438,439],{},"Archive.Customers",[33,441,442],{},"有些数据库中 Schema 与 Database 同义（MySQL同义），有些数据库中有区别。",[13,444,213],{},[215,446,448],{"className":217,"code":447,"language":219,"meta":220,"style":220},"-- 创建模式\nCREATE SCHEMA Sales;\n\n-- 在指定模式中创建表\nCREATE TABLE Sales.Customers (\n    Id INT PRIMARY KEY,\n    Name VARCHAR(50) NOT NULL\n);\n\n-- 查询时带上模式名\nSELECT * FROM Sales.Customers;\n\n-- 删除模式\nDROP SCHEMA Sales;\n",[61,449,450,454,464,468,473,483,493,507,511,515,520,539,543,548],{"__ignoreMap":220},[224,451,452],{"class":226,"line":227},[224,453,231],{"class":230},[224,455,456,458,460,462],{"class":226,"line":234},[224,457,63],{"class":237},[224,459,240],{"class":237},[224,461,244],{"class":243},[224,463,248],{"class":247},[224,465,466],{"class":226,"line":251},[224,467,255],{"emptyLinePlaceholder":254},[224,469,470],{"class":226,"line":258},[224,471,472],{"class":230},"-- 在指定模式中创建表\n",[224,474,475,477,479,481],{"class":226,"line":264},[224,476,63],{"class":237},[224,478,269],{"class":237},[224,480,244],{"class":243},[224,482,274],{"class":247},[224,484,485,487,489,491],{"class":226,"line":277},[224,486,280],{"class":247},[224,488,283],{"class":237},[224,490,286],{"class":237},[224,492,289],{"class":247},[224,494,495,497,499,501,503,505],{"class":226,"line":292},[224,496,295],{"class":237},[224,498,298],{"class":237},[224,500,301],{"class":247},[224,502,305],{"class":304},[224,504,308],{"class":247},[224,506,311],{"class":237},[224,508,509],{"class":226,"line":314},[224,510,317],{"class":247},[224,512,513],{"class":226,"line":320},[224,514,255],{"emptyLinePlaceholder":254},[224,516,517],{"class":226,"line":325},[224,518,519],{"class":230},"-- 查询时带上模式名\n",[224,521,522,525,528,531,533,535,537],{"class":226,"line":331},[224,523,524],{"class":237},"SELECT",[224,526,527],{"class":237}," *",[224,529,530],{"class":237}," FROM",[224,532,244],{"class":304},[224,534,340],{"class":247},[224,536,387],{"class":304},[224,538,248],{"class":247},[224,540,541],{"class":226,"line":346},[224,542,255],{"emptyLinePlaceholder":254},[224,544,545],{"class":226,"line":365},[224,546,547],{"class":230},"-- 删除模式\n",[224,549,550,552,554],{"class":226,"line":370},[224,551,69],{"class":237},[224,553,240],{"class":237},[224,555,556],{"class":247}," Sales;\n",[13,558,79],{},[30,560,561,573,576],{},[33,562,563,565,566,569,570,572],{},[61,564,434],{}," 表示 ",[61,567,568],{},"Sales"," 模式下的 ",[61,571,387],{}," 表。",[33,574,575],{},"使用 Schema 可以避免表名冲突，也便于按业务分类。",[33,577,578,579,98],{},"删除 Schema 时，不同数据库可能要求先删除其中对象，或使用 ",[61,580,581],{},"CASCADE",[13,583,392],{},[30,585,586,589,592],{},[33,587,588],{},"组织数据库对象。",[33,590,591],{},"隔离不同业务、模块或用户的数据结构。",[33,593,594],{},"提供更清晰的命名空间。",[411,596],{},[22,598,600],{"id":599},"_83-table表","8.3 Table（表）",[13,602,603],{},"表是关系数据库中实际存储数据的基本对象。",[13,605,606],{},"表包含：",[30,608,609,612,615,618,621],{},[33,610,611],{},"Columns \u002F Fields \u002F Attributes：列 \u002F 字段 \u002F 属性",[33,613,614],{},"Rows \u002F Tuples \u002F Records：行 \u002F 元组 \u002F 记录",[33,616,617],{},"Primary Key：主键",[33,619,620],{},"Column name：列名",[33,622,623],{},"Column Values \u002F Data Items：列值 \u002F 数据项",[13,625,213],{},[215,627,629],{"className":217,"code":628,"language":219,"meta":220,"style":220},"CREATE TABLE Sales.Customers (\n    Id INT PRIMARY KEY,\n    Name VARCHAR(50) NOT NULL,\n    Race CHAR(2),\n    Age INT,\n    Email VARCHAR(100)\n);\n",[61,630,631,641,651,668,684,693,707],{"__ignoreMap":220},[224,632,633,635,637,639],{"class":226,"line":227},[224,634,63],{"class":237},[224,636,269],{"class":237},[224,638,244],{"class":243},[224,640,274],{"class":247},[224,642,643,645,647,649],{"class":226,"line":234},[224,644,280],{"class":247},[224,646,283],{"class":237},[224,648,286],{"class":237},[224,650,289],{"class":247},[224,652,653,655,657,659,661,663,666],{"class":226,"line":251},[224,654,295],{"class":237},[224,656,298],{"class":237},[224,658,301],{"class":247},[224,660,305],{"class":304},[224,662,308],{"class":247},[224,664,665],{"class":237},"NOT NULL",[224,667,289],{"class":247},[224,669,670,673,676,678,681],{"class":226,"line":258},[224,671,672],{"class":247},"    Race ",[224,674,675],{"class":237},"CHAR",[224,677,301],{"class":247},[224,679,680],{"class":304},"2",[224,682,683],{"class":247},"),\n",[224,685,686,689,691],{"class":226,"line":264},[224,687,688],{"class":247},"    Age ",[224,690,283],{"class":237},[224,692,289],{"class":247},[224,694,695,698,700,702,704],{"class":226,"line":277},[224,696,697],{"class":247},"    Email ",[224,699,355],{"class":237},[224,701,301],{"class":247},[224,703,360],{"class":304},[224,705,706],{"class":247},")\n",[224,708,709],{"class":226,"line":292},[224,710,317],{"class":247},[13,712,79],{},[30,714,715,721,730,742,748],{},[33,716,717,720],{},[61,718,719],{},"Id"," 是主键，用于唯一标识一行。",[33,722,723,726,727,729],{},[61,724,725],{},"Name"," 是 ",[61,728,665],{},"，插入时必须提供值。",[33,731,732,91,735,91,738,741],{},[61,733,734],{},"Race",[61,736,737],{},"Age",[61,739,740],{},"Email"," 可以为空。",[33,743,744,747],{},[61,745,746],{},"VARCHAR(50)"," 表示可变长度字符串，最大 50 个字符。",[33,749,750,752],{},[61,751,283],{}," 表示整数。",[13,754,755],{},"表中数据示意：",[106,757,758,773],{},[109,759,760],{},[112,761,762,765,767,769,771],{},[115,763,719],{"align":764},"right",[115,766,725],{},[115,768,734],{},[115,770,737],{"align":764},[115,772,740],{},[128,774,775,796,812],{},[112,776,777,780,783,786,789],{},[133,778,779],{"align":764},"1",[133,781,782],{},"Chia",[133,784,785],{},"CN",[133,787,788],{"align":764},"22",[133,790,791],{},[792,793,795],"a",{"href":794},"mailto:chia@example.com","chia@example.com",[112,797,798,800,803,806,809],{},[133,799,680],{"align":764},[133,801,802],{},"Tom",[133,804,805],{},"ML",[133,807,808],{"align":764},"18",[133,810,811],{},"NULL",[112,813,814,817,820,823,826],{},[133,815,816],{"align":764},"3",[133,818,819],{},"Alice",[133,821,822],{},"IND",[133,824,825],{"align":764},"25",[133,827,828],{},[792,829,831],{"href":830},"mailto:alice@example.com","alice@example.com",[13,833,834],{},"修改表结构：",[215,836,838],{"className":217,"code":837,"language":219,"meta":220,"style":220},"-- 添加列\nALTER TABLE Sales.Customers\nADD Phone VARCHAR(20);\n\n-- 修改列定义，不同数据库语法不同\nALTER TABLE Sales.Customers\nMODIFY Name VARCHAR(100);\n\n-- 删除列\nALTER TABLE Sales.Customers\nDROP COLUMN Phone;\n",[61,839,840,845,857,873,877,882,894,910,914,919,931],{"__ignoreMap":220},[224,841,842],{"class":226,"line":227},[224,843,844],{"class":230},"-- 添加列\n",[224,846,847,849,851,853,855],{"class":226,"line":234},[224,848,75],{"class":237},[224,850,269],{"class":237},[224,852,244],{"class":304},[224,854,340],{"class":247},[224,856,343],{"class":304},[224,858,859,861,864,866,868,871],{"class":226,"line":251},[224,860,349],{"class":237},[224,862,863],{"class":247}," Phone ",[224,865,355],{"class":237},[224,867,301],{"class":247},[224,869,870],{"class":304},"20",[224,872,317],{"class":247},[224,874,875],{"class":226,"line":258},[224,876,255],{"emptyLinePlaceholder":254},[224,878,879],{"class":226,"line":264},[224,880,881],{"class":230},"-- 修改列定义，不同数据库语法不同\n",[224,883,884,886,888,890,892],{"class":226,"line":277},[224,885,75],{"class":237},[224,887,269],{"class":237},[224,889,244],{"class":304},[224,891,340],{"class":247},[224,893,343],{"class":304},[224,895,896,899,902,904,906,908],{"class":226,"line":292},[224,897,898],{"class":237},"MODIFY",[224,900,901],{"class":237}," Name",[224,903,298],{"class":237},[224,905,301],{"class":247},[224,907,360],{"class":304},[224,909,317],{"class":247},[224,911,912],{"class":226,"line":314},[224,913,255],{"emptyLinePlaceholder":254},[224,915,916],{"class":226,"line":320},[224,917,918],{"class":230},"-- 删除列\n",[224,920,921,923,925,927,929],{"class":226,"line":325},[224,922,75],{"class":237},[224,924,269],{"class":237},[224,926,244],{"class":304},[224,928,340],{"class":247},[224,930,343],{"class":304},[224,932,933,935],{"class":226,"line":331},[224,934,69],{"class":237},[224,936,937],{"class":247}," COLUMN Phone;\n",[13,939,940],{},"删除表：",[215,942,944],{"className":217,"code":943,"language":219,"meta":220,"style":220},"-- 删除表结构和数据\nDROP TABLE Sales.Customers;\n",[61,945,946,951],{"__ignoreMap":220},[224,947,948],{"class":226,"line":227},[224,949,950],{"class":230},"-- 删除表结构和数据\n",[224,952,953,955,957,959,961,963],{"class":226,"line":234},[224,954,69],{"class":237},[224,956,269],{"class":237},[224,958,244],{"class":304},[224,960,340],{"class":247},[224,962,387],{"class":304},[224,964,248],{"class":247},[13,966,392],{},[30,968,969,974,979,984],{},[33,970,971,973],{},[61,972,158],{}," 定义表结构。",[33,975,976,978],{},[61,977,163],{}," 修改表结构。",[33,980,981,983],{},[61,982,168],{}," 删除整个表。",[33,985,986],{},"表是数据存储的核心对象，行表示记录，列表示属性。",[411,988],{},[22,990,992],{"id":991},"_84-view视图","8.4 View（视图）",[13,994,995],{},"视图是虚拟表，不存储数据。",[30,997,998,1004,1007],{},[33,999,1000,1001,1003],{},"视图基于 ",[61,1002,524],{}," 查询定义。",[33,1005,1006],{},"查询视图时，实际上执行的是视图背后的查询。",[33,1008,1009],{},"视图可以简化复杂查询，也可以隐藏部分列。",[13,1011,213],{},[215,1013,1015],{"className":217,"code":1014,"language":219,"meta":220,"style":220},"-- 创建视图：只显示 CN 客户\nCREATE VIEW Sales.CN_Customers AS\nSELECT Id, Name, Age\nFROM Sales.Customers\nWHERE Race = 'CN';\n",[61,1016,1017,1022,1037,1049,1060],{"__ignoreMap":220},[224,1018,1019],{"class":226,"line":227},[224,1020,1021],{"class":230},"-- 创建视图：只显示 CN 客户\n",[224,1023,1024,1026,1029,1031,1034],{"class":226,"line":234},[224,1025,63],{"class":237},[224,1027,1028],{"class":237}," VIEW",[224,1030,244],{"class":243},[224,1032,1033],{"class":247},".CN_Customers ",[224,1035,1036],{"class":237},"AS\n",[224,1038,1039,1041,1044,1046],{"class":226,"line":251},[224,1040,524],{"class":237},[224,1042,1043],{"class":247}," Id, ",[224,1045,725],{"class":237},[224,1047,1048],{"class":247},", Age\n",[224,1050,1051,1054,1056,1058],{"class":226,"line":258},[224,1052,1053],{"class":237},"FROM",[224,1055,244],{"class":304},[224,1057,340],{"class":247},[224,1059,343],{"class":304},[224,1061,1062,1065,1068,1071,1075],{"class":226,"line":264},[224,1063,1064],{"class":237},"WHERE",[224,1066,1067],{"class":247}," Race ",[224,1069,1070],{"class":237},"=",[224,1072,1074],{"class":1073},"sZZnC"," 'CN'",[224,1076,248],{"class":247},[13,1078,1079],{},"查询视图：",[215,1081,1083],{"className":217,"code":1082,"language":219,"meta":220,"style":220},"SELECT * FROM Sales.CN_Customers;\n",[61,1084,1085],{"__ignoreMap":220},[224,1086,1087,1089,1091,1093,1095,1097,1100],{"class":226,"line":227},[224,1088,524],{"class":237},[224,1090,527],{"class":237},[224,1092,530],{"class":237},[224,1094,244],{"class":304},[224,1096,340],{"class":247},[224,1098,1099],{"class":304},"CN_Customers",[224,1101,248],{"class":247},[13,1103,1104],{},"效果类似：",[106,1106,1107,1117],{},[109,1108,1109],{},[112,1110,1111,1113,1115],{},[115,1112,719],{"align":764},[115,1114,725],{},[115,1116,737],{"align":764},[128,1118,1119,1127,1138],{},[112,1120,1121,1123,1125],{},[133,1122,779],{"align":764},[133,1124,782],{},[133,1126,788],{"align":764},[112,1128,1129,1132,1135],{},[133,1130,1131],{"align":764},"4",[133,1133,1134],{},"Bob",[133,1136,1137],{"align":764},"17",[112,1139,1140,1143,1146],{},[133,1141,1142],{"align":764},"5",[133,1144,1145],{},"Chen",[133,1147,1148],{"align":764},"30",[13,1150,1151],{},"删除视图：",[215,1153,1155],{"className":217,"code":1154,"language":219,"meta":220,"style":220},"DROP VIEW Sales.CN_Customers;\n",[61,1156,1157],{"__ignoreMap":220},[224,1158,1159,1161,1163,1165,1167,1169],{"class":226,"line":227},[224,1160,69],{"class":237},[224,1162,1028],{"class":237},[224,1164,244],{"class":304},[224,1166,340],{"class":247},[224,1168,1099],{"class":304},[224,1170,248],{"class":247},[13,1172,79],{},[30,1174,1175,1178,1181,1184],{},[33,1176,1177],{},"视图本身通常不保存数据，只保存定义。",[33,1179,1180],{},"视图可以像表一样被查询。",[33,1182,1183],{},"视图是否可更新取决于数据库和视图定义，这里不展开。",[33,1185,1186],{},"使用视图可以简化常用查询，提高复用性。",[13,1188,392],{},[30,1190,1191,1194,1197],{},[33,1192,1193],{},"简化复杂查询。",[33,1195,1196],{},"隐藏敏感列或复杂逻辑。",[33,1198,1199],{},"提供逻辑层面的数据视图。",[411,1201],{},[22,1203,1205],{"id":1204},"_85-index索引","8.5 Index（索引）",[13,1207,1208],{},"索引用于提高数据检索速度。",[30,1210,1211,1214,1217],{},[33,1212,1213],{},"类似书的目录。",[33,1215,1216],{},"可以建立在表的一列或多列上。",[33,1218,1219,1220,91,1222,91,1225,1228],{},"常见于 ",[61,1221,1064],{},[61,1223,1224],{},"JOIN",[61,1226,1227],{},"ORDER BY"," 等操作。",[13,1230,213],{},[215,1232,1234],{"className":217,"code":1233,"language":219,"meta":220,"style":220},"-- 在 Race 列上创建普通索引\nCREATE INDEX idx_customers_race\nON Sales.Customers(Race);\n\n-- 在 Email 列上创建唯一索引\nCREATE UNIQUE INDEX idx_customers_email\nON Sales.Customers(Email);\n",[61,1235,1236,1241,1251,1265,1269,1274,1284],{"__ignoreMap":220},[224,1237,1238],{"class":226,"line":227},[224,1239,1240],{"class":230},"-- 在 Race 列上创建普通索引\n",[224,1242,1243,1245,1248],{"class":226,"line":234},[224,1244,63],{"class":237},[224,1246,1247],{"class":237}," INDEX",[224,1249,1250],{"class":243}," idx_customers_race\n",[224,1252,1253,1256,1258,1260,1262],{"class":226,"line":251},[224,1254,1255],{"class":237},"ON",[224,1257,244],{"class":304},[224,1259,340],{"class":247},[224,1261,387],{"class":304},[224,1263,1264],{"class":247},"(Race);\n",[224,1266,1267],{"class":226,"line":258},[224,1268,255],{"emptyLinePlaceholder":254},[224,1270,1271],{"class":226,"line":264},[224,1272,1273],{"class":230},"-- 在 Email 列上创建唯一索引\n",[224,1275,1276,1278,1281],{"class":226,"line":277},[224,1277,63],{"class":237},[224,1279,1280],{"class":237}," UNIQUE INDEX",[224,1282,1283],{"class":243}," idx_customers_email\n",[224,1285,1286,1288,1290,1292,1294],{"class":226,"line":292},[224,1287,1255],{"class":237},[224,1289,244],{"class":304},[224,1291,340],{"class":247},[224,1293,387],{"class":304},[224,1295,1296],{"class":247},"(Email);\n",[13,1298,1299],{},"删除索引：",[215,1301,1303],{"className":217,"code":1302,"language":219,"meta":220,"style":220},"-- MySQL 语法\nDROP INDEX idx_customers_race ON Sales.Customers;\n",[61,1304,1305,1310],{"__ignoreMap":220},[224,1306,1307],{"class":226,"line":227},[224,1308,1309],{"class":230},"-- MySQL 语法\n",[224,1311,1312,1314,1316,1319,1321,1323,1325,1327],{"class":226,"line":234},[224,1313,69],{"class":237},[224,1315,1247],{"class":237},[224,1317,1318],{"class":247}," idx_customers_race ",[224,1320,1255],{"class":237},[224,1322,244],{"class":304},[224,1324,340],{"class":247},[224,1326,387],{"class":304},[224,1328,248],{"class":247},[13,1330,79],{},[30,1332,1333,1336,1346,1349,1352],{},[33,1334,1335],{},"索引可以加快查询，但会占用额外空间。",[33,1337,1338,1339,91,1341,91,1343,1345],{},"索引会降低 ",[61,1340,90],{},[61,1342,94],{},[61,1344,97],{}," 的速度，因为数据变化时索引也要维护。",[33,1347,1348],{},"唯一索引要求索引列的值不能重复。",[33,1350,1351],{},"主键通常会自动创建索引。",[33,1353,1354],{},"不同数据库删除索引语法可能不同。",[13,1356,392],{},[30,1358,1359,1362,1365],{},[33,1360,1361],{},"加速数据检索。",[33,1363,1364],{},"支持唯一性约束。",[33,1366,1367],{},"优化连接和排序操作。",[411,1369],{},[22,1371,1373],{"id":1372},"_86-constraints约束","8.6 Constraints（约束）",[13,1375,1376],{},"约束是强制数据完整性的规则。",[13,1378,1379],{},"常见约束：",[106,1381,1382,1392],{},[109,1383,1384],{},[112,1385,1386,1389],{},[115,1387,1388],{},"约束",[115,1390,1391],{},"作用",[128,1393,1394,1404,1414,1423,1433,1443],{},[112,1395,1396,1401],{},[133,1397,1398],{},[61,1399,1400],{},"PRIMARY KEY",[133,1402,1403],{},"主键，唯一且非空，标识一行",[112,1405,1406,1411],{},[133,1407,1408],{},[61,1409,1410],{},"FOREIGN KEY",[133,1412,1413],{},"外键，引用另一张表的主键或唯一键",[112,1415,1416,1420],{},[133,1417,1418],{},[61,1419,665],{},[133,1421,1422],{},"该列不允许为空",[112,1424,1425,1430],{},[133,1426,1427],{},[61,1428,1429],{},"UNIQUE",[133,1431,1432],{},"该列或列组合的值必须唯一",[112,1434,1435,1440],{},[133,1436,1437],{},[61,1438,1439],{},"CHECK",[133,1441,1442],{},"该列值必须满足指定条件",[112,1444,1445,1450],{},[133,1446,1447],{},[61,1448,1449],{},"DEFAULT",[133,1451,1452],{},"未提供值时使用默认值",[13,1454,213],{},[215,1456,1458],{"className":217,"code":1457,"language":219,"meta":220,"style":220},"CREATE TABLE Sales.Customers (\n    Id INT PRIMARY KEY,\n    Name VARCHAR(50) NOT NULL,\n    Email VARCHAR(100) UNIQUE,\n    Age INT CHECK (Age >= 0),\n    CountryCode CHAR(2) DEFAULT 'CN'\n);\n",[61,1459,1460,1470,1480,1496,1512,1532,1550],{"__ignoreMap":220},[224,1461,1462,1464,1466,1468],{"class":226,"line":227},[224,1463,63],{"class":237},[224,1465,269],{"class":237},[224,1467,244],{"class":243},[224,1469,274],{"class":247},[224,1471,1472,1474,1476,1478],{"class":226,"line":234},[224,1473,280],{"class":247},[224,1475,283],{"class":237},[224,1477,286],{"class":237},[224,1479,289],{"class":247},[224,1481,1482,1484,1486,1488,1490,1492,1494],{"class":226,"line":251},[224,1483,295],{"class":237},[224,1485,298],{"class":237},[224,1487,301],{"class":247},[224,1489,305],{"class":304},[224,1491,308],{"class":247},[224,1493,665],{"class":237},[224,1495,289],{"class":247},[224,1497,1498,1500,1502,1504,1506,1508,1510],{"class":226,"line":258},[224,1499,697],{"class":247},[224,1501,355],{"class":237},[224,1503,301],{"class":247},[224,1505,360],{"class":304},[224,1507,308],{"class":247},[224,1509,1429],{"class":237},[224,1511,289],{"class":247},[224,1513,1514,1516,1518,1521,1524,1527,1530],{"class":226,"line":264},[224,1515,688],{"class":247},[224,1517,283],{"class":237},[224,1519,1520],{"class":237}," CHECK",[224,1522,1523],{"class":247}," (Age ",[224,1525,1526],{"class":237},">=",[224,1528,1529],{"class":304}," 0",[224,1531,683],{"class":247},[224,1533,1534,1537,1539,1541,1543,1545,1547],{"class":226,"line":277},[224,1535,1536],{"class":247},"    CountryCode ",[224,1538,675],{"class":237},[224,1540,301],{"class":247},[224,1542,680],{"class":304},[224,1544,308],{"class":247},[224,1546,1449],{"class":237},[224,1548,1549],{"class":1073}," 'CN'\n",[224,1551,1552],{"class":226,"line":292},[224,1553,317],{"class":247},[13,1555,79],{},[30,1557,1558,1564,1570,1576,1582],{},[33,1559,1560,1563],{},[61,1561,1562],{},"Id INT PRIMARY KEY","：主键，唯一且非空。",[33,1565,1566,1569],{},[61,1567,1568],{},"Name VARCHAR(50) NOT NULL","：姓名不能为空。",[33,1571,1572,1575],{},[61,1573,1574],{},"Email VARCHAR(100) UNIQUE","：邮箱不能重复。",[33,1577,1578,1581],{},[61,1579,1580],{},"Age INT CHECK (Age >= 0)","：年龄不能为负数。",[33,1583,1584,1587,1588,98],{},[61,1585,1586],{},"CountryCode CHAR(2) DEFAULT 'CN'","：不填时默认 ",[61,1589,785],{},[13,1591,1592],{},"外键示例：",[215,1594,1596],{"className":217,"code":1595,"language":219,"meta":220,"style":220},"CREATE TABLE Sales.Orders (\n    OrderId INT PRIMARY KEY,\n    CustId INT NOT NULL,\n    Amount DECIMAL(10,2) CHECK (Amount > 0),\n    FOREIGN KEY (CustId) REFERENCES Sales.Customers(Id)\n);\n",[61,1597,1598,1609,1620,1632,1664,1684],{"__ignoreMap":220},[224,1599,1600,1602,1604,1606],{"class":226,"line":227},[224,1601,63],{"class":237},[224,1603,269],{"class":237},[224,1605,244],{"class":243},[224,1607,1608],{"class":247},".Orders (\n",[224,1610,1611,1614,1616,1618],{"class":226,"line":234},[224,1612,1613],{"class":247},"    OrderId ",[224,1615,283],{"class":237},[224,1617,286],{"class":237},[224,1619,289],{"class":247},[224,1621,1622,1625,1627,1630],{"class":226,"line":251},[224,1623,1624],{"class":247},"    CustId ",[224,1626,283],{"class":237},[224,1628,1629],{"class":237}," NOT NULL",[224,1631,289],{"class":247},[224,1633,1634,1637,1640,1642,1645,1648,1650,1652,1654,1657,1660,1662],{"class":226,"line":258},[224,1635,1636],{"class":247},"    Amount ",[224,1638,1639],{"class":237},"DECIMAL",[224,1641,301],{"class":247},[224,1643,1644],{"class":304},"10",[224,1646,1647],{"class":247},",",[224,1649,680],{"class":304},[224,1651,308],{"class":247},[224,1653,1439],{"class":237},[224,1655,1656],{"class":247}," (Amount ",[224,1658,1659],{"class":237},">",[224,1661,1529],{"class":304},[224,1663,683],{"class":247},[224,1665,1666,1669,1672,1675,1677,1679,1681],{"class":226,"line":264},[224,1667,1668],{"class":237},"    FOREIGN KEY",[224,1670,1671],{"class":247}," (CustId) ",[224,1673,1674],{"class":237},"REFERENCES",[224,1676,244],{"class":304},[224,1678,340],{"class":247},[224,1680,387],{"class":304},[224,1682,1683],{"class":247},"(Id)\n",[224,1685,1686],{"class":226,"line":277},[224,1687,317],{"class":247},[13,1689,79],{},[30,1691,1692,1701,1714],{},[33,1693,1694,1697,1698,98],{},[61,1695,1696],{},"CustId"," 引用 ",[61,1699,1700],{},"Sales.Customers(Id)",[33,1702,1703,1704,1707,1708,1710,1711,1713],{},"插入 ",[61,1705,1706],{},"Orders"," 时，",[61,1709,1696],{}," 必须存在于 ",[61,1712,387],{}," 中。",[33,1715,1716],{},"删除或更新被引用行时，行为取决于外键规则。",[13,1718,1719,1720,1722],{},"通过 ",[61,1721,163],{}," 添加约束：",[215,1724,1726],{"className":217,"code":1725,"language":219,"meta":220,"style":220},"ALTER TABLE Sales.Orders\nADD CONSTRAINT fk_orders_customer\nFOREIGN KEY (CustId) REFERENCES Sales.Customers(Id);\n",[61,1727,1728,1741,1751],{"__ignoreMap":220},[224,1729,1730,1732,1734,1736,1738],{"class":226,"line":227},[224,1731,75],{"class":237},[224,1733,269],{"class":237},[224,1735,244],{"class":304},[224,1737,340],{"class":247},[224,1739,1740],{"class":304},"Orders\n",[224,1742,1743,1745,1748],{"class":226,"line":234},[224,1744,349],{"class":237},[224,1746,1747],{"class":237}," CONSTRAINT",[224,1749,1750],{"class":247}," fk_orders_customer\n",[224,1752,1753,1755,1757,1759,1761,1763,1765],{"class":226,"line":251},[224,1754,1410],{"class":237},[224,1756,1671],{"class":247},[224,1758,1674],{"class":237},[224,1760,244],{"class":304},[224,1762,340],{"class":247},[224,1764,387],{"class":304},[224,1766,1767],{"class":247},"(Id);\n",[13,1769,1770],{},"删除约束：",[215,1772,1774],{"className":217,"code":1773,"language":219,"meta":220,"style":220},"-- 标准写法\nALTER TABLE Sales.Orders\nDROP CONSTRAINT fk_orders_customer;\n",[61,1775,1776,1781,1793],{"__ignoreMap":220},[224,1777,1778],{"class":226,"line":227},[224,1779,1780],{"class":230},"-- 标准写法\n",[224,1782,1783,1785,1787,1789,1791],{"class":226,"line":234},[224,1784,75],{"class":237},[224,1786,269],{"class":237},[224,1788,244],{"class":304},[224,1790,340],{"class":247},[224,1792,1740],{"class":304},[224,1794,1795,1797,1799],{"class":226,"line":251},[224,1796,69],{"class":237},[224,1798,1747],{"class":237},[224,1800,1801],{"class":247}," fk_orders_customer;\n",[13,1803,79],{},[30,1805,1806,1809,1812],{},[33,1807,1808],{},"约束在插入或更新数据时自动检查。",[33,1810,1811],{},"约束用于保证数据的正确性、一致性和完整性。",[33,1813,1814,1815,98],{},"不同数据库删除约束语法可能不同，例如 MySQL 删除外键常用 ",[61,1816,1817],{},"DROP FOREIGN KEY",[13,1819,392],{},[30,1821,1822,1825,1828],{},[33,1823,1824],{},"防止非法数据进入表中。",[33,1826,1827],{},"保证表与表之间的引用关系。",[33,1829,1830],{},"减少应用层的数据校验负担。",[411,1832],{},[22,1834,1836],{"id":1835},"_87-本章核心记忆点","8.7 本章核心记忆点",[215,1838,1843],{"className":1839,"code":1841,"language":1842,"meta":220},[1840],"language-text","DDL 管结构：CREATE、ALTER、DROP。\nSchema 是逻辑容器，用于组织数据库对象。\nTable 实际存储数据，由行和列组成。\nView 是虚拟表，不存储数据，只保存查询定义。\nIndex 提高检索速度，但会增加维护成本。\nConstraints 强制数据完整性。\n","text",[61,1844,1841],{"__ignoreMap":220},[13,1846,1847],{},"本章只需要掌握：",[30,1849,1850,1853,1856,1865],{},[33,1851,1852],{},"DDL 做什么：定义和管理数据库对象结构。",[33,1854,1855],{},"四个核心对象：Schema、Table、View、Index。",[33,1857,1858,1859,91,1861,91,1863,98],{},"三个核心命令：",[61,1860,63],{},[61,1862,75],{},[61,1864,69],{},[33,1866,1867],{},"约束的作用：保证数据完整性。",[1869,1870,1871],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":220,"searchDepth":251,"depth":251,"links":1873},[1874,1875,1876,1877,1878,1879,1880],{"id":24,"depth":234,"text":25},{"id":415,"depth":234,"text":416},{"id":599,"depth":234,"text":600},{"id":991,"depth":234,"text":992},{"id":1204,"depth":234,"text":1205},{"id":1372,"depth":234,"text":1373},{"id":1835,"depth":234,"text":1836},"学习",null,"2026-10-10","MySQL 学习笔记第五篇：数据定义语言概览——Schema、Table、View、Index、Constraints 这几类对象分别对应哪些 CREATE \u002F ALTER \u002F DROP 命令。","md",false,{},"\u002Fposts\u002Fmysql\u002Fmysql-learning-05",{"title":5,"description":1884},"SQL 学习笔记","posts\u002Fmysql\u002Fmysql-learning-05",[1893,1894,1895],"SQL","MySQL","学习笔记","P5-OJcAf1U1pp_2xi3LtXVHZSg19O8YiFHIpTZZ_k2I",[1898,1905,1911,1917,1923,1929,1935,1941,1947,1953,1959,1965,1971,1977,1982,1987,1992,1997,2002,2007,2012,2017,2022,2027,2032,2037,2042,2047,2052,2058,2062,2066,2070,2074,2078,2082,2086,2090,2094,2098,2102,2108,2112,2116,2117,2121,2125,2129,2133,2137,2141,2146,2150,2154,2159,2164,2170,2174,2179,2183],{"path":1899,"title":1900,"description":1901,"date":1902,"series":1903,"seriesOrder":1904},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-28","软件分析与设计笔记 28：draw.io 作图手册：五张图的符号位置、落笔顺序与自检","不模拟软件界面，只讲清三件事：每个 UML 符号在 draw.io 里搜什么词、一张图该按什么顺序落笔、画完拿什么标准自查。覆盖用例图、活动图、顺序图、类图、界面草图五种图纸，末尾附「最容易画反的十二笔」总检表。","2026-11-19","软件分析与设计笔记",28,{"path":1906,"title":1907,"description":1908,"date":1909,"series":1903,"seriesOrder":1910},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-27","软件分析与设计笔记 27：Paper 1 应试：从读案例到交卷的一次完整演算","拿一份完整的案例，从头到尾走一遍：怎么读案例列角色、怎么在四个小问之间分配时间、每一张图从哪一句话推出来、两张表怎么填、交卷前拿什么清单自查。附 C25 真题与样卷的题型分值对照。","2026-11-18",27,{"path":1912,"title":1913,"description":1914,"date":1915,"series":1903,"seriesOrder":1916},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-26","软件分析与设计笔记 26：总结：把整条链路串起来","系列收尾：从需求到代码的完整链路回顾、每一环的产出与验收方式、六条贯穿全系列的原则，以及一份可以直接拿去做项目自查的清单。","2026-11-17",26,{"path":1918,"title":1919,"description":1920,"date":1921,"series":1903,"seriesOrder":1922},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-25","软件分析与设计笔记 25：代码重构：坏味道与手法","重构不改变外部行为、只改善内部结构：四种常见坏味道与对应手法、为什么动手之前必须先有测试、什么时候该重构，以及重构和前面那些设计模型是什么关系。","2026-11-16",25,{"path":1924,"title":1925,"description":1926,"date":1927,"series":1903,"seriesOrder":1928},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-24","软件分析与设计笔记 24：设计原则：内聚、耦合与多态","好设计怎么衡量：内聚与耦合分别在说什么、一次从「差设计」到「多态重设计」的完整对照、抽象类与接口的选择依据，以及复用为什么会从优势变成风险。","2026-11-15",24,{"path":1930,"title":1931,"description":1932,"date":1933,"series":1903,"seriesOrder":1934},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-23","软件分析与设计笔记 23：设计建模：从对象模型到能实现的方案","分析模型能用但还不能直接开工：对象模型怎么映射到关系模型、继承映射的三种方案怎么选、数据访问层与 Data Broker 解决什么问题，以及三层架构与 MVC 的分工。","2026-11-14",23,{"path":1936,"title":1937,"description":1938,"date":1939,"series":1903,"seriesOrder":1940},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-22","软件分析与设计笔记 22：分析建模：边界、实体与控制对象","不经过分析直接写代码会踩什么坑、三种分析对象各管一段、怎么用顺序图完成一次用例实现，以及从顺序图导出类的属性、操作与关系的方法。","2026-11-13",22,{"path":1942,"title":1943,"description":1944,"date":1945,"series":1903,"seriesOrder":1946},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-21","软件分析与设计笔记 21：UML：类图与顺序图","为什么需要一种共同的画法：类符号三格怎么画、五种关系的符号与设计含义、每种关系落到 Java 是什么写法，顺序图的三要素怎么摆；以及这三种最容易找不到的符号在 draw.io 里各搜什么词。","2026-11-12",21,{"path":1948,"title":1949,"description":1950,"date":1951,"series":1903,"seriesOrder":1952},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-20","软件分析与设计笔记 20：面向对象概念：对象、关系与多态","面向对象不是「用某个语言写代码」：对象与类的区别、封装真正在保护什么、五种关系（依赖、关联、聚合、组合、继承）各自何时用，以及多态为什么能减少条件判断。","2026-11-11",20,{"path":1954,"title":1955,"description":1956,"date":1957,"series":1903,"seriesOrder":1958},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-19","软件分析与设计笔记 19：规范化与逻辑数据模型","一次改地址引发的数据不一致，讲清规范化的真正动机；UNF 到 3NF 每一步在解决什么问题，派生字段为什么不能存，优化为什么和规范化方向相反，以及逻辑数据模型在 3NF 之上补了什么。","2026-11-10",19,{"path":1960,"title":1961,"description":1962,"date":1963,"series":1903,"seriesOrder":1964},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-18","软件分析与设计笔记 18：数据库分析：实体、关系与数据字典","为什么不能拿到需求就动手建表：实体与关系怎么判定、基数为什么必须由业务方确认、数据命名要遵守什么规则，以及数据字典四列里最容易被空着的那一列。","2026-11-09",18,{"path":1966,"title":1967,"description":1968,"date":1969,"series":1903,"seriesOrder":1970},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-17","软件分析与设计笔记 17：用生成式 AI 做设计与开发：能用的场景与要防的坑","生成式 AI 在工作流里真正站得住的三个场景 —— 造示例数据、解释陌生代码、起草初稿；它为什么会复现社会偏见、为什么会编得像真的，以及哪些内容绝不能直接采用。","2026-11-08",17,{"path":1972,"title":1973,"description":1974,"date":1975,"series":1903,"seriesOrder":1976},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-16","软件分析与设计笔记 16：从 persona 到 URS：一份交付物的完整骨架","把前面十几篇串成一份能交出去的东西：用户需求规格说明书的九个部分、每一章来自哪个环节、由谁确认，以及面向决策者的提案该讲清哪三件事。","2026-11-07",16,{"path":1978,"title":1979,"description":1980,"date":1981,"series":1903,"seriesOrder":376},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-15","软件分析与设计笔记 15：非功能需求：把「快、稳、安全」变成数字","为什么「系统要快」不是一条需求：非功能需求怎么量化，决定性能的用户量、交易量、数据量三张表怎么估，安全需求要写清什么，以及可靠性的「不可用」该怎么定义。","2026-11-06",{"path":1983,"title":1984,"description":1985,"date":1986,"series":1903,"seriesOrder":370},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-14","软件分析与设计笔记 14：软件测试：层级、方法与等价类划分","「我们测过了」这句话问题在哪：为什么静态评审和动态测试缺一不可，五个测试层级各自验证什么，白盒与黑盒的差别，以及用等价类划分和边界值把无限输入变成有限用例的方法。","2026-11-05",{"path":1988,"title":1989,"description":1990,"date":1991,"series":1903,"seriesOrder":365},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-13","软件分析与设计笔记 13：需求获取：五种调查方法与一场访谈","需求从哪里来：五种事实调查方法各自适合回答什么、代价是什么，访谈从准备到记录的全过程，问卷设计里最容易犯的错，以及访谈记录必须写下来的那几项信息。","2026-11-04",{"path":1993,"title":1994,"description":1995,"date":1996,"series":1903,"seriesOrder":346},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-12","软件分析与设计笔记 12：前端设计：把流程变成屏幕","界面设计不是「画得好看」：从活动图走到屏幕的三步，CRUD 任务流怎么当检查表，界面必须回答的三个问题，信息架构与五种导航类型，视觉一致性与留白，以及移动端与 Web 端的差别。","2026-11-03",{"path":1998,"title":1999,"description":2000,"date":2001,"series":1903,"seriesOrder":331},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-11","软件分析与设计笔记 11：Agentic AI 与业务流程自动化","AI agent 到底是什么：五项能力与四个核心组件，什么场景该用定时任务、什么该用程序、什么才值得用 agent，两种实现路径的差别，必须提前防住的四类失败模式，以及设计方法从提示词到编排的演进。","2026-11-02",{"path":2003,"title":2004,"description":2005,"date":2006,"series":1903,"seriesOrder":325},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-10","软件分析与设计笔记 10：精炼用例模型：include、extend 与泛化","三种精炼用例关系的判断标准：include 什么时候用、它和 extend 的区别到底在哪、参与者泛化与用例泛化各解决什么问题，以及精炼到什么程度就该停手。","2026-11-01",{"path":2008,"title":2009,"description":2010,"date":2011,"series":1903,"seriesOrder":320},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-09","软件分析与设计笔记 09：功能需求（二）：从流程到业务实体","活动图画完之后，怎么从流程里筛出真正的业务实体：三条判断标准、哪些名词其实不该建实体、属性从哪里来，以及领域模型和后面的数据模型分别负责什么。","2026-10-31",{"path":2013,"title":2014,"description":2015,"date":2016,"series":1903,"seriesOrder":314},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-08","软件分析与设计笔记 08：功能需求（一）：用例模型与活动图","从用户故事到用例的翻译过程：什么才算「好」的参与者，系统边界怎么划，用例描述必须写清哪四件事，活动图怎么把分支、并行与泳道画清楚，以及这两个图在 draw.io 里各用哪个形状、最容易画错哪一笔。","2026-10-30",{"path":2018,"title":2019,"description":2020,"date":2021,"series":1903,"seriesOrder":292},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-07","软件分析与设计笔记 07：用户故事：把需求写成可验收的一句话","用户故事的三段结构，怎么从用户画像和数据地图里把它提取出来，一条故事多大算合适、时序为什么也是需求的一部分，以及验收标准怎么写才算真的可验收。","2026-10-29",{"path":2023,"title":2024,"description":2025,"date":2026,"series":1903,"seriesOrder":277},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-06","软件分析与设计笔记 06：范围界定（数据侧）：用数据校验你的判断","访谈结论和数字对不上时该怎么办：分析的四个层次分别在回答什么问题、为什么不能跳级、数据准备与搜集怎么做成一张应用地图，以及数据最容易在哪几个地方骗你。","2026-10-28",{"path":2028,"title":2029,"description":2030,"date":2031,"series":1903,"seriesOrder":264},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-05","软件分析与设计笔记 05：范围界定（用户侧）：用户画像与客户旅程图","为什么「所有用户」是一个陷阱，项目边界该怎么划，用户画像要写哪五个要素、最容易写成什么废纸，客户旅程图怎么把阶段、想法和情绪画在同一张纸上，以及怎么从这两样东西一步步推到可验证的需求。","2026-10-27",{"path":2033,"title":2034,"description":2035,"date":2036,"series":1903,"seriesOrder":258},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-04","软件分析与设计笔记 04：接手陌生案例的第一步：三问与一张表","拿到一个完全陌生的业务案例，怎么从零开始不跑偏：只问 Who、What、Why 三个问题，把「问题—事实—假设—理由」记成一张四列表，说清为什么假设必须写明理由，以及带着问题进访谈为什么比空手去有效得多。","2026-10-26",{"path":2038,"title":2039,"description":2040,"date":2041,"series":1903,"seriesOrder":251},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-03","软件分析与设计笔记 03：Agile 与 Scrum：迭代、角色与产出物","从「三周做完交付，客户说这不是我要的」讲起，说清瀑布式与迭代式的根本差别，Scrum 的三个角色和三种产出物，一个 sprint 里四次固定活动各自在解决什么问题，以及敏捷里最常见的几个误解。","2026-10-25",{"path":2043,"title":2044,"description":2045,"date":2046,"series":1903,"seriesOrder":234},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-02","软件分析与设计笔记 02：设计思维、用户驱动与数据驱动","从「客服要一个能一次看完所有排期的界面」这个翻车案例讲起，说清设计思维到底是什么、用户驱动与数据驱动各自能看见什么又看不见什么、为什么真正的落点是把两者合起来的 data-informed design，以及访谈中怎么问出有用的信息。","2026-10-24",{"path":2048,"title":2049,"description":2050,"date":2051,"series":1903,"seriesOrder":227},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-01","软件分析与设计笔记 01：课程地图与从需求到设计的主干","这一篇不写具体方法，先把整条链路铺开：软件分析与设计到底要解决什么问题，从需求到设计分成哪两段，中间有哪十几个环节，一份完整的交付物里应该有什么，以及后面 27 篇笔记怎么排、新人该按什么顺序读。","2026-10-23",{"path":2053,"title":2054,"description":2055,"date":2056,"series":2057,"seriesOrder":227},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-01","Spring 学习笔记 01：IoC、依赖注入与第一个 Spring Boot 应用","从「手写 new 出来的三层结构」的痛点讲起，说清 IoC 容器、Bean 与依赖注入是怎么回事，再用 Maven 与 Spring Initializr 跑起第一个能返回 JSON 的应用。","2026-10-15","Spring 学习笔记",{"path":2059,"title":2060,"description":2061,"date":2056,"series":2057,"seriesOrder":234},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-02","Spring 学习笔记 02：Spring Data JPA 基础——实体映射与 Repository","用 ORM 把类映射到表：@Entity、@Id、@GeneratedValue 怎么用，CrudRepository 三层接口怎么选，H2 与 MySQL 怎么配，以及 ddl-auto 到底该写哪个值。",{"path":2063,"title":2064,"description":2065,"date":2056,"series":2057,"seriesOrder":251},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-03","Spring 学习笔记 03：JPA 查询——派生方法、JPQL 与分页排序","Repository 自带的方法只够按主键查，这篇讲三种自己造查询的方式：方法名派生、@Query 写 JPQL、原生 SQL，以及 Pageable 分页排序和投影返回。",{"path":2067,"title":2068,"description":2069,"date":2056,"series":2057,"seriesOrder":258},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-04","Spring 学习笔记 04：JPA 关联映射与仓储测试","一对多、多对多怎么映射，谁负责维护外键，FetchType 与 CascadeType 该怎么选，顺带用 @DataJpaTest 与 AssertJ 把仓储层测起来。",{"path":2071,"title":2072,"description":2073,"date":2056,"series":2057,"seriesOrder":264},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-05","Spring 学习笔记 05：Spring MVC 与 Thymeleaf 入门","一次页面请求在 Spring MVC 里走了哪几步，@Controller 怎么把数据交给模板，@PathVariable 与 @RequestParam 怎么取参数，以及控制器为什么必须是无状态的。",{"path":2075,"title":2076,"description":2077,"date":2056,"series":2057,"seriesOrder":277},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-06","Spring 学习笔记 06：表单绑定与服务端校验","把表单字段绑到对象上，用 Bean Validation 注解做服务端校验，把错误信息显示回用户刚填的那一页，再补上自定义校验注解与全局异常处理。",{"path":2079,"title":2080,"description":2081,"date":2056,"series":2057,"seriesOrder":292},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-07","Spring 学习笔记 07：Thymeleaf 片段复用与国际化","用 th:fragment 与 th:insert\u002Fth:replace 把导航栏、页脚抽成片段，页面套用统一布局，再用 messages.properties 与 LocaleResolver 做中英文切换。",{"path":2083,"title":2084,"description":2085,"date":2056,"series":2057,"seriesOrder":314},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-08","Spring 学习笔记 08：HTTP Session 与会话状态管理","HTTP 无状态带来的问题，Cookie 与 Session 怎么分工，Spring 里读写会话的几种方式，以及会话固定、超时、多实例共享这些必须想清楚的事。",{"path":2087,"title":2088,"description":2089,"date":2056,"series":2057,"seriesOrder":320},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-09","Spring 学习笔记 09：拦截器 HandlerInterceptor","登录检查、权限判断、请求耗时统计这类横切逻辑该放哪：HandlerInterceptor 的三个回调各在什么时机执行，怎么注册与排除路径，以及它和过滤器的分工。",{"path":2091,"title":2092,"description":2093,"date":2056,"series":2057,"seriesOrder":325},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-10","Spring 学习笔记 10：Service 层与事务","一组数据库操作要么全成功要么全失败，靠 @Transactional 怎么做到；传播行为、隔离级别、回滚规则怎么选，以及自调用失效、乐观锁悲观锁这些实战里的坑。",{"path":2095,"title":2096,"description":2097,"date":2056,"series":2057,"seriesOrder":331},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-11","Spring 学习笔记 11：REST API 基础——把 Service 暴露成接口","同一套 Service 怎么同时服务页面和客户端：@RestController 的路由与方法语义、状态码怎么给、DTO 怎么定，以及 MockMvc 端到端和切片测试的两种写法与各自的坑。",{"path":2099,"title":2100,"description":2101,"date":2056,"series":2057,"seriesOrder":346},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-12","Spring 学习笔记 12：REST 进阶——版本、更新、跨域与文档化","接口能跑通之后要处理的几件事：URL 与响应结构怎么定、版本怎么演进、更新怎么做到可安全重试、CORS 怎么配、HATEOAS 与 Spring Data REST 该不该用。",{"path":2103,"title":2104,"description":2105,"date":2106,"series":2107,"seriesOrder":258},"\u002Fposts\u002Fjava\u002Fjava-functionalprogramming-notes","Java 函数式编程笔记：Lambda、函数式接口与 Streams","学习 Java 函数式编程时的个人笔记：Lambda 表达式的五步简写与方法引用、常见函数式接口、Stream 流水线与惰性求值，以及创建流、中间操作、终止操作与收集器的用法。示例代码均为自写，运行结果来自本地实测。","2026-10-13","Java 学习笔记",{"path":2109,"title":2110,"description":2111,"date":2106,"series":2107,"seriesOrder":251},"\u002Fposts\u002Fjava\u002Fjava-generics-notes","Java 泛型笔记：泛型方法、有界类型与泛型类","学习 Java 泛型时的个人笔记：从重复的重载方法与多态尝试讲起，再到泛型方法与类型推断、有界泛型类型、Comparable 与 Number 边界，以及泛型类在集合中的用法。示例代码均为自写，运行结果来自本地实测。",{"path":2113,"title":2114,"description":2115,"date":1883,"series":1890,"seriesOrder":258},"\u002Fposts\u002Fmysql\u002Fmysql-learning-04","MySQL 学习笔记 04：数据操纵（增删改）","MySQL 学习笔记第四篇：INSERT 插入（含批量插入与 INSERT ... SELECT）、UPDATE 更新、DELETE 删除，以及各自的坑。",{"path":1888,"title":5,"description":1884,"date":1883,"series":1890,"seriesOrder":264},{"path":2118,"title":2119,"description":2120,"date":1883,"series":1890,"seriesOrder":277},"\u002Fposts\u002Fmysql\u002Fmysql-learning-06","MySQL 学习笔记 06：CREATE TABLE 与数据类型","MySQL 学习笔记第六篇：CREATE TABLE 的完整语法、常用数据类型的选型建议，以及外键的两种定义方式。",{"path":2122,"title":2123,"description":2124,"date":1883,"series":1890,"seriesOrder":292},"\u002Fposts\u002Fmysql\u002Fmysql-learning-07","MySQL 学习笔记 07：索引","MySQL 学习笔记第七篇：索引的作用与 B+ 树结构、单列与复合索引的创建、索引的代价与适用场景。",{"path":2126,"title":2127,"description":2128,"date":1883,"series":1890,"seriesOrder":314},"\u002Fposts\u002Fmysql\u002Fmysql-learning-08","MySQL 学习笔记 08：DROP 与 ALTER","MySQL 学习笔记第八篇：DROP 删除数据库对象、ALTER 修改表结构，以及常见的坑。",{"path":2130,"title":2131,"description":2132,"date":1883,"series":1890,"seriesOrder":320},"\u002Fposts\u002Fmysql\u002Fmysql-learning-09","MySQL 学习笔记 09：约束与数据完整性","MySQL 学习笔记第九篇：SQL 约束——NOT NULL、CHECK、PRIMARY KEY、FOREIGN KEY 等如何保证数据完整性，以及它们的对比。",{"path":2134,"title":2135,"description":2136,"date":1883,"series":1890,"seriesOrder":325},"\u002Fposts\u002Fmysql\u002Fmysql-learning-10","MySQL 学习笔记 10：视图","MySQL 学习笔记第十篇：视图（Views）的定义与特性、和表的对比、创建与使用，以及可更新视图的限制。",{"path":2138,"title":2139,"description":2140,"date":1883,"series":1890,"seriesOrder":331},"\u002Fposts\u002Fmysql\u002Fmysql-learning-11","MySQL 学习笔记 11：存储过程","MySQL 学习笔记第十一篇：存储过程（Stored Procedures）的概念、创建与调用、带参数的写法，以及优缺点。",{"path":2142,"title":2143,"description":2144,"date":2145,"series":1890,"seriesOrder":227},"\u002Fposts\u002Fmysql\u002Fmysql-learning-01","MySQL 学习笔记 01：MySQL 基础知识","MySQL 学习笔记第一篇：MySQL Server 与 Workbench 的安装，数据库与 DBMS 的基本概念，关系模型、ACID 事务、常见数据类型，以及后续的学习路线。","2026-10-09",{"path":2147,"title":2148,"description":2149,"date":2145,"series":1890,"seriesOrder":234},"\u002Fposts\u002Fmysql\u002Fmysql-learning-02","MySQL 学习笔记 02：SELECT 查询与过滤","MySQL 学习笔记第二篇：SELECT 的基本语法与逻辑执行顺序，WHERE 过滤（比较、LIKE、IN、BETWEEN、NULL）、各种 JOIN、UNION 与子查询。",{"path":2151,"title":2152,"description":2153,"date":2145,"series":1890,"seriesOrder":251},"\u002Fposts\u002Fmysql\u002Fmysql-learning-03","MySQL 学习笔记 03：聚合、分组与输出控制","MySQL 学习笔记第三篇：COUNT\u002FSUM\u002FAVG 等聚合函数、GROUP BY 分组、HAVING 过滤、ORDER BY 与 LIMIT，以及一条 SELECT 的完整逻辑执行顺序。",{"path":2155,"title":2156,"description":2157,"date":2158,"series":2107,"seriesOrder":234},"\u002Fposts\u002Fjava\u002Fjava-oop-notes","Java 面向对象笔记：类、继承、多态与异常","学习 Java 面向对象编程时的个人笔记：类与对象、封装与访问修饰符、继承与多态、集合、抽象类与接口、异常处理。示例代码均为自写，运行结果来自本地实测。","2026-10-06",{"path":2160,"title":2161,"description":2162,"date":2163,"series":2107,"seriesOrder":227},"\u002Fposts\u002Fjava\u002Fjava-basics-notes","Java 基础语法笔记：从环境安装到方法与数组","学习 Java 基础语法时的个人笔记：JDK 安装、输入输出、变量与运算符、条件与循环、字符串、数组与方法。示例代码均为自写，运行结果来自本地实测。","2026-10-05",{"path":2165,"title":2166,"description":2167,"date":2168,"series":2169,"seriesOrder":227},"\u002Fposts\u002Fgit\u002Fgit-install-and-basics","Git 安装与基本使用","从装好 Git 到跑通日常提交流程，把最常用的几条命令和它们背后的三个区域讲清楚。","2026-10-04","Git 入门",{"path":2171,"title":2172,"description":2173,"date":2168,"series":2169,"seriesOrder":234},"\u002Fposts\u002Fgit\u002Flocal-remote-repository","本地远程仓库的部署","用自己的机器当 Git 服务器：建一个裸仓库、走 SSH 连上去，把本地提交推上去。",{"path":2175,"title":2176,"description":2177,"date":2168,"series":2178,"seriesOrder":227},"\u002Fposts\u002Fguide\u002Fguide-file-layout","文件都放在哪","文章、图片、封面分别放在仓库的什么位置，哪些目录可以放手改、哪些碰了会出问题。","博客使用指南",{"path":2180,"title":2181,"description":2182,"date":2168,"series":2178,"seriesOrder":234},"\u002Fposts\u002Fguide\u002Fguide-frontmatter","frontmatter 每个字段是什么意思","文章开头那段被横线包住的字段，逐个说明作用、默认行为和写错的后果。",{"path":2184,"title":2185,"description":2186,"date":2168,"series":2178,"seriesOrder":251},"\u002Fposts\u002Fguide\u002Fguide-markdown","正文怎么写 —— Markdown 与排版效果","标题、链接、图片、代码、表格分别怎么写，以及本站对它们做了哪些自定义处理。",1793268153563]