(202307)wonderful-sql:初识数据库(task1)

本文介绍了关系型数据库的基本概念,包括行和列组成的二维表结构,客户端/服务器模型,以及SQL语言的作用。文章详细讲解了SQL的DML,如INSERT、UPDATE、DELETE,并提到了数据类型、约束和索引的概念。此外,还提供了创建和修改表的示例,以及数据操作的注意事项。

学习知识

初识数据库

关系型数据库简介

特点是由行和列组成的二维表来管理数据,这种类型的 DBMS 称为关系数据库管理系统(Relational Database Management System,RDBMS)。本课程将向大家介绍使用 SQL 语言的数据库管理系统,也就是关系数据库管理系统(RDBMS)的操作方法。

在关系型数据库中,常见的是客户端 / 服务器类型(C/S类型)。通过客户端发出sql语言,向服务端请求数据,服务端像数据库中读取数据返回给客户端。

数据库中存储的表结构类似于excel中的行和列,在数据库中,行称为记录,它相当于一条记录,列称为字段,它代表了表中存储的数据项目。

SQL是为操作数据库而开发的语言。国际标准化组织(ISO)为 SQL 制定了相应的标准,以此为基准的SQL 称为标准 SQL。但实际上完全基于标准的RDBMS很少,不过datawhale教程中使用的都是标准的sql语言。

根据指令的不同,sql语句分为三类,数据定义语言DDL、数据操纵语言DML、数据控制语言DCL,教程中主要围绕DML来讲,因为其使用最多,实际使用的 SQL 语句当中有 90% 属于 DML。

语法规范

在datawhale的该项目的仓库中,有完整sql语法规范

命名规则

只能使用半角英文字母、数字、下划线(_)作为数据库、表和列的名称
名称必须以半角英文字母开头

数据类型的指定

在数据类型中,在其他语言中见得比较少的是VARCHAR类型,如其名“VAR CHAR"可变长字符串类型。

约束的设置

约束是除了数据类型之外,对列中存储的数据进行限制或者追加条件的功能。
NOT NULL是非空约束,即该列必须输入数据。
PRIMARY KEY是主键约束,代表该列是唯一值,可以通过该列取出特定的行的数据。

并且,在教程中给出的创建表的示例中,也可以把主键约束加到行后进行约束,即:

CREATE TABLE product
(
  product_id CHAR(4) NOT NULL PRIMARY KEY,
  product_name VARCHAR(100) NOT NULL,
  product_type VARCHAR(32) NOT NULL,
  sale_price INTEGER,
  purchase_price INTEGER,
  regist_date DATE
);

或者我们也可以对约束进行命名,将约束写为:

CONSTRAINT pk_product PRIMARY KEY (product_id)

即把约束命名为pk_product
创建表时也可以用DEFAULT设置默认值。

表的删除和更新

表的删除和更新主要有DROP、DELETE、ALTER、TRUNCATE等命令,需要注意的是删除后不可恢复的情况以及必须指定where的情况。
如果不指定where,那么修改(DELETE或UPDATE)将会作用于整个表。
UPDATE的SET语句也支持同时将多个列作为更新对象。

-- 合并后的写法
UPDATE product
   SET sale_price = sale_price * 10,
       purchase_price = purchase_price / 2
 WHERE product_type = '厨房用具';  

插入数据

INSERT语句可以用于添加数据。添加数据可以不列出列清单,不列出列清单将会从左往右依次添加。

-- 包含列清单
INSERT INTO productins (product_id, product_name, product_type, sale_price, purchase_price, regist_date) VALUES ('0005', '高压锅', '厨房用具', 6800, 5000, '2009-01-15');
-- 省略列清单
INSERT INTO productins VALUES ('0005', '高压锅', '厨房用具', 6800, 5000, '2009-01-15');  

并且,INSERT语句可以一次插入多行。

INSERT INTO productins VALUES ('0002', '打孔器', '办公用品', 500, 320, '2009-09-11'),
                              ('0003', '运动T恤', '衣服', 4000, 2800, NULL),
                              ('0004', '菜刀', '厨房用具', 3000, 2800, '2009-09-20'); 

如果想要赋值为空,那么将值写为NULL即可,但是只能对没有非空约束的列赋值为空哦。

也可以使用INSERT INTO...SELECT...FROM...来复制其他表中的数据。

索引

索引分为主键索引、唯一索引、普通索引、前缀索引、全文索引*(利用“分词技术”实现在长文本中搜索关键字的一种索引)、单列索引、联合索引(复合索引、多列索引)*等。

练习题

1

编写一条 CREATE TABLE 语句,用来创建一个包含表 1-A 中所列各项的表 Addressbook (地址簿),并为 regist_no (注册编号)列设置主键约束。

CREATE TABLE Addressbook
(
	regist_no INTEGER NOT NULL,
	name VARCHAR(128) NOT NULL,
	address VARCHAR(256) NOT NULL,
	tel_no CHAR(10),
	mail_address CHAR(20),
	PRIMARY KEY (regist_no)
);

在这里插入图片描述

2

假设在创建练习1.1中的 Addressbook 表时忘记添加如下一列 postal_code (邮政编码)了,请编写 SQL 把此列添加到 Addressbook 表中。
列名 : postal_code
数据类型 :定长字符串类型(长度为 8)
约束 :不能为 NULL

ALTER TABLE Addressbook ADD postal_code CHAR(8) NOT NULL;

在这里插入图片描述

3

请补充如下 SQL 语句来删除 Addressbook 表。

DROP TABLE Addressbook;

4

这是不可恢复的,无论是使用TRUNCATE TABLE 或 DELETE 清除数据还是使用DROP删除表,使用ALTER删除一列,都是不可恢复的,因为删除后数据没有被存放在任何地方,当然也就无法被恢复。

<template> <div class="main-layout"> <div class="body-layout"> <Sidebar /> <div class="crud-container"> <div class="welcome"> <!-- 公共头部 --> <HeaderBar :devices="devices" @search="handleSearch" @search-reset="handleSearchReset" /> <el-main style="padding: 20px; display: flex; flex-direction: column"> <div> <!-- 首页内容 --> <div class="add-device"> <div class="add-device-bg"> <div class="hellow-text" style="margin-top: 30px"> 你好,小智 </div> <div class="hellow-text"> 让我们度过 <div style="display: inline-block; color: #5778ff"> 美好的一天! </div> </div> <div class="hi-hint">Hello, Let's have a wonderful day!</div> <div class="add-device-btn"> <div class="left-add" @click="showAddDialog"> 添加智能体 </div> <div style=" width: 23px; height: 13px; background: #5778ff; margin-left: -10px; " /> <div class="right-add"> <i class="el-icon-right" @click="showAddDialog" style="font-size: 20px; color: #fff" /> </div> </div> </div> </div> <div class="device-list-container"> <template v-if="isLoading"> <div v-for="i in skeletonCount" :key="'skeleton-' + i" class="skeleton-item" > <div class="skeleton-image"></div> <div class="skeleton-content"> <div class="skeleton-line"></div> <div class="skeleton-line-short"></div> </div> </div> </template> <template v-else> <DeviceItem v-for="(item, index) in devices" :key="index" :device="item" @configure="goToRoleConfig" @deviceManage="handleDeviceManage" @delete="handleDeleteAgent" @chat-history="handleShowChatHistory" /> </template> </div> </div> <AddWisdomBodyDialog :visible.sync="addDeviceDialogVisible" @confirm="handleWisdomBodyAdded" /> </el-main> <el-footer> <version-footer /> </el-footer> <chat-history-dialog :visible.sync="showChatHistory" :agent-id="currentAgentId" :agent-name="currentAgentName" /> </div> </div> </div> </div> </template> <script> import Api from "@/apis/api"; import AddWisdomBodyDialog from "@/components/AddWisdomBodyDialog.vue"; import ChatHistoryDialog from "@/components/ChatHistoryDialog.vue"; import DeviceItem from "@/components/DeviceItem.vue"; import HeaderBar from "@/components/HeaderBar.vue"; import VersionFooter from "@/components/VersionFooter.vue"; import Sidebar from "@/components/SideBar.vue"; export default { name: "HomePage", components: { Sidebar, DeviceItem, AddWisdomBodyDialog, HeaderBar, VersionFooter, ChatHistoryDialog, }, data() { return { addDeviceDialogVisible: false, devices: [], originalDevices: [], isSearching: false, searchRegex: null, isLoading: true, skeletonCount: localStorage.getItem("skeletonCount") || 8, showChatHistory: false, currentAgentId: "", currentAgentName: "", }; }, mounted() { this.fetchAgentList(); }, methods: { showAddDialog() { this.addDeviceDialogVisible = true; }, goToRoleConfig() { // 点击配置角色后跳转到角色配置页 this.$router.push("/role-config"); }, handleWisdomBodyAdded(res) { this.fetchAgentList(); this.addDeviceDialogVisible = false; }, handleDeviceManage() { this.$router.push("/device-management"); }, handleSearch(regex) { this.isSearching = true; this.searchRegex = regex; this.applySearchFilter(); }, handleSearchReset() { this.isSearching = false; this.searchRegex = null; this.devices = [...this.originalDevices]; }, applySearchFilter() { if (!this.isSearching || !this.searchRegex) { this.devices = [...this.originalDevices]; return; } this.devices = this.originalDevices.filter((device) => { return this.searchRegex.test(device.agentName); }); }, // 搜索更新智能体列表 handleSearchResult(filteredList) { this.devices = filteredList; // 更新设备列表 }, // 获取智能体列表 fetchAgentList() { this.isLoading = true; Api.agent.getAgentList( ({ data }) => { if (data?.data) { this.originalDevices = data.data.map((item) => ({ ...item, agentId: item.id, })); // 动态设置骨架屏数量(可选) this.skeletonCount = Math.min( Math.max(this.originalDevices.length, 3), // 最少3个 10 // 最多10个 ); this.handleSearchReset(); } this.isLoading = false; }, (error) => { console.error("Failed to fetch agent list:", error); this.isLoading = false; } ); }, // 删除智能体 handleDeleteAgent(agentId) { this.$confirm("确定要删除该智能体吗?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { Api.agent.deleteAgent(agentId, (res) => { if (res.data.code === 0) { this.$message.success({ message: "删除成功", showClose: true, }); this.fetchAgentList(); // 刷新列表 } else { this.$message.error({ message: res.data.msg || "删除失败", showClose: true, }); } }); }) .catch(() => {}); }, handleShowChatHistory({ agentId, agentName }) { this.currentAgentId = agentId; this.currentAgentName = agentName; this.showChatHistory = true; }, }, }; </script> <style scoped> .main-layout { display: flex; flex-direction: column; height: 100vh; } .body-layout { display: flex; flex: 1; min-height: 0; } .crud-container { flex: 1; background: #f5f7fa; min-width: 0; min-height: 0; overflow: auto; } .welcome { min-width: 900px; min-height: 506px; height: 100vh; display: flex; flex-direction: column; background: linear-gradient(145deg, #e6eeff, #eff0ff); background-size: cover; /* 确保背景图像覆盖整个元素 */ background-position: center; /* 从顶部中心对齐 */ -webkit-background-size: cover; /* 兼容老版本WebKit浏览器 */ -o-background-size: cover; /* 兼容老版本Opera浏览器 */ } .add-device { height: 195px; border-radius: 15px; position: relative; overflow: hidden; background: linear-gradient( 269.62deg, #e0e6fd 0%, #cce7ff 49.69%, #d3d3fe 100% ); } .add-device-bg { width: 100%; height: 100%; text-align: left; background-image: url("@/assets/home/main-top-bg.png"); overflow: hidden; background-size: cover; /* 确保背景图像覆盖整个元素 */ background-position: center; /* 从顶部中心对齐 */ -webkit-background-size: cover; /* 兼容老版本WebKit浏览器 */ -o-background-size: cover; box-sizing: border-box; /* 兼容老版本Opera浏览器 */ .hellow-text { margin-left: 75px; color: #3d4566; font-size: 33px; font-weight: 700; letter-spacing: 0; } .hi-hint { font-weight: 400; font-size: 12px; text-align: left; color: #818cae; margin-left: 75px; margin-top: 5px; } } .add-device-btn { display: flex; align-items: center; margin-left: 75px; margin-top: 15px; cursor: pointer; .left-add { width: 105px; height: 34px; border-radius: 17px; background: #5778ff; color: #fff; font-size: 14px; font-weight: 500; text-align: center; line-height: 34px; } .right-add { width: 34px; height: 34px; border-radius: 50%; background: #5778ff; margin-left: -6px; display: flex; justify-content: center; align-items: center; } } .device-list-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); gap: 30px; padding: 30px 0; } /* 在 DeviceItem.vue 的样式中 */ .device-item { margin: 0 !important; /* 避免冲突 */ width: auto !important; } .footer { font-size: 12px; font-weight: 400; margin-top: auto; padding-top: 30px; color: #979db1; text-align: center; /* 居中显示 */ } /* 骨架屏动画 */ @keyframes shimmer { 100% { transform: translateX(100%); } } .skeleton-item { background: #fff; border-radius: 8px; padding: 20px; height: 120px; position: relative; overflow: hidden; margin-bottom: 20px; } .skeleton-image { width: 80px; height: 80px; background: #f0f2f5; border-radius: 4px; float: left; position: relative; overflow: hidden; } .skeleton-content { margin-left: 100px; } .skeleton-line { height: 16px; background: #f0f2f5; border-radius: 4px; margin-bottom: 12px; width: 70%; position: relative; overflow: hidden; } .skeleton-line-short { height: 12px; background: #f0f2f5; border-radius: 4px; width: 50%; } .skeleton-item::after { content: ""; position: absolute; top: 0; left: 0; width: 50%; height: 100%; background: linear-gradient( 90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0) ); animation: shimmer 1.5s infinite; } </style> 在代码不变的情况下实现懒加载
08-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早上真好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值