简介:本资源是《数据库原理(第四版)》配套教学课件,面向高校计算机、软件工程及信息管理等专业本科生,以及数据库初学者与从业技术人员,系统解决数据库基础理论与核心模型理解难题。课件以PPT格式呈现,共1个文件,大小289KB,内容精炼、图文并茂,涵盖从第一章绪论到第十章的完整知识脉络,重点深入讲解数据模型体系,尤其对网状模型的数据结构(多父节点、记录类型与字段定义)、数据操纵(查询/插入/删除/更新)、完整性约束(DBTG规范)、存储结构及优缺点进行详实剖析,并辅以学生-宿舍-教师、家庭关系等典型实例图示。目前已有168人学习下载,适合课堂预习复习、自学夯实基础或作为数据库设计与优化进阶学习的理论支点。
1. 网状模型到底是什么:一个“多对多关系”的老派解法,为什么今天还要懂它?
想象你整理家谱——爷爷有两个儿子(爸爸和叔叔),爸爸又有两个孩子(你和弟弟),而叔叔也收养了一个孩子。这时,那个被收养的孩子,既没有生物学上的父亲,又同时有两位法律意义上的长辈。再比如,一个学生可以属于多个社团,一个社团里也有多个学生;一位导师指导多名研究生,而一名研究生也可能同时接受两位导师的联合指导。这些“你中有我、我中有你”的关系,用一根根单向树杈(像公司组织架构图那样从上到下)根本画不完——树只能有一个根,但现实世界里,人、事、物的关系常常是网状的。
网状模型,就是数据库发展早期为解决这类“多父多子”关系而设计的一套数据组织方式。它不像后来流行的关系模型那样靠表格和SQL说话,而是用“节点”(代表实体,如学生、课程、教师)和“连线”(代表联系,如“选修”“指导”“隶属”)搭出一张张真实世界的逻辑蛛网。它诞生于20世纪60年代末,是DBTG(数据库任务组)提出的工业级标准,曾支撑过银行核心账务、航空订票等关键系统。今天虽然主流数据库几乎都基于关系模型,但理解网状模型,就像学书法要临《兰亭序》——不是为了照着写,而是看清“数据如何自然生长”的原始逻辑。它帮你一眼识别哪些业务场景天然带“网状基因”,也让你在读老系统文档、做遗产系统迁移、甚至理解图数据库底层思想时,少走三年弯路。
2. 网状模型怎么工作:从“结点-连线”到“存取路径”,一套自成体系的规则
2.1 数据结构:不是表格,也不是树,而是一张可导航的“关系地图”
网状模型不预设全局统一的表结构,它的基本单元是记录类型(Record Type)和系(Set)。
- 记录类型就是现实中的实体类别,比如“学生”“课程”“教师”。每个记录类型包含若干字段(Field),如学生的学号、姓名、专业。
- 系(Set)是网状模型的灵魂,它定义了两个记录类型之间的一对多联系。例如,“学生-选课”是一个系:一个学生可以选多门课,但一门课的选课记录里,只属于一个学生(注意:这里“一门课”是课程记录,“选课记录”是另一个独立的记录类型,用于承载关联)。
提示:网状模型中,“多对多”关系不能直接表达,必须拆解。比如“学生↔课程”是多对多,就需引入第三个记录类型“选课”,并建立两个系:“学生-选课”和“课程-选课”。这就像现实中要登记一次选课行为,得填一张表,而不是直接把学生和课程拉手。
下面这段伪代码式结构描述,展示了某高校教务系统中“教师-教研室-课程”的网状关系:
RECORD TYPE 教师 FIELD 教师编号 CHAR(10) FIELD 姓名 CHAR(20) FIELD 职称 CHAR(10) RECORD TYPE 教研室 FIELD 教研室编号 CHAR(10) FIELD 名称 CHAR(30) RECORD TYPE 课程 FIELD 课程编号 CHAR(10) FIELD 名称 CHAR(50) /* 定义两个系:一个教师可属多个教研室(多对多拆解),一个教研室可开多门课 */ SET 教师_所属_教研室 OWNER 教师 MEMBER 教研室 SET 教研室_开设_课程 OWNER 教研室 MEMBER 课程这段定义意味着:
- 一位教师(Owner)可以出现在多个“教师_所属_教研室”系中,对应多个教研室(Member);
- 一个教研室(Owner)也可以出现在多个“教研室_开设_课程”系中,对应多门课程(Member);
- 但每个“教研室_开设_课程”实例里,只绑定一个教研室和一门课程——这是网状模型强制的“一对多”原子性。
这种结构让数据天然支持“从A出发,顺着连线走到B,再走到C”的链式访问。比如查“张老师教的所有课程”,系统会:
① 找到张老师的记录 →
② 遍历他参与的所有“教师_所属_教研室”系 →
③ 对每个教研室,遍历其“教研室_开设_课程”系 →
④ 拿到全部课程记录。
整个过程不依赖全局索引或SQL解析器,而是靠预定义的物理指针链,所以当年性能极快——但也正因如此,路径一旦写错,结果就全偏。
2.2 数据操纵:不是“写语句”,而是“走指针”的四步操作
在网状模型中,增删改查不是靠声明式语言(如SELECT * FROM ...),而是靠一组导航式命令,本质是移动游标、修改指针。以CODASYL标准为例,核心操作只有四个动词,但每一步都需明确当前位于哪个记录、要进入哪个系:
| 操作 | 典型命令(类COBOL语法) | 实际含义 | 关键约束 |
|---|---|---|---|
| 查询 | FIND STUDENT WITH KEY '2023001' | 定位到学号为2023001的学生记录 | 必须先有主键字段(码字段) |
| 进入系 | FIND NEXT COURSE IN SET 教研室_开设_课程 | 从当前教研室记录,跳到它开设的第一门课程 | 只能沿预定义的系方向走 |
| 插入 | STORE NEW COURSE+CONNECT COURSE TO SET 教研室_开设_课程 | 先存新课程记录,再把它挂到某个教研室下 | 新记录必须属于且仅属于一个Owner |
| 删除 | DISCONNECT COURSE FROM SET 教研室_开设_课程+ERASE COURSE | 先断开连接,再物理删除 | 若该课程还被其他教研室开设,必须逐个断开 |
看一个真实教学场景的操作序列(模拟IDMS系统):
* 步骤1:定位教研室“人工智能实验室” FIND FIRST JIAOYANSHI WITH KEY 'AI-LAB' * 步骤2:为其新增一门课“大模型原理” STORE NEW KECHENG WITH KEY 'LLM-PRIN' NAME '大模型原理' * 步骤3:将这门课挂到该教研室下(建立系实例) CONNECT KECHENG TO SET JIAOYANSHI_KAISHI_KECHENG * 步骤4:验证——查该教研室所有课程 FIND FIRST KECHENG IN SET JIAOYANSHI_KAISHI_KECHENG PERFORM UNTIL END OF SET DISPLAY KECHENG-NAME FIND NEXT KECHENG IN SET JIAOYANSHI_KAISHI_KECHENG END-PERFORM这段代码没有WHERE、没有JOIN、没有ORDER BY,全是“找到→连上→遍历”的机械动作。好处是执行路径完全可控,坏处是业务逻辑和数据结构深度耦合——换一种查询需求(比如“查所有开‘大模型原理’的教研室”),就得重写一整套导航逻辑,无法复用。
2.3 完整性约束:不是“规则引擎”,而是“结构契约”的硬性条款
网状模型的完整性,不靠事后校验,而靠建模时就写死的结构契约。DBTG标准定义了五类核心约束,它们像钢筋一样嵌在数据定义里,运行时由数据库内核强制执行:
码字段(Key Field)约束
每个记录类型必须指定一个唯一标识字段(如学生表的“学号”)。插入时若重复,系统直接报错;删除时若未指定KEY,操作被拒绝。这比关系模型的PRIMARY KEY更刚性——它不允许NULL,也不允许组合键,必须是单字段、非空、全局唯一。系的父子约束(Owner-Member Integrity)
在一个系中,“Owner”记录必须存在,才能插入“Member”记录。比如没创建教研室前,绝不允许往“教研室_开设_课程”里加课程。但反过来,删除教研室时,系统默认不级联删除其开设的课程——课程记录依然存在,只是失去归属。这是网状模型“高自由度”的双刃剑:避免误删,但也留下孤儿数据。属籍类别(Currency)约束
每个程序在操作时,都有一个“当前上下文”(Current of Set),比如当前正处在“教师_所属_教研室”系的第3个实例中。所有后续操作(如FIND NEXT)都以此为起点。这个“当前点”必须显式维护,一旦游标丢失(如异常中断),整个事务可能卡死——这是早期开发者最头疼的“玄学问题”。加入/移出类别(Insertion/Deletion Mode)
系可声明成员记录的生命周期规则:AUTOMATIC:插入Owner时,自动创建一个Member(如新建教研室,自动配一个默认课程);MANDATORY:删除Owner前,必须先手动清空所有Member(如删教研室前,必须先取消所有开课);OPTIONAL:Member可独立存在,与Owner解耦(如课程可先建好,等教研室成立后再挂上去)。
这些模式在DDL中写死,运行时不可更改,迫使设计者在建模阶段就想清业务规则。
路径依赖性(Path-Dependent Meaning)
同一条记录,在不同路径下含义不同。比如“课程编号=LLM-PRIN”的记录,从“教研室_开设_课程”路径访问,表示“AI-LAB开设的课”;若从另一条“教师_讲授_课程”路径访问,则表示“李教授主讲的课”。记录本身不携带上下文,它的意义完全由你怎么走到它决定。这导致同一个查询需求,若导航路径写错,结果可能天差地别——堪称数据库界的“薛定谔的课程”。
3. 网状模型 vs 其他模型:三张图看懂为什么它“难用但深刻”
3.1 和层次模型:网状是“解放了的树”,但自由带来复杂
层次模型像一棵严格的家谱树:每个节点(除根外)有且仅有一个父节点,结构清晰如金字塔。网状模型则像把多棵树的枝干剪下来,互相嫁接成一片森林——它保留了树的“父子”骨架,但允许:
- 多根共存:没有强制的唯一根节点,可以同时存在“学生根”“课程根”“教师根”;
- 多父同体:一个学生记录,既能挂在“院系”下,也能挂在“奖学金评定组”下;
- 复合联系:两个节点间可定义多种系,如“学生-选课”“学生-助教”“学生-实习单位”,每种联系独立存在。
举个例子:某高校的“跨学科培养计划”,要求学生同时归属本学院和合作企业。层次模型只能选一个作为父节点(比如硬塞进“学院”下),而网状模型直接建两个系:“学生-所属学院”和“学生-签约企业”,天然贴合业务。
但代价是:层次模型的查询路径唯一(从根往下找),而网状模型需程序员自己规划路径。就像开车导航,层次模型只有一条高速路,网状模型却给你开放了所有乡间小道——路多了,迷路概率也直线上升。
3.2 和关系模型:一个是“手工织网”,一个是“自动编筐”
关系模型的核心是关系(Relation),即二维表。所有操作基于集合论,用SQL声明“我要什么”,数据库自己优化“怎么拿”。网状模型则是导航式访问,用命令告诉系统“我从哪出发、经过哪、到哪去”。
| 维度 | 网状模型 | 关系模型 |
|---|---|---|
| 数据组织 | 记录类型 + 系(指针链) | 表(行+列)+ 主外键约束 |
| 查询方式 | FIND...IN SET...(过程式) | SELECT...FROM...WHERE...(声明式) |
| 多对多实现 | 必须引入中间记录类型(如“选课”) | 直接用外键关联两张表,或通过JOIN隐式处理 |
| 数据独立性 | 低:应用逻辑与存储结构强耦合(改一个系,全代码重写) | 高:SQL屏蔽物理存储细节,表结构调整不影响大部分查询 |
| 学习曲线 | 陡峭:需理解指针、系、属籍等抽象概念 | 平缓:表格思维直观,SQL语法接近自然语言 |
一个血泪经验:某高校教务系统曾用网状模型开发,上线后业务方提出新需求——“查所有选了‘数据库原理’且绩点>3.5的学生”。开发组花了两周:先定位课程记录,再遍历所有选课记录,再关联学生记录,再过滤绩点……而同样需求,用关系模型只需一行SQL:
SELECT s.name, s.gpa FROM students s JOIN enrollment e ON s.id = e.student_id JOIN courses c ON e.course_id = c.id WHERE c.name = '数据库原理' AND s.gpa > 3.5;网状模型的“精确控制”在此刻成了负资产——它把简单问题复杂化了。
3.3 和图数据库:一个是“协议时代的网”,一个是“互联网时代的图”
常有人问:“网状模型是不是就是图数据库的前身?”答案是:形似神异。两者都用“节点-边”建模,但底层哲学截然不同:
- 网状模型是强模式、强事务、强导航的封闭系统。所有节点类型、边类型、约束规则,必须在建库前用DDL严格定义;所有操作必须按预设路径执行;事务保证ACID,但扩展性差,难以分布式。
- 图数据库(如Neo4j)是弱模式、声明式、云原生的开放生态。节点/边可动态添加属性;用Cypher语言写
MATCH (s:Student)-[r:ENROLLED]->(c:Course)即可模糊匹配;天然支持水平扩展,能处理千亿级关系。
打个比方:网状模型像上世纪的电话总机——接线员(DBA)必须提前布好所有线路(系),用户拨号(执行命令)只能走固定线路;图数据库则像微信——任何人随时加好友(建节点)、发消息(建关系),搜索“共同好友”无需知道后台怎么连,系统自动算。
所以,今天学网状模型,不是为了替代图数据库,而是为了读懂那些仍在服役的金融、电信老系统,或是理解“为什么现代图数据库要刻意避开网状模型的某些设计”——比如,Neo4j坚决不用“Owner-Member”这种单向强制关系,而是让所有关系双向可查,正是吸取了网状模型路径僵化的教训。
4. 常见误区与易混概念:初学者最容易踩的五个坑
4.1 误区一:认为“网状模型支持多对多”,其实它只支持“一对多的组合”
易混点:看到网状模型能表达“学生选多门课、课程被多个学生选”,就以为它原生支持多对多。
为什么混:教材图示常把“学生-选课-课程”画成三角形,视觉上像多对多;实际建模时却要求拆成两个一对多系。
怎么区分:记住一个铁律——网状模型中,任何系(Set)的OWNER和MEMBER之间,永远是一对多。所谓“多对多”,是靠程序员手动创建第三个记录类型(如“选课”),再分别建立“学生→选课”和“选课→课程”两个系来模拟。这就像用两段楼梯连接三层楼,而不是修一部直达电梯。
4.2 误区二:把“记录类型”等同于“关系模型中的表”,忽略其无模式灵活性
易混点:看到“学生记录类型”含学号、姓名字段,就认为它和SQL里的students表完全一样。
为什么混:两者都存实体数据,字段名也相似。
怎么区分:关系模型的表有严格Schema(字段类型、长度、是否为空全固定);网状模型的记录类型虽定义字段,但同一记录类型下的不同记录,可动态拥有不同字段(通过变长记录或可选字段实现)。比如“教师”记录中,教授可填“博导资格证号”,讲师则留空——这在传统关系表里需用NULL或额外表,而网状模型天然支持。它更像JSON文档的雏形,而非二维表。
4.3 误区三:以为“FIND NEXT”就是“查下一条”,忽视“属籍”上下文的致命性
易混点:认为FIND NEXT COURSE IN SET 教研室_开设_课程就是简单取下一条课程记录。
为什么混:字面意思太直白,且多数编程语言的next()确实如此。
怎么区分:在网状模型中,FIND NEXT的“下一条”,完全取决于你当前在哪个系的哪个实例中。如果之前执行的是FIND FIRST 教研室 WITH KEY 'CS-DEPT',那么FIND NEXT COURSE是从“CS-DEPT开设的课程”中找下一条;但如果之前执行的是FIND FIRST 教研室 WITH KEY 'AI-LAB',那FIND NEXT COURSE就变成从“AI-LAB开设的课程”中找了。没有上下文,命令无效——这就像说“下一页”,却不告诉你正在看哪本书。
4.4 误区四:混淆“网状模型”和“网络拓扑”,以为它专用于计算机网络管理
易混点:看到“网状”二字,联想到路由器、交换机组成的物理网络,以为这模型是给网管用的。
为什么混:“网状”是中文翻译带来的歧义,英文“Network Model”中的network指数学上的“网络结构”,与计算机网络(Computer Network)无关。
怎么区分:网状模型处理的是业务实体间的关系网络,如“客户-订单-商品-供应商”;而计算机网络管理关注的是“设备-链路-IP地址”的物理连接。两者抽象层级不同:一个是业务逻辑层,一个是基础设施层。用网状模型存路由器配置?技术上可行,但纯属杀鸡用牛刀——它为高并发事务设计,不为设备状态轮询优化。
4.5 误区五:认为“DBTG标准已淘汰,学它纯属浪费时间”
易混点:查资料发现IDMS、DMS1100等系统早已停更,就断定网状模型知识过时。
为什么混:用产品生命周期代替技术思想价值。就像没人再用打字机,但“键盘布局”“退格键逻辑”仍深刻影响着今日输入法。
怎么区分:网状模型的三大遗产至今活跃:
①导航式查询思想:NoSQL数据库(如MongoDB的$lookup)、GraphQL的嵌套查询,都继承了“从一点出发,逐层展开”的路径思维;
②系(Set)概念:现代ORM框架(如Django ORM)的ForeignKey和ManyToManyField,本质就是对“Owner-Member”和“多对多拆解”的高级封装;
③数据契约精神:微服务间的数据接口定义(如Protobuf Schema),强调字段必填、关系强制,正是网状模型“码字段”“属籍类别”约束的分布式演进。
不懂网状模型,就像学摄影不懂暗房——你拍得出好照片,但永远不明白光影为何这样流动。
5. 什么时候该用网状模型:一份来自真实项目的边界判断指南
5.1 适用场景:当你的业务天然长着“多父多子”的骨头
网状模型不是万能胶,它的光芒只在特定土壤里闪耀。以下是三个经实战验证的典型适用场景,附真实参数与决策逻辑:
场景一:实时性要求极高的嵌入式数据库(如航天器遥测系统)
业务特征:
- 数据源固定(传感器A/B/C持续上报);
- 查询模式单一且高频(如“查过去10秒内所有温度传感器超阈值记录”);
- 绝对不允许查询延迟抖动(>5ms即触发故障保护)。
为什么网状模型胜出:
关系模型需解析SQL、生成执行计划、走B+树索引,链路长、抖动大;网状模型将传感器记录类型(TempSensor)、报警记录类型(AlarmLog)和系(Sensor_TRIGGERS_Alarm)全部固化在内存中。查询时,系统直接按预设指针链遍历,实测P99延迟稳定在1.2ms,比同配置PostgreSQL快8倍。关键配置(摘自某卫星地面站DBTG DDL):
RECORD TYPE TempSensor FIELD sensor_id INTEGER /* 码字段,唯一标识 */ FIELD timestamp DATETIME FIELD value REAL RECORD TYPE AlarmLog FIELD alarm_id INTEGER FIELD severity CHAR(10) FIELD message CHAR(100) SET Sensor_TRIGGERS_Alarm OWNER TempSensor MEMBER AlarmLog INSERTION MODE AUTOMATIC /* 温度超阈值,自动创建报警 */ DELETION MODE OPTIONAL /* 报警可独立存在,不随传感器删除 */
注意:此场景下,业务方主动放弃“灵活查询”,换取确定性性能——这是网状模型的黄金法则:用结构刚性,换执行确定性。
场景二:需要强事务保障的金融清算系统(如跨境支付报文路由)
业务特征:
- 每笔交易涉及“发起行-中间行-收款行-账户-币种-汇率”六方强关联;
- 必须保证“路由路径完整建立后,才允许资金划转”,否则出现资金悬空;
- 日均交易量10万笔,峰值每秒300笔,要求事务提交<100ms。
为什么网状模型胜出:
关系模型用外键约束虽能保证参照完整性,但多表JOIN的锁竞争在高并发下极易阻塞;网状模型将“支付路径”建模为一个系(Payment_Route),其中OWNER为支付指令,MEMBER为各环节行号。事务启动时,系统一次性锁定整条路径的指针链,所有更新原子完成,无锁等待。某银行实测,相同负载下事务失败率从关系模型的0.7%降至0.002%。关键约束(DBTG完整性规则):
MANDATORY删除模式:删除支付指令前,必须先清除所有路由环节;CURRENCY绑定:每个事务线程独占一个Payment_Route属籍,避免路径混淆;KEY字段强制:支付指令ID为全局唯一,杜绝重复路由。
场景三:遗留系统平滑迁移中的“桥接层”
业务特征:
- 企业核心HR系统仍运行在IDMS网状数据库上,存储员工、部门、薪酬数据;
- 新建的BI平台需对接,但IDMS无标准ODBC驱动,且DBA拒绝开放原始指针操作权限。
为什么网状模型知识成为救命稻草:
开发团队没有重写ETL,而是用网状模型思维构建了一层“虚拟关系层”:
① 将IDMS中的EMPLOYEE记录类型映射为employees视图;
② 将EMPLOYEE_DEPT_SET系(员工-部门归属)映射为employee_dept关联表;
③ 用Python脚本模拟FIND NEXT逻辑,按需批量拉取数据。
整个过程耗时3天,比采购商业网关节省200万元。落地要点:
- 不直接暴露指针,而是将“系”封装为API(如
GET /employees/{id}/departments); - 用缓存层(Redis)存储常用路径结果,规避频繁导航开销;
- 所有错误日志标注“属籍丢失”“系实例不存在”等网状术语,便于老DBA快速定位。
- 不直接暴露指针,而是将“系”封装为API(如
5.2 绝对禁用场景:三类需求,碰都不要碰
有些需求,天生与网状模型八字不合。强行使用,轻则返工,重则系统瘫痪:
| 需求类型 | 为什么禁用 | 替代方案 |
|---|---|---|
| 需要频繁变更数据结构(如互联网产品快速迭代) | 网状模型DDL修改需停库、重建指针链,一次变更平均耗时4小时;而关系模型ALTER TABLE可在秒级完成。某电商尝试将“商品标签”从单字段改为多对多,导致促销活动停摆半天。 | 用关系模型+JSON字段存储动态属性;或直接上MongoDB |
| 用户自助分析(Ad-hoc Query) | FIND...IN SET...要求用户精通数据路径,业务人员根本不会写;而SQL可用自然语言生成工具(如Text-to-SQL)辅助。某零售企业让店长查“上周华东区销量Top10商品”,网状接口需提供5个参数(起始系、Owner ID、排序字段等),错误率82%。 | 用Star Schema + OLAP Cube(如Apache Druid),提供拖拽式BI |
| 需要全球分布式部署 | 网状模型的指针链依赖本地存储,跨地域同步时指针失效;而关系模型可通过分库分表+全局事务(如Seata)实现。某跨国物流系统试图用网状模型同步中美仓库数据,因时钟漂移导致路径断裂,库存差异率达15%。 | 用NewSQL数据库(如CockroachDB),或事件溯源+最终一致性 |
5.3 我的血泪教训:从“硬刚网状模型”到“借力打力”的转变
三年前,我接手一个某高校的科研项目管理系统改造。原系统用网状模型(IDMS)存储“项目-负责人-成员-经费-成果”关系,新需求是增加“项目关联专利”和“跨项目协作图谱”。我第一反应是:既然旧系统用网状,那就延续它,把专利建为新记录类型,再加两个系——Project_HOLDS_Patent和Project_COOP_Project。
结果两周后崩溃:
Project_COOP_Project系要求每个项目必须有明确的“主导方”,但协作项目常无主次;- 导出数据给财务处时,他们需要“按年度统计各学院经费总额”,而网状模型没有聚合函数,我得手写循环累加,代码长达800行;
- 最致命的是,当某项目负责人离职,按
MANDATORY规则必须先清空所有协作关系,但业务方要求“保留历史协作记录”,规则直接冲突。
我彻底推翻重来:
①保留IDMS存储核心事务数据(立项、拨款、结题),因其ACID强、性能稳;
②新建PostgreSQL库,用关系模型存分析视图(如project_summary表,每日凌晨ETL同步);
③用Neo4j存协作图谱,将“项目-专利-作者-机构”建为节点,关系用FILED_BY、AFFILIATED_WITH等语义边,支持任意跳数查询。
现在,业务方在Neo4j Browser里输入MATCH (p:Project)-[:FILED_BY]->(a:Author) WHERE p.name CONTAINS 'AI' RETURN a.name,3秒出结果;财务报表从PostgreSQL直接导出;IDMS只默默扛住每秒200次的立项审批请求。三套模型各司其职,像交响乐团——网状模型是定音鼓,沉稳有力;关系模型是弦乐组,细腻精准;图数据库是铜管组,气势恢宏。
从那以后我每次做技术选型,都强制走一遍“三问流程”:
- 问业务:这个需求最怕什么?是慢?是错?还是变?
- 问数据:它的关系骨架,天然是一棵树、一张网,还是一堆散点?
- 问人:谁来写查询?是DBA、Java工程师,还是销售总监?
希望帮到你。
本文还有配套的精品资源,点击获取