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