MySQL Oracle面试题

主键的作用:

唯一标识每一行数据

主键(Primary Key) 的取值必须唯一,且不能为NULL

什么是外键?

外键是一个表中的字段,它的值必须匹配另一张表(或同一张表)的主键值。

外键的核心是建立和强制两张表之间的引用关系 ,从而保证数据的逻辑一致性

什么是关系型数据库?

RDBMS的核心特性(如强事务、实时更新、严格的ACID)

关系型数据库的"关系"是什么?

"关系" 在关系型数据库中,本源是数学上的集合关系,具体表现为二维表,并通过SQL操作。

它主要包含以下三层含义,层层递进:

第一层:数学基础------关系代数(核心本源)

这是"关系"一词的真正来源

  • "关系"在这里是一个数学集合论中的概念 。具体指:多个集合的笛卡尔积的一个子集

  • 通俗化解释 :想象一个"学生"表,它有学号、姓名、年龄三个字段。这个表在数学上就是一个"关系",它代表了所有可能的(学号,姓名,年龄)组合中,实际存在的那些数据行所构成的集合。

  • 关键点 :这个"关系"是值的集合 ,是无序的,强调的是数据的逻辑集合本身,而不是其物理存储形式。

对"关系"(即表)的操作,遵循一套完整的数学理论------关系代数

  • 其核心操作包括:选择(σ)、投影(π)、连接(⋈)、并集(∪) 等。

  • SQL语言 正是基于关系代数设计的。当你写 SELECT ... FROM ... WHERE ... JOIN ... 时,你就是在描述一系列关系代数运算。

  • 所有操作的结果仍然是一个"关系"(一张新表),这使得操作可以层层组合,非常强大和灵活

第二层:数据结构------二维表(具体表现)

在计算机中,我们用二维表来直观地表示和操作这个数学上的"关系"。

  • 一个"关系" = 一张表(Table)

  • 关系的属性(Attribute) = 表的列(Column)

  • 关系的元组(Tuple) = 表的行(Row)

  • 这种结构极其清晰、直观,符合人类理解数据的习惯。

关系模型的三要素

  1. 数据结构:二维表(关系)。

  2. 操作方式:关系代数/SQL。

  3. 完整性约束:实体完整性(主键)、参照完整性(外键)、用户自定义完整性

关系型数据库的核心特征总结

基于关系模型构建的数据库(RDBMS)通常具备以下特征:

  1. 数据以二维表形式呈现

  2. 支持SQL语言进行数据定义和操作。

  3. 支持ACID事务,保证数据一致性(这是Oracle/MySQL等OLTP数据库的强项)。

  4. 支持完整性约束(主键、外键等)。

关系型数据库的完整性约束是什么?实体完整性(主键)、参照完整性(外键)、用户自定义完整性?

约束类型 中文名称 英文名称 核心作用 典型实现机制
实体完整性 实体完整性 Entity Integrity 保证表中每行数据的唯一可标识性 主键(Primary Key) 约束
参照完整性 参照完整性 Referential Integrity 保证表与表之间引用关系的一致性 外键(Foreign Key) 约束
用户自定义完整性 用户自定义完整性 User-defined Integrity 保证数据符合具体的业务规则 **检查(CHECK)、唯一(UNIQUE)、非空(NOT NULL)、默认值(DEFAULT)、触发器(Trigger)**等
1. 实体完整性

主键(Primary Key) 的取值必须唯一,且不能为NULL。

  • 为什么重要

    • 唯一标识:确保表中的每一行都是一个可区分的"实体"。就像每个人有唯一的身份证号。

    • 操作基础 :是数据更新、删除和关联查询的唯一依据

2.参照完整性
  • 定义 :如果表A中的某个字段(外键)引用了表B的主键,那么该外键的取值要么为NULL,要么必须在表B的主键值中存在

  • 为什么重要

    • 防止"孤儿数据":确保不会出现引用了一个不存在实体的数据。比如,不会出现一笔交易对应的账户在账户表中不存在。

    • 维护数据关联网络:保证整个数据库内数据关系的逻辑一致性。

  • 银行实例

    • 交易流水表 中有一个 账号(ACCT_NO) 字段,它作为外键 ,引用了 账户表 的主键 ACCT_NO

    • 这意味着,任何一笔交易记录中的 ACCT_NO,都必须在 账户表 中真实存在。

  • 违反示例

    • 试图在 交易流水表 中插入一条 ACCT_NO = '9999999999' 的记录,而 账户表 中根本没有这个账号。数据库会拒绝插入

    • 如果试图从 账户表 中删除一个还有交易流水关联的账户,数据库的典型行为是:

      • RESTRICT(默认)拒绝删除,除非先删除所有关联流水。

      • CASCADE级联删除,自动删除所有关联的流水记录(风险高,银行慎用)。

      • SET NULL:将流水表中的外键设为NULL(通常不符合业务逻辑)。

银行实例

  • 客户信息表 中,客户号(CUST_ID) 必须设为主键。这保证了一个客户号只对应一个真实的客户,避免重复开户或信息混淆。
3. 用户自定义完整性
  • 定义 :根据具体业务需求定义的、超出上述两种基本完整性之外的规则。最为灵活,也最体现业务特性

  • 为什么重要:将业务规则固化在数据库层面,从源头保证数据质量,避免脏数据流入。

  • 常见实现机制与银行实例

机制 银行实例 SQL示例(简写)
非空约束 客户姓名不能为空 CUST_NAME VARCHAR(100) NOT NULL
唯一约束 客户身份证号不能重复(即使它不是主键) ID_NO VARCHAR(18) UNIQUE
检查约束 账户余额不能为负数 客户年龄必须大于等于18岁 交易金额必须大于0 BALANCE DECIMAL(15,2) CHECK (BALANCE >= 0) AGE INT CHECK (AGE >= 18) TX_AMT DECIMAL(15,2) CHECK (TX_AMT > 0)
默认值 账户开户日期默认为系统当前日期 OPEN_DATE DATE DEFAULT CURRENT_DATE
触发器 更复杂的业务规则: 1. 当账户余额变更时,自动插入一条余额变更流水。 2. 当单日交易累计金额超过5万时,发送预警。 3. 确保贷款状态与还款计划状态的逻辑一致。 通过 CREATE TRIGGER 实现的一段PL/SQL或T-SQL程序。

Hive和MySQL Oracle在延迟上有什么不同?

MySQL和Oracle毫秒到秒级, Hive:分钟到小时级

银行数仓使用Hive这个非关系型数据库,是没有主键的。如果不小心录入了一个新开户信息,身份证号和hive数据库里面的身份证号相同,但是名字信息不同,是不是不会报错?那也不容易发现这样的错误?

为什么Hive不会报错?

  1. 无主键约束 :Hive不强制id_no字段的唯一性。

  2. 无唯一约束 :即使声明了UNIQUE(Hive 3.x支持语法),默认也不强制执行。

  3. 批量处理特性 :Hive设计为高吞吐批处理,将数据质量检查交给上游应用

三、具体业务情境:何时会遇到这种重复?

情境1:新分行开户时的信息录入错误(最常见)

  • 场景:客户"张三"在A分行已有账户,姓名录入为"张三"。

  • 问题:同一客户到B分行开户,柜员误录入为"张叁"。

  • 结果 :核心系统创建了新的客户记录(新的customer_id),但身份证号相同。

  • 进入数仓 :ETL拉取时会发现同一id_no对应两个name值。

情境2:客户信息变更未同步

  • 场景:客户"张三"改名为"张四",在开户行更新了信息(更新了C001记录)。

  • 问题:但该客户在其他分行的账户信息(C002记录)未同步更新。

  • 结果:核心系统存在两条同一身份证的记录,姓名不同。

  • 进入数仓:ETL看到"历史姓名"和"新姓名"的冲突。

情境3:渠道数据不一致

  • 场景

    • 线下渠道:客户实名认证为"张三"

    • 线上渠道(手机银行):客户注册时自填为"张叁"

  • 结果:银行不同渠道系统可能为同一客户创建了不同客户ID。

  • 进入数仓:多渠道数据整合时发现冲突。

情境4:数据迁移或系统合并

  • 场景:银行A并购银行B,两个核心系统合并。

  • 问题:同一客户在两个银行都有账户,但客户信息(姓名简繁体、空格等)有细微差异。

  • 结果:系统合并后,出现"重复"客户记录。

  • 进入数仓:ETL需要处理这种历史遗留问题。

三、这种错误的严重性(在银行场景下)

这种"同人不同名"的错误极其危险:

影响层面 具体后果
客户视角 1. 客户征信记录混乱 2. 同一身份证号可能获得多份授信额度 3. 风险评级不一致,导致风控失效
业务视角 1. 同一客户被重复营销,成本浪费 2. 客户资产统计翻倍,报表失真 3. 反洗钱监控失效(无法关联同一人的所有交易)
监管视角 1. 违反"了解你的客户"(KYC)原则 2. 监管报送数据不准确,面临重罚 3. 无法满足《反洗钱法》对客户身份识别的要求

真实案例:某银行曾因客户信息重复,导致同一客户在不同分行获得多笔贷款,最终形成集中度风险,被监管处罚。

一、真实案例:从新闻到监管罚单

案例1:某大型银行因客户身份信息不符被重罚(2022年)

  • 事件 :监管检查发现,该银行客户信息系统中,同一身份证号对应多个不同姓名的客户记录超过万条。

  • 后果

    1. 反洗钱监控失效:无法有效识别同一客户的多账户异常交易

    2. 信贷过度集中:同一客户在不同分行获得多笔贷款,突破集中度限额

    3. 监管处罚 :因违反《金融机构客户身份识别和客户身份资料及交易记录保存管理办法》被罚款数百万元

  • 根本原因:各分行录入客户信息时标准不统一,且总行缺乏有效的去重和校验机制。

案例2:城商行"一人多卡"套现案(2021年)

  • 事件 :犯罪分子利用银行系统漏洞,使用同一身份证但不同姓名拼音(如"Zhang San"和"Zhang San1")在多个网点开立账户。

  • 手法

    • 利用柜员录入疏忽(英文名大小写、空格差异)

    • 在不同支行分别申请信用卡

    • 通过虚假交易套现

  • 暴露问题 :银行风险系统未将ID_NO=110101199001011234, NAME=ZHANG SANID_NO=110101199001011234, NAME=ZHANG SAN1识别为同一客户。

案例3:某股份制银行监管报送数据错误(2020年)

  • 事件:向人民银行报送的"同一客户贷款总额"统计严重失实。

  • 发现:检查发现,因客户姓名录入差异(简体/繁体、有无中间空格),导致:

    • 一个实际贷款5000万的客户,被统计为3个"不同客户"

    • 每个"客户"贷款额都不超过2000万

    • 掩盖了单一客户集中度风险

  • 处罚:因"报送金融统计报表错误"被警告并罚款。

四、银行的应对策略:如何发现并防止?

银行绝不会依赖Hive自身的约束,而是通过一整套数据治理体系来保证数据质量:

策略1:ETL过程中的强制去重(最核心防线)

在数据入仓的ODS→DWD层清洗时,就必须进行去重:

sql 复制代码
-- 示例:使用窗口函数确保身份证号唯一
INSERT OVERWRITE TABLE dwd_customer
SELECT 
    cust_id,
    id_no,
    name,
    -- 其他字段...
FROM (
    SELECT *,
           ROW_NUMBER() OVER (
               PARTITION BY id_no 
               ORDER BY update_time DESC, data_source_priority
           ) AS rn
    FROM ods_customer
    WHERE id_no IS NOT NULL -- 非空检查
) t
WHERE rn = 1; -- 只取每个身份证号最新的一条记录
策略2:建立专门的数据质量监控(DQC)

银行数仓通常有独立的数据质量监控平台,定期扫描:

sql 复制代码
-- 质量检查SQL:找出重复的身份证号
SELECT id_no, COUNT(*) as cnt, 
       COLLECT_SET(name) as names, -- 收集不同的名字
       COLLECT_SET(cust_id) as cust_ids
FROM dim_customer
WHERE id_no IS NOT NULL
GROUP BY id_no
HAVING COUNT(*) > 1
-- 结果会推送到数据质量告警平台,通知负责人处理
策略3:引入数据湖表格式(现代解决方案)

使用Apache Hudi/Iceberg 等支持主键级更新的表格式:

复制代码
-- Hudi示例:使用id_no作为主键进行Upsert
-- 如果id_no已存在,则更新记录;否则插入
-- 这本质上实现了“主键”的更新语义

Hive与MySQL/Oracle的区别,优势,劣势

响应速度上,MySQL/Oracle是秒级/毫秒级,Hive是分钟级/小时级

设计哲学不同

Hive :面向批处理离线分析,设计目标是处理TB/PB级数据的复杂查询

MySQL/ Oracle :面向实时事件响应 ,是OLTP(在线事务处理)数据库的特性

Hive没有主键和索引,有可能存在主键重复的情况

Hive中没有触发器Trigger,因为触发器 是面向实时事件响应,是OLTP(在线事务处理)数据库的特性。

Hive中没有存储过程Procedure和Function

Hive的批处理是什么?

批处理 = 把一批数据攒到一起,定时 / 定量后一次性集中处理。

就像:

  • 不是来一件快递就送一次,而是攒满一车再统一派送
  • 不是洗一件衣服就开一次洗衣机,而是攒一桶再一起洗

放到银行 / 大数据里就是:

  • 白天业务系统产生交易、还款、逾期、开户等数据
  • 晚上 24:00 或凌晨 2:00 统一抽取到数仓
  • 一次性计算:不良率、入催率、延滞率、迁徙率、拨备覆盖率等
  • 第二天早上出报表给业务 / 风控部门看

HiveSQL里面有触发器吗?一般下面这种操作是在做分析的数仓里面,还是Oracle里面直接做了

  1. 当账户余额变更时,自动插入一条余额变更流水。

  2. 当单日交易累计金额超过5万时,发送预警。

答案是:没有。HiveSQL不支持触发器(Trigger)。

为什么Hive没有触发器?

  1. 设计哲学不同

    • Hive :面向批处理离线分析,设计目标是处理TB/PB级数据的复杂查询

    • 触发器 :面向实时事件响应,是OLTP(在线事务处理)数据库的特性

  2. 技术架构限制

    • 存储与计算分离 :数据在HDFS/S3,计算在集群,难以实现"数据变更即时触发"

    • 无事务支持(早期):触发器需要在事务中执行,Hive传统上不支持ACID事务

    • 延迟特性 :Hive查询通常是分钟/小时级,触发器需要毫秒级响应

触发器性能开销大,违背批处理设计。

解释一下COLLECT_SET()函数如何使用?

策略2:建立专门的数据质量监控(DQC)

银行数仓通常有独立的数据质量监控平台,定期扫描:

sql 复制代码
-- 质量检查SQL:找出重复的身份证号
SELECT id_no, COUNT(*) as cnt, 
       COLLECT_SET(name) as names, -- 收集不同的名字
       COLLECT_SET(cust_id) as cust_ids
FROM dim_customer
WHERE id_no IS NOT NULL
GROUP BY id_no
HAVING COUNT(*) > 1
-- 结果会推送到数据质量告警平台,通知负责人处理

关系型数据库中的ACID是什么?

A:原子性(Atomicity)

  • 定义 :事务中的所有操作要么全部完成,要么全部不完成,不可能停在中间状态。

  • 银行比喻 :转账操作包含两个步骤:1.从A账户扣款 2.向B账户加款。原子性确保这两个步骤要么都成功,要么都失败。绝不会出现A账户钱扣了,但B账户没收到的情况。

  • 技术实现 :通过事务日志(Transaction Log)回滚(Rollback) 机制实现。

C:一致性(Consistency)

  • 定义 :事务执行前后,数据库必须保持一致的状态,所有数据约束(如主键、外键、检查约束)都必须满足。

  • 银行比喻 :转账前后,银行的总资产必须保持不变(A账户减少的金额 = B账户增加的金额)。同时,账户余额不能为负数(检查约束)。

  • 技术实现:由数据库的完整性约束和应用程序逻辑共同保证。

I:隔离性(Isolation)

  • 定义 :多个事务并发执行时,彼此相互隔离,一个事务不应看到其他未完成事务的中间状态。

  • 银行比喻 :当你正在查账户余额时,正好有人给你转账。隔离性确保你要么看到转账前的余额,要么看到转账后的完整余额,绝不会看到一个"正在转账中"的中间值(比如只看到对方账户已扣款,但你账户还没入账的状态)。

  • 技术实现 :通过锁机制多版本并发控制(MVCC) 实现,有不同的隔离级别。

D:持久性(Durability)

  • 定义 :一旦事务提交成功,它对数据的修改就是永久性的,即使系统崩溃也不会丢失。

  • 银行比喻 :转账成功后,这笔交易记录必须永久保存,即使银行服务器突然断电,重启后转账结果依然有效。

  • 技术实现 :通过预写日志(WAL)数据持久化存储(磁盘)实现。

一致性中的主键约束、外键约束、检查约束分别是什么?

一、主键约束:数据的"身份证"

核心定义

主键约束(Primary Key Constraint) 是表中唯一标识每一行记录的列或列组合,它必须满足:

  1. 唯一性:主键值在整个表中必须唯一

  2. 非空性:主键值不能为NULL

  3. 不可变性:主键值一旦确定,通常不应更改

二、外键约束:数据的"关系证明"

核心定义

外键约束(Foreign Key Constraint) 是一个表中的字段,它引用另一个表的主键,用于维护表间的引用完整性。

外键的核心规则

  1. 引用存在:外键值必须在被引用表的主键中存在(或为NULL)

  2. 数据一致性:防止"孤儿记录"

  3. 级联操作:可定义当主表数据变化时,从表的联动行为

三、什么是检查约束?

简单定义

检查约束(Check Constraint)是数据库中对单个列或整行数据施加的条件规则,只有满足该条件的数据才能被插入或更新。

实例:账户余额不能为负数

sql 复制代码
-- 创建账户表时定义检查约束
CREATE TABLE accounts (
    account_no   VARCHAR(20) PRIMARY KEY,
    account_name VARCHAR(100),
    balance      DECIMAL(15,2) NOT NULL,
    -- 检查约束:余额必须 >= 0
    CONSTRAINT ck_balance_non_negative 
    CHECK (balance >= 0),
    
    account_type VARCHAR(10),
    -- 检查约束:账户类型只能是特定值
    CONSTRAINT ck_account_type 
    CHECK (account_type IN ('SAVINGS', 'CURRENT', 'FIXED_DEPOSIT', 'LOAN'))
);
相关推荐
数据知道2 小时前
PostgreSQL 核心原理:什么场景下开启 JIT 能提升性能?(JIT 编译)
数据库·postgresql
吕司2 小时前
MySQL库的操作
数据库·mysql·oracle
LaughingZhu2 小时前
Product Hunt 每日热榜 | 2026-02-05
大数据·数据库·人工智能·经验分享·搜索引擎·产品运营
逃逸线LOF2 小时前
mysql本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止
数据库
Remember_9932 小时前
MySQL 索引详解:从原理到实战优化
java·数据库·mysql·spring·http·adb·面试
dishugj2 小时前
【Oracle】 rac的一些问题以及解决方案
数据库·oracle
Ronin3052 小时前
日志打印和实用 Helper 工具
数据库·sqlite·rabbitmq·文件操作·uuid生成
eWidget2 小时前
面向信创环境的Oracle兼容型数据库解决方案
数据库·oracle·kingbase·数据库平替用金仓·金仓数据库
阿正的梦工坊3 小时前
使用即梦(seedream)来图生图:读取与写入飞书多维表格
数据库·飞书