2025-02-06
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
### **一、标准输入输出函数**(`<stdio.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| --------- | -------------------- | ------------------------------------ |
|
||||
| `printf` | 格式化输出 | `printf("Hello, %s!\n", "World");` |
|
||||
| `scanf` | 格式化输入 | `scanf("%d", &num);` |
|
||||
| `putchar` | 输出单个字符 | `putchar('A');` |
|
||||
| `getchar` | 输入单个字符 | `char c = getchar();` |
|
||||
| `puts` | 输出字符串并换行 | `puts("Hello World!");` |
|
||||
| `gets` | 读取一行字符串 | `char str[100]; gets(str);` |
|
||||
| `fopen` | 打开文件 | `FILE *fp = fopen("test.txt", "r");` |
|
||||
| `fclose` | 关闭文件 | `fclose(fp);` |
|
||||
| `fread` | 从文件读取数据 | `fread(buffer, 1, size, fp);` |
|
||||
| `fwrite` | 向文件写入数据 | `fwrite(data, 1, size, fp);` |
|
||||
| `fprintf` | 格式化写入文件 | `fprintf(fp, "Value: %d\n", value);` |
|
||||
| `fscanf` | 格式化从文件读取数据 | `fscanf(fp, "%d", &value);` |
|
||||
|
||||
------
|
||||
|
||||
### **二、字符串处理函数**(`<string.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| --------- | ------------------------ | --------------------------------- |
|
||||
| `strlen` | 计算字符串长度 | `size_t len = strlen("Hello");` |
|
||||
| `strcpy` | 复制字符串 | `strcpy(dest, src);` |
|
||||
| `strncpy` | 复制指定长度字符串 | `strncpy(dest, src, 5);` |
|
||||
| `strcat` | 拼接字符串 | `strcat(dest, src);` |
|
||||
| `strncat` | 拼接指定长度字符串 | `strncat(dest, src, 5);` |
|
||||
| `strcmp` | 比较两个字符串 | `strcmp(str1, str2);` |
|
||||
| `strncmp` | 比较指定长度的字符串 | `strncmp(str1, str2, 5);` |
|
||||
| `strchr` | 查找字符在字符串中的位置 | `char *p = strchr(str, 'a');` |
|
||||
| `strstr` | 查找子串 | `char *p = strstr(str, "test");` |
|
||||
| `strtok` | 分割字符串 | `char *token = strtok(str, ",");` |
|
||||
|
||||
------
|
||||
|
||||
### **三、数学函数**(`<math.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| ------- | ---------------- | --------------------------------------- |
|
||||
| `abs` | 计算整数绝对值 | `int value = abs(-10);` |
|
||||
| `fabs` | 计算浮点数绝对值 | `double value = fabs(-3.14);` |
|
||||
| `pow` | 计算幂 | `double result = pow(2.0, 3.0); // 2^3` |
|
||||
| `sqrt` | 计算平方根 | `double result = sqrt(9.0);` |
|
||||
| `ceil` | 向上取整 | `double result = ceil(3.14); // 4.0` |
|
||||
| `floor` | 向下取整 | `double result = floor(3.14); // 3.0` |
|
||||
| `round` | 四舍五入 | `double result = round(3.5); // 4.0` |
|
||||
| `sin` | 计算正弦值 | `double result = sin(M_PI / 2); // 1.0` |
|
||||
| `cos` | 计算余弦值 | `double result = cos(0); // 1.0` |
|
||||
| `tan` | 计算正切值 | `double result = tan(M_PI / 4); // 1.0` |
|
||||
|
||||
------
|
||||
|
||||
### **四、内存操作函数**(`<string.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| --------- | ------------ | ------------------------------------ |
|
||||
| `memset` | 设置内存的值 | `memset(buffer, 0, sizeof(buffer));` |
|
||||
| `memcpy` | 内存拷贝 | `memcpy(dest, src, n);` |
|
||||
| `memcmp` | 比较内存区域 | `memcmp(ptr1, ptr2, n);` |
|
||||
| `memmove` | 内存区域移动 | `memmove(dest, src, n);` |
|
||||
|
||||
------
|
||||
|
||||
### **五、动态内存管理函数**(`<stdlib.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| --------- | -------------------- | ------------------------------------------- |
|
||||
| `malloc` | 动态分配内存 | `int *p = (int *)malloc(10 * sizeof(int));` |
|
||||
| `calloc` | 动态分配并初始化内存 | `int *p = (int *)calloc(10, sizeof(int));` |
|
||||
| `realloc` | 重新分配内存大小 | `p = (int *)realloc(p, 20 * sizeof(int));` |
|
||||
| `free` | 释放动态分配的内存 | `free(p);` |
|
||||
|
||||
------
|
||||
|
||||
### **六、时间与日期函数**(`<time.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| ----------- | ------------------ | ---------------------------------------- |
|
||||
| `time` | 获取当前时间戳 | `time_t t = time(NULL);` |
|
||||
| `clock` | 获取程序运行时间 | `clock_t c = clock();` |
|
||||
| `difftime` | 计算时间差 | `double diff = difftime(t1, t2);` |
|
||||
| `localtime` | 转换为本地时间结构 | `struct tm *lt = localtime(&t);` |
|
||||
| `strftime` | 格式化时间为字符串 | `strftime(buffer, 100, "%Y-%m-%d", lt);` |
|
||||
|
||||
------
|
||||
|
||||
### **七、随机数函数**(`<stdlib.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| ------- | -------------- | ------------------------------ |
|
||||
| `rand` | 生成随机数 | `int r = rand();` |
|
||||
| `srand` | 设置随机数种子 | `srand((unsigned)time(NULL));` |
|
||||
|
||||
------
|
||||
|
||||
### **八、进程控制函数**(`<stdlib.h>`)
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| -------- | ------------ | ---------------- |
|
||||
| `exit` | 退出程序 | `exit(0);` |
|
||||
| `system` | 执行系统命令 | `system("dir");` |
|
||||
|
||||
------
|
||||
|
||||
### **九、其他常用函数**
|
||||
|
||||
| 函数 | 功能 | 示例 |
|
||||
| ---------------- | -------------- | ----------------------------------------- |
|
||||
| `atoi` | 字符串转整数 | `int num = atoi("123");` |
|
||||
| `atof` | 字符串转浮点数 | `double num = atof("3.14");` |
|
||||
| `itoa`(非标准) | 整数转字符串 | `itoa(123, buffer, 10);` |
|
||||
| `qsort` | 快速排序 | `qsort(arr, n, sizeof(int), cmp);` |
|
||||
| `bsearch` | 二分查找 | `bsearch(key, arr, n, sizeof(int), cmp);` |
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 252 KiB |
@@ -0,0 +1,115 @@
|
||||
### 1.创建项目
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222165137489.png!compress" alt="image-20241222165137489" style="zoom:50%;" />
|
||||
|
||||
创建项目时选择空项目
|
||||
|
||||
### 2.配置输出控制台
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222165231278.png!compress" alt="image-20241222165231278" style="zoom:50%;" />
|
||||
|
||||
右键项目名称选择`属性`
|
||||
|
||||
配置属性->链接器->系统->子系统设置为`控制台 (/SUBSYSTEM:CONSOLE)`
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222165309647.png!compress" alt="image-20241222165309647" style="zoom:50%;" />
|
||||
|
||||
### 3.安装连接软件
|
||||
|
||||
- 64位编译器选择**Windows (x86, 64-bit), ZIP Archive**(mysql-connector-c-6.1.11-winx64.zip)
|
||||
- 32位编译器选择**Windows (x86, 32-bit), ZIP Archive**(mysql-connector-c-6.1.11-win32.zip)
|
||||
|
||||
https://downloads.mysql.com/archives/c-c/?version=6.1.11&os=src
|
||||
|
||||

|
||||
|
||||
安装完后会在C:\Program Files (x86)\MySQL\MySQL Connector C 6.1目录下
|
||||
|
||||
### 4.配置头文件和lib文件
|
||||
|
||||
**配置头文件路径**
|
||||
|
||||
C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\include
|
||||
|
||||
右键项目名称点击属性 找到 配置属性下的VC++目录 将上述路径加入到`包含目录`下
|
||||
|
||||
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222170322231.png!compress" alt="image-20241222170322231" style="zoom:50%;" />
|
||||
|
||||
点击最右侧下拉框后点击编辑
|
||||
|
||||

|
||||
|
||||
**配置lib文件路径**
|
||||
|
||||
C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib
|
||||
|
||||
右键项目名称点击属性 找到 配置属性->链接器->常规 将上述路径加入到`附加库目录`下
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222170720851.png!compress" alt="image-20241222170720851" style="zoom:50%;" />
|
||||
|
||||
**配置附加依赖性**
|
||||
|
||||
配置属性——>链接器——>输入——>附加依赖项
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222170820644.png!compress" alt="image-20241222170820644" style="zoom:50%;" />
|
||||
|
||||
在其中加入`libmysql.lib`
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20241222171057161.png!compress" alt="image-20241222171057161" style="zoom:50%;" />
|
||||
|
||||
### 5.编写数据库连接代码
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <mysql.h>
|
||||
|
||||
|
||||
void init_conn(MYSQL* mysql) {
|
||||
mysql_init(mysql); // 初始化 MySQL 连接
|
||||
if (!mysql_real_connect(mysql, "localhost", "root", "root", "user", 3306, NULL, CLIENT_IGNORE_SIGPIPE)) {
|
||||
printf("连接数据库时发生错误!\n");
|
||||
printf("%s\n", mysql_error(mysql));
|
||||
}else{
|
||||
printf("连接成功!\n");
|
||||
}
|
||||
}
|
||||
int main(void){
|
||||
MYSQL mysql;
|
||||
int ret = 0;
|
||||
|
||||
init_conn(&mysql);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 6.配置my.ini
|
||||
|
||||
运行代码后会发现
|
||||
|
||||
<img src="https://yp.smallkun.cn/markdown/image-20240518190612777.png!compress!compress" alt="image-20240518190612777" style="zoom:50%;" />
|
||||
|
||||
要永久地关闭 MySQL 中的 SSL 连接功能,需要进行以下步骤:
|
||||
|
||||
编辑 MySQL 配置文件 my.cnf(或 my.ini),一般位于 MySQL 安装目录的 /etc 或 /etc/mysql 子目录下。
|
||||
|
||||
并添加以下配置:
|
||||
|
||||
Windows下此文件路径在C:\ProgramData\MySQL\MySQL Server 5.7\my.ini
|
||||
|
||||
```ini
|
||||
ssl=0
|
||||
```
|
||||
|
||||
1. 保存文件并退出编辑器。
|
||||
2. 重启 MySQL 服务。
|
||||
|
||||
|
||||
|
||||
**测试连接**
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "mysql_utils.h"
|
||||
|
||||
/*
|
||||
DBConnection *db_init(const char *host, const char *user, const char *password, const char *database, unsigned int port)
|
||||
|
||||
void db_close(DBConnection *db)
|
||||
|
||||
int db_common(DBConnection *db, const char *query)
|
||||
|
||||
MYSQL_RES *db_query(DBConnection *db, const char *query)
|
||||
|
||||
void process_result(MYSQL_RES *result)
|
||||
*/
|
||||
void clearUser(DBConnection *db){
|
||||
db_common(db, "TRUNCATE users");
|
||||
printf("Çå¿Õ³É¹¦!!! \n");
|
||||
}
|
||||
|
||||
int addUser(DBConnection *db, char *username, char *password){
|
||||
char sql[100];
|
||||
sprintf(sql, "INSERT INTO users() VALUES(DEFAULT, \"%s\", \"%s\")", username, password);
|
||||
printf("%s\n", sql);
|
||||
return db_common(db, sql);
|
||||
}
|
||||
|
||||
int main(void){
|
||||
DBConnection *conn;
|
||||
|
||||
conn = db_init("localhost", "root", "root", "user", 3306);
|
||||
|
||||
//process_result(db_query(conn, "SELECT * FROM users"));
|
||||
|
||||
printf("%d\n", addUser(conn, "root", "root"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,108 @@
|
||||
#ifndef MYSQL_H
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
#ifndef STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
//对MySQL连接指针变量 创建结构体变量并取别名
|
||||
typedef struct {
|
||||
MYSQL *conn;
|
||||
} DBConnection;
|
||||
|
||||
DBConnection *db_init(const char *host, const char *user, const char *password, const char *database, unsigned int port) {
|
||||
//动态内存分配连接的地址
|
||||
DBConnection *db = (DBConnection *)malloc(sizeof(DBConnection));
|
||||
if (db == NULL) {
|
||||
printf("内存分配错误\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//对连接地址进行动态内存分配
|
||||
db->conn = mysql_init(NULL);
|
||||
if (db->conn == NULL) {
|
||||
printf("初始化失败\n");
|
||||
free(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//对连接地址进行配置
|
||||
if (mysql_real_connect(db->conn, host, user, password, database, port, NULL, 0) == NULL) {
|
||||
printf("配置连接失败: %s\n", mysql_error(db->conn));
|
||||
mysql_close(db->conn);
|
||||
free(db);
|
||||
return NULL;
|
||||
}
|
||||
mysql_set_character_set(db->conn, "GBK");//设置输入输出结果字符串为GBK
|
||||
return db;
|
||||
}
|
||||
|
||||
//关闭连接函数
|
||||
void db_close(DBConnection *db) {
|
||||
if (db != NULL) {
|
||||
if (db->conn != NULL) {
|
||||
mysql_close(db->conn);
|
||||
}
|
||||
free(db);
|
||||
}
|
||||
}
|
||||
|
||||
//更新、删除、新增 通用函数
|
||||
int db_common(DBConnection *db, const char *query) {
|
||||
if (mysql_query(db->conn, query)) {
|
||||
printf("common query failed: %s\n", mysql_error(db->conn));
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(query, "INSERT", 6) == 0) {
|
||||
return (int)mysql_insert_id(db->conn);
|
||||
}
|
||||
|
||||
return (int)mysql_affected_rows(db->conn);
|
||||
}
|
||||
|
||||
//查询通用函数
|
||||
MYSQL_RES *db_query(DBConnection *db, const char *query) {
|
||||
MYSQL_RES *result;
|
||||
if (mysql_query(db->conn, query)) {
|
||||
printf("查询失败: %s\n", mysql_error(db->conn));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = mysql_store_result(db->conn);
|
||||
if (result == NULL) {
|
||||
printf("获取查询结果失败: %s\n", mysql_error(db->conn));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//处理查询结果函数
|
||||
void process_result(MYSQL_RES *result) {
|
||||
MYSQL_ROW row;
|
||||
unsigned int num_fields;
|
||||
unsigned int i;
|
||||
|
||||
if (result == NULL) {
|
||||
fprintf(stderr, "Result set is NULL.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//获取字段数
|
||||
num_fields = mysql_num_fields(result);
|
||||
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
for (i = 0; i < num_fields; i++) {
|
||||
printf("%s\t", row[i] ? row[i] : "NULL");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
## 解决vs2010程序运行结束后关闭
|
||||
|
||||
右键项目名称->属性->链接器->系统->子系统->设置成控制台
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,106 @@
|
||||
1. **函数指针示例**:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// 声明函数指针
|
||||
int (*ptr_add)(int, int);
|
||||
|
||||
// 将 add 函数的地址赋值给函数指针
|
||||
ptr_add = add;
|
||||
|
||||
// 通过函数指针调用函数
|
||||
int result = ptr_add(5, 3);
|
||||
printf("Result: %d\n", result); // 输出: Result: 8
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
2. **指针函数示例**:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int* allocate_array(int size) {
|
||||
// 动态分配内存并返回指针
|
||||
return (int*)malloc(size * sizeof(int));
|
||||
}
|
||||
|
||||
int main() {
|
||||
// 调用指针函数获取动态分配的数组
|
||||
int* arr = allocate_array(5);
|
||||
|
||||
// 使用动态分配的数组
|
||||
for (int i = 0; i < 5; i++) {
|
||||
arr[i] = i * 2;
|
||||
printf("%d ", arr[i]);
|
||||
}
|
||||
printf("\n"); // 输出: 0 2 4 6 8
|
||||
|
||||
// 释放动态分配的内存
|
||||
free(arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
3. **回调函数示例**:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
// 回调函数的类型定义
|
||||
typedef int (*CompareFn)(int, int);
|
||||
|
||||
// 使用回调函数的排序函数
|
||||
void sort_array(int arr[], int size, CompareFn compare_fn) {
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
for (int j = 0; j < size - i - 1; j++) {
|
||||
if (compare_fn(arr[j], arr[j+1]) > 0) {
|
||||
// 使用回调函数比较元素大小
|
||||
int temp = arr[j];
|
||||
arr[j] = arr[j+1];
|
||||
arr[j+1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 升序比较函数
|
||||
int compare_ascending(int a, int b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
// 降序比较函数
|
||||
int compare_descending(int a, int b) {
|
||||
return b - a;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int numbers[] = {5, 2, 8, 1, 9};
|
||||
int size = sizeof(numbers) / sizeof(numbers[0]);
|
||||
|
||||
printf("Ascending sort:\n");
|
||||
sort_array(numbers, size, compare_ascending);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", numbers[i]); // 输出: 1 2 5 8 9
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("Descending sort:\n");
|
||||
sort_array(numbers, size, compare_descending);
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d ", numbers[i]); // 输出: 9 8 5 2 1
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,990 @@
|
||||
## 测试数据
|
||||
|
||||
```sql
|
||||
/*stu测试数据*/
|
||||
create table stu
|
||||
(
|
||||
stuNo char(6) primary key,
|
||||
stuName varchar(10) not null,
|
||||
stuSex char(2) not null,
|
||||
stuAge tinyint not null ,
|
||||
stuSeat tinyint not null,
|
||||
stuAddress varchar(10) not null,
|
||||
ch tinyint,
|
||||
math tinyint
|
||||
);
|
||||
|
||||
|
||||
insert into stu values ('s25301','张秋丽','男',18,1,'北京',80,null);
|
||||
insert into stu values ('s25302','李文才','男',31,3,'上海',77,76);
|
||||
insert into stu values ('s25303','李斯文','女',22,2,'北京',55,82);
|
||||
insert into stu values ('s25304','欧阳俊雄','男',28,4,'天津',null,74);
|
||||
insert into stu values ('s25305','诸葛丽丽','女',23,7,'河南',72,56);
|
||||
insert into stu values ('s25318','争青小子','男',26,6,'天津',86,92);
|
||||
insert into stu values ('s25319','梅超风','女',23,5,'河北',74,67);
|
||||
|
||||
insert into stu values ('s25320','Tom','男',24,8,'北京',65,67);
|
||||
insert into stu values ('s25321','Tabm','女',23,9,'河北',88,77);
|
||||
|
||||
/*stuinfo测试数据*/
|
||||
create table stuinfo
|
||||
(
|
||||
stuNo char(6) primary key,
|
||||
stuName varchar(10) not null,
|
||||
stuSex char(2) not null,
|
||||
stuAge tinyint not null ,
|
||||
stuSeat tinyint not null,
|
||||
stuAddress varchar(10) not null
|
||||
);
|
||||
|
||||
|
||||
insert into stuinfo values ('s25301','张秋丽','男',18,1,'北京');
|
||||
insert into stuinfo values ('s25302','李文才','男',31,3,'上海');
|
||||
insert into stuinfo values ('s25303','李斯文','女',22,2,'北京');
|
||||
insert into stuinfo values ('s25304','欧阳俊雄','男',28,4,'天津');
|
||||
insert into stuinfo values ('s25305','诸葛丽丽','女',23,7,'河南');
|
||||
insert into stuinfo values ('s25318','争青小子','男',26,6,'天津');
|
||||
insert into stuinfo values ('s25319','梅超风','女',23,5,'河北');
|
||||
|
||||
/*stuMarks测试数据*/
|
||||
|
||||
create table stuMarks
|
||||
(
|
||||
examNo char(7) primary key,
|
||||
stuNo char(6) not null ,
|
||||
writtenExam int,
|
||||
labExam int
|
||||
);
|
||||
|
||||
insert into stumarks values ('s271811','s25303',80,58);
|
||||
insert into stumarks values ('s271813','s25302',50,90);
|
||||
insert into stumarks values ('s271815','s25304',65,50);
|
||||
insert into stumarks values ('s271816','s25301',77,82);
|
||||
insert into stumarks values ('s271819','s25318',56,48);
|
||||
insert into stumarks values ('s271820','s25320',66,77);
|
||||
```
|
||||
|
||||
## 1.1 今日目标
|
||||
|
||||
1. 理解实体之间的关系
|
||||
2. 理解绘制E-R图
|
||||
3. 理解三范式
|
||||
4. 理解范式和性能的关系
|
||||
5. 能够查询表中的数据
|
||||
6. 理解聚合函数
|
||||
7. 理解模糊查询
|
||||
8. 理解分组查询
|
||||
|
||||
## 1.2 数据库基本概念
|
||||
|
||||
1、关系:两个表的公共字段
|
||||
|
||||
2、行:也称记录,也称实体
|
||||
|
||||
3、列:也称字段,也称属性
|
||||
|
||||
```
|
||||
就表结构而言,表分为行和列;
|
||||
就表数据而言,分为记录和字段;
|
||||
就面向对象而言,一个记录就是一个实体,一个字段就是一个属性。
|
||||
```
|
||||
|
||||
4、数据冗余:相同的数据存储在不同的地方
|
||||
|
||||
```
|
||||
脚下留心:
|
||||
1、冗余只能减少,不能杜绝。
|
||||
2、减少冗余的方法是分表
|
||||
3、为减少数据查找的麻烦,允许数据有一定的冗余
|
||||
```
|
||||
|
||||
5、数据完整性:正确性+准确性=数据完整性
|
||||
|
||||
```
|
||||
正确性:数据类型正确
|
||||
准确性:数据范围要准确
|
||||
```
|
||||
|
||||
思考:学生的年龄是整型,输入1000岁,正确性和准确性如何?
|
||||
|
||||
答:正确的,但不准确
|
||||
|
||||
思考:年龄是整形的,收入了字符串,正确性和准确性如何?
|
||||
|
||||
答:不正确
|
||||
|
||||
|
||||
|
||||
## 1.3 实体和实体之间的关系
|
||||
|
||||
1、一对一
|
||||
|
||||
2、一对多 (多对一)
|
||||
|
||||
3、多对多 
|
||||
|
||||
|
||||
|
||||
#### 1.3.1 一对多 1:N
|
||||
|
||||
1、主表中的一条记录对应从表中的多条记录。
|
||||
|
||||
2、一对多和多对一是一样的
|
||||
|
||||

|
||||
|
||||
如何实现一对多?
|
||||
|
||||
答:主键和非主键建关系
|
||||
|
||||
问题:说出几个一对多的关系?
|
||||
|
||||
答:班级表和学生表、 班主表和学生表
|
||||
|
||||
|
||||
|
||||
#### 1.3.2 一对一(1:1)
|
||||
|
||||
1、主表中的一条记录对应从表中的一条记录
|
||||
|
||||

|
||||
|
||||
如何实现一对一?
|
||||
|
||||
主键和主键建关系就能实现一对一。
|
||||
|
||||
```
|
||||
思考:一对一两个表完全可以用一个表实现,为什么还要分成两个表?
|
||||
|
||||
答:在字段数量很多情况下,数据量也就很大,每次查询都需要检索大量数据,这样效率低下。我们可以将所有字段分成两个部分,“常用字段”和“不常用字段”,这样对大部分查询者来说效率提高了。【表的垂直分割】
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 1.3.3 多对多(N:M)
|
||||
|
||||
主表中的一条记录对应从表中的多条记录,从表中的一条记录对应主表中的多条记录
|
||||
|
||||
班级和讲师的关系
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
如何实现多对多?
|
||||
|
||||
答:建立第三张表来保存关系。
|
||||
|
||||
问题:说出几个多对多的关系?
|
||||
|
||||
1、科目表和学生表的关系 2、商品表和订单表 3、游戏目录表和玩家表
|
||||
|
||||
|
||||
|
||||
## 1.4 数据库设计的步骤
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.4.1 数据库设计具体步骤
|
||||
|
||||
1、 收集信息:与该系统有关人员进行交流、坐谈,充分理解数据库需要完成的任务
|
||||
|
||||
2、 标识对象(实体-Entity)标识数据库要管理的关键对象或实体
|
||||
|
||||
3、 标识每个实体的属性(Attribute)
|
||||
|
||||
4、 标识对象之间的关系(Relationship)
|
||||
|
||||
5、 将模型转换成数据库
|
||||
|
||||
6、 规范化
|
||||
|
||||
#### 1.4.2 绘制E-R图
|
||||
|
||||
E-R(Entity-Relationship)实体关系图
|
||||
|
||||
E-R图的语法
|
||||
|
||||

|
||||
|
||||
绘制E-R图
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.4.3 将E-R图转成表
|
||||
|
||||
1、 实体转成表,属性转成字段
|
||||
|
||||
2、 如果没有合适的字段做主键,给表添加一个自动增长列做主键。
|
||||
|
||||
|
||||
|
||||
#### 1.4.4 例题
|
||||
|
||||
1、项目需求
|
||||
|
||||
```
|
||||
BBS论坛的基本功能:
|
||||
用户注册和登录,后台数据库需要存放用户的注册信息和在线状态信息;
|
||||
用户发贴,后台数据库需要存放贴子相关信息,如贴子内容、标题等;
|
||||
用户可以对发帖进行回复;
|
||||
论坛版块管理:后台数据库需要存放各个版块信息,如版主、版块名称、贴子数等;
|
||||
```
|
||||
|
||||
2、标识对象
|
||||
|
||||
```
|
||||
参与的对象有:用户、发的帖子、跟帖、板块
|
||||
```
|
||||
|
||||
3、标识对象的属性
|
||||
|
||||

|
||||
|
||||
4、建立关系,绘制E-R图
|
||||
|
||||

|
||||
|
||||
5、将E-R图转出表结构
|
||||
|
||||
|
||||
|
||||
## 1.5 数据规范化
|
||||
|
||||
Codd博士定义了6个范式来规范化数据库,范式由小到大来约束,范式越高冗余越小,但表的个数也越多。实验证明,三范式是性价比最高的。
|
||||
|
||||
#### 1.5.1 第一范式:确保每列原子性
|
||||
|
||||
第一范式确保每个字段不可再分
|
||||
|
||||

|
||||
|
||||
思考:如下表设计是否合理?
|
||||
|
||||

|
||||
|
||||
不合理。不满足第一范式,上课时间可以再分
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
思考:地址包含省、市、县、地区是否需要拆分?
|
||||
|
||||
答:如果仅仅起地址的作用,不需要统计,可以不拆分;如果有按地区统计的功能需要拆分。
|
||||
|
||||
在实际项目中,建议拆分。
|
||||
|
||||
|
||||
|
||||
#### 1.5.2 第二范式:非键字段必须依赖于键字段
|
||||
|
||||
一个表只能描述一件事
|
||||
|
||||

|
||||
|
||||
思考:如下表设计是否合理?
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 1.5.3 第三范式:消除传递依赖
|
||||
|
||||
在所有的非键字段中,不能有传递依赖
|
||||
|
||||

|
||||
|
||||
下列设计是否满足第三范式?
|
||||
|
||||

|
||||
|
||||
不满足,因为语文和数学确定了,总分就确定了。
|
||||
|
||||
```
|
||||
多学一招:上面的设计不满足第三范式,但是高考分数表就是这样设计的,为什么?
|
||||
|
||||
答:高考分数峰值访问量非常大,这时候就是性能更重要。当性能和规范化冲突的时候,我们首选性能。这就是“反三范式”。
|
||||
```
|
||||
|
||||
#### 1.5.4 数据库设计的例题
|
||||
|
||||
1、需求
|
||||
|
||||
```
|
||||
公司承担多个工程项目,每一项工程有:工程号、工程名称、施工人员等
|
||||
公司有多名职工,每一名职工有:职工号、姓名、性别、职务(工程师、技术员)等
|
||||
公司按照工时和小时工资率支付工资,小时工资率由职工的职务决定(例如,技术员的小时工资率与工程师不同)
|
||||
```
|
||||
|
||||
2、工资表
|
||||
|
||||

|
||||
|
||||
3、将工资表转成数据库表
|
||||
|
||||

|
||||
|
||||
4、这个表存在的问题
|
||||
|
||||
```
|
||||
A:新人入职需要虚拟一个项目
|
||||
|
||||
B:职务更改,小时工资率可能会忘记更改,造成数据不完整
|
||||
|
||||
C:有人离职,删除记录后,工程也没有了
|
||||
```
|
||||
|
||||
5、规范化表
|
||||
|
||||
```
|
||||
第一步:这个表满足第一范式
|
||||
|
||||
第二步:这个表不是描述了一件事情
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
```
|
||||
第三步:是否满足第三范式
|
||||
```
|
||||
|
||||

|
||||
|
||||
更改如下:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 1.6 查询语句
|
||||
|
||||
```sql
|
||||
语法:select [选项] 列名 [from 表名] [where 条件] [group by 分组] [order by 排序][having 条件] [limit 限制]
|
||||
```
|
||||
|
||||
#### 1.6.1 字段表达式
|
||||
|
||||
```sql
|
||||
mysql> select '锄禾日当午';
|
||||
+------------+
|
||||
| 锄禾日当午 |
|
||||
+------------+
|
||||
| 锄禾日当午 |
|
||||
+------------+
|
||||
|
||||
mysql> select 10*10;
|
||||
+-------+
|
||||
| 10*10 |
|
||||
+-------+
|
||||
| 100 |
|
||||
+-------+
|
||||
```
|
||||
|
||||
通过as给字段取别名
|
||||
|
||||
```sql
|
||||
mysql> select '锄禾日当午' as content;
|
||||
+------------+
|
||||
| content |
|
||||
+------------+
|
||||
| 锄禾日当午 |
|
||||
+------------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> select 10*10 as result;
|
||||
+--------+
|
||||
| result |
|
||||
+--------+
|
||||
| 100 |
|
||||
+--------+
|
||||
1 row in set (0.00 sec)
|
||||
```
|
||||
|
||||
多学一招:as可以省略
|
||||
|
||||
```sql
|
||||
mysql> select 10*10 result;
|
||||
+--------+
|
||||
| result |
|
||||
+--------+
|
||||
| 100 |
|
||||
+--------+
|
||||
1 row in set (0.00 sec)
|
||||
```
|
||||
|
||||
#### 1.6.2 from子句
|
||||
|
||||
from:来自,from后面跟的是数据源。数据源可以有多个。返回笛卡尔积。
|
||||
|
||||
插入测试表
|
||||
|
||||
```sql
|
||||
mysql> create table t1(
|
||||
-> id int,
|
||||
-> name varchar(10)
|
||||
-> );
|
||||
Query OK, 0 rows affected (0.05 sec)
|
||||
|
||||
mysql> create table t2(
|
||||
-> field1 varchar(10),
|
||||
-> field2 varchar(10)
|
||||
-> );
|
||||
Query OK, 0 rows affected (0.00 sec)
|
||||
|
||||
mysql> insert into t1 values (1,'tom'),(2,'berry');
|
||||
Query OK, 2 rows affected (0.00 sec)
|
||||
Records: 2 Duplicates: 0 Warnings: 0
|
||||
|
||||
mysql> insert into t2 values ('333','333'),('444','444');
|
||||
Query OK, 2 rows affected (0.02 sec)
|
||||
Records: 2 Duplicates: 0 Warnings: 0
|
||||
```
|
||||
|
||||
测试多个数据源
|
||||
|
||||
```sql
|
||||
mysql> select * from t1,t2; # 返回笛卡尔积
|
||||
+------+-------+--------+--------+
|
||||
| id | name | field1 | field2 |
|
||||
+------+-------+--------+--------+
|
||||
| 1 | tom | 333 | 333 |
|
||||
| 2 | berry | 333 | 333 |
|
||||
| 1 | tom | 444 | 444 |
|
||||
| 2 | berry | 444 | 444 |
|
||||
+------+-------+--------+--------+
|
||||
4 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
#### 1.6.3 dual表
|
||||
|
||||
dual表是一个伪表。在有些特定情况下,没有具体的表的参与,但是为了保证select语句的完整又必须要一个表名,这时候就使用伪表。
|
||||
|
||||
```sql
|
||||
mysql> select 10*10 as result from dual; #dual表是用来保证select语句的完整性。
|
||||
+--------+
|
||||
| result |
|
||||
+--------+
|
||||
| 100 |
|
||||
+--------+
|
||||
```
|
||||
|
||||
#### 1.6.4 where子句
|
||||
|
||||
where后面跟的是条件,在数据源中进行筛选。返回条件为真记录
|
||||
|
||||
MySQL支持的运算符
|
||||
|
||||
1. `>` 大于
|
||||
2. `<`小于
|
||||
3. `>=`
|
||||
4. `<=`
|
||||
5. `=`
|
||||
6. `!=`
|
||||
7. and 与
|
||||
8. or 或
|
||||
9. not 非
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stusex='男'; # 查找性别是男的记录
|
||||
mysql> select * from stu where stuage>=20; # 查找年龄不低于20的记录
|
||||
```
|
||||
|
||||
思考:如下代码输出什么
|
||||
|
||||
```sql
|
||||
select * from stu where 1 # 返回所有数据库
|
||||
select * from stu where 0 #返回空记录
|
||||
```
|
||||
|
||||
思考:如何查找北京和上海的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuaddress='上海' or stuaddress='北京';
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
| s25302 | 李文才 | 男 | 31 | 3 | 上海 | 77 | 76 |
|
||||
| s25303 | 李斯文 | 女 | 22 | 2 | 北京 | 55 | 82 |
|
||||
| s25320 | Tom | 男 | 24 | 8 | 北京 | 65 | 67 |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
```
|
||||
|
||||
#### 1.6.5 in | not in
|
||||
|
||||
上面的查询上海和北京的学生的SQL可以通过in语句来实现
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuaddress in ('北京','上海');
|
||||
```
|
||||
|
||||
练习:
|
||||
|
||||
1、查找学号是s25301,s25302,s25303的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuno in ('s25301','s25302','s25303');
|
||||
```
|
||||
|
||||
2、查找年龄是18,19,20的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuage in(18,19,20);
|
||||
```
|
||||
|
||||
3、查找不是北京和上海的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuaddress not in ('北京','上海');
|
||||
```
|
||||
|
||||
#### 1.6.6 between…and|not between…and
|
||||
|
||||
查找某个范围的记录
|
||||
|
||||
1、查找年龄在18~20之间的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuage>=18 and stuage<=20; # 方法一
|
||||
|
||||
mysql> select * from stu where stuage between 18 and 20; # 方法二
|
||||
```
|
||||
|
||||
2、查找年龄不在18~20之间的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stuage<18 or stuage>20; #方法一
|
||||
|
||||
mysql> select * from stu where not (stuage>=18 and stuage<=20);
|
||||
|
||||
mysql> select * from stu where stuage not between 18 and 20;
|
||||
```
|
||||
|
||||
#### 1.6.7 is null | is not null
|
||||
|
||||
脚下留心:查询一个为空的字段不能用等于,必须用is null
|
||||
|
||||
查找缺考的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where ch is null or math is null; # 查找缺考的人
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
| s25304 | 欧阳俊雄 | 男 | 28 | 4 | 天津 | NULL | 74 |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
```
|
||||
|
||||
查找参加考试的学生
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where ch is not null and math is not null;
|
||||
```
|
||||
|
||||
#### 1.6.8 聚合函数
|
||||
|
||||
1. sum() 求和
|
||||
2. avg() 求平均值
|
||||
3. max() 求最大值
|
||||
4. min() 求最小值
|
||||
5. count() 求记录数
|
||||
|
||||
```sql
|
||||
#求语文总分、语文平均分、语文最高分、语文最低分、总人数
|
||||
|
||||
mysql> select sum(ch) '语文总分',avg(ch) '语文平均分', max(ch) '语文最高分',min(ch) '语文最低分',count(*) '总人数' from stu;
|
||||
+----------+------------+------------+------------+--------+
|
||||
| 语文总分 | 语文平均分 | 语文最高分 | 语文最低分 | 总人数 |
|
||||
|
||||
+----------+------------+------------+------------+--------+
|
||||
| 597 | 74.6250 | 88 | 55 | 9 |
|
||||
+----------+------------+------------+------------+--------+
|
||||
1 row in set (0.00 sec)
|
||||
```
|
||||
|
||||
#### 1.6.9 通配符
|
||||
|
||||
1. _ [下划线] 表示任意一个字符
|
||||
2. % 表示任意字符
|
||||
|
||||
练习
|
||||
|
||||
1、满足“T_m”的有(A、C)
|
||||
|
||||
A:Tom B:Toom C:Tam D:Tm E:Tmo
|
||||
|
||||
2、满足“T_m_”的有(B、C )
|
||||
|
||||
A:Tmom B:Tmmm C:T1m2 D:Tmm E:Tm
|
||||
|
||||
3、满足“张%”的是(A、B、C、D)
|
||||
|
||||
A:张三 B:张三丰 C:张牙舞爪 D:张 E:小张
|
||||
|
||||
4、满足“%诺基亚%”的是(A、B、C、D)
|
||||
|
||||
A:诺基亚2100 B:2100诺基亚 C:把我的诺基亚拿过来 D:诺基亚
|
||||
|
||||
#### 16.10 模糊查询(like)
|
||||
|
||||
```sql
|
||||
# 查找姓张的同学
|
||||
mysql> select * from stu where stuname like '张%';
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
1 row in set (0.00 sec)
|
||||
#例题
|
||||
mysql> select * from stu where stuname like 'T_m';
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| s25320 | Tom | 男 | 24 | 8 | 北京 | 65 | 67 |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
1 row in set (0.00 sec)
|
||||
```
|
||||
|
||||
#### 1.6.11 order by排序
|
||||
|
||||
asc:升序【默认】
|
||||
|
||||
desc:降序
|
||||
|
||||
```sql
|
||||
mysql> select * from stu order by ch desc; # 语文成绩降序排列
|
||||
|
||||
mysql> select * from stu order by math asc; # 数学成绩升序排列
|
||||
|
||||
mysql> select * from stu order by math; # 默认升序排列
|
||||
```
|
||||
|
||||
多列排序
|
||||
|
||||
```sql
|
||||
#年龄升序,成绩降序
|
||||
mysql> select *,(ch+math) as '总分' from stu order by stuage asc,(ch+math) desc;
|
||||
```
|
||||
|
||||
思考如下代码表示什么含义
|
||||
|
||||
```sql
|
||||
select * from stu order by stuage desc,ch desc; #年龄降序,语文降序
|
||||
select * from stu order by stuage desc,ch asc; #年龄降序,语文升序
|
||||
select * from stu order by stuage,ch desc; #年龄升序、语文降序
|
||||
select * from stu order by stuage,ch; #年龄升序、语文升序
|
||||
```
|
||||
|
||||
#### 1.6.12 group by 【分组查询】
|
||||
|
||||
将查询的结果分组,分组查询目的在于统计数据。
|
||||
|
||||
```sql
|
||||
# 按性别分组,显示每组的平均年龄
|
||||
mysql> select avg(stuage) as '年龄',stusex from stu group by stusex;
|
||||
+---------+--------+
|
||||
| 年龄 | stusex |
|
||||
+---------+--------+
|
||||
| 22.7500 | 女 |
|
||||
| 25.4000 | 男 |
|
||||
+---------+--------+
|
||||
2 rows in set (0.00 sec)
|
||||
# 按地区分组,每个地区的平均年龄
|
||||
mysql> select avg(stuage) as '年龄',stuaddress from stu group by stuaddress;
|
||||
+---------+------------+
|
||||
| 年龄 | stuaddress |
|
||||
+---------+------------+
|
||||
| 31.0000 | 上海 |
|
||||
| 21.3333 | 北京 |
|
||||
| 27.0000 | 天津 |
|
||||
| 23.0000 | 河北 |
|
||||
| 23.0000 | 河南 |
|
||||
+---------+------------+
|
||||
5 rows in set (0.00 sec)
|
||||
脚下留心:
|
||||
1、如果是分组查询,查询字段必须是分组字段和聚合函数。
|
||||
2、查询字段是普通字段,只取第一个值
|
||||
```
|
||||
|
||||

|
||||
|
||||
通过group_concat()函数将同一组的值连接起来显示
|
||||
|
||||
```sql
|
||||
mysql> select group_concat(stuname),stusex from stu group by stusex;
|
||||
+-------------------------------------+--------+
|
||||
| group_concat(stuname) | stusex |
|
||||
+-------------------------------------+--------+
|
||||
| 李斯文,诸葛丽丽,梅超风,Tabm | 女 |
|
||||
| 张秋丽,李文才,欧阳俊雄,争青小子,Tom | 男 |
|
||||
+-------------------------------------+--------+
|
||||
2 rows in set (0.00 sec)
|
||||
多学一招:【了解】
|
||||
1、分组后的结果默认会按升序排列显示
|
||||
2、也是可以使用desc实现分组后的降序
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
多列分组
|
||||
|
||||
```sql
|
||||
mysql> select stuaddress,stusex,avg(stuage) from stu group by stuaddress,stusex;
|
||||
+------------+--------+-------------+
|
||||
| stuaddress | stusex | avg(stuage) |
|
||||
+------------+--------+-------------+
|
||||
| 上海 | 男 | 31.0000 |
|
||||
| 北京 | 女 | 22.0000 |
|
||||
| 北京 | 男 | 21.0000 |
|
||||
| 天津 | 男 | 27.0000 |
|
||||
| 河北 | 女 | 23.0000 |
|
||||
| 河南 | 女 | 23.0000 |
|
||||
+------------+--------+-------------+
|
||||
6 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
#### 1.6.13 having条件
|
||||
|
||||
```
|
||||
思考:数据库中的表是一个二维表,返回的结果是一张二维表,既然能在数据库的二维表中进行查询,能否在结果集的二维表上继续进行查询?
|
||||
|
||||
答:可以,having条件就是在结果集上继续进行筛选。
|
||||
```
|
||||
|
||||
例题
|
||||
|
||||
```sql
|
||||
mysql> select * from stu where stusex='男'; # 从数据库中查找
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
| s25302 | 李文才 | 男 | 31 | 3 | 上海 | 77 | 76 |
|
||||
| s25304 | 欧阳俊雄 | 男 | 28 | 4 | 天津 | NULL | 74 |
|
||||
| s25318 | 争青小子 | 男 | 26 | 6 | 天津 | 86 | 92 |
|
||||
| s25320 | Tom | 男 | 24 | 8 | 北京 | 65 | 67 |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
5 rows in set (0.00 sec)
|
||||
|
||||
mysql> select * from stu having stusex='男'; # 从结果集中查找
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
| s25302 | 李文才 | 男 | 31 | 3 | 上海 | 77 | 76 |
|
||||
| s25304 | 欧阳俊雄 | 男 | 28 | 4 | 天津 | NULL | 74 |
|
||||
| s25318 | 争青小子 | 男 | 26 | 6 | 天津 | 86 | 92 |
|
||||
| s25320 | Tom | 男 | 24 | 8 | 北京 | 65 | 67 |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
5 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
思考如下语句是否正确 
|
||||
|
||||

|
||||
|
||||
having和where的区别:
|
||||
|
||||
where是对原始数据进行筛选,having是对记录集进行筛选。
|
||||
|
||||
#### 1.6.14 limit
|
||||
|
||||
语法:limit 起始位置,显示长度
|
||||
|
||||
```sql
|
||||
mysql> select * from stu limit 0,2; # 从0的位置开始,取两条数据
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
| s25302 | 李文才 | 男 | 31 | 3 | 上海 | 77 | 76 |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
2 rows in set (0.00 sec)
|
||||
|
||||
mysql> select * from stu limit 2,2; # 从2的位置开始,取两条数据
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
| s25303 | 李斯文 | 女 | 22 | 2 | 北京 | 55 | 82 |
|
||||
| s25304 | 欧阳俊雄 | 男 | 28 | 4 | 天津 | NULL | 74 |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+
|
||||
```
|
||||
|
||||
起始位置可以省略,默认是从0开始
|
||||
|
||||
```sql
|
||||
mysql> select * from stu limit 2;
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
| s25301 | 张秋丽 | 男 | 18 | 1 | 北京 | 80 | NULL |
|
||||
| s25302 | 李文才 | 男 | 31 | 3 | 上海 | 77 | 76 |
|
||||
+--------+---------+--------+--------+---------+------------+------+------+
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
例题:找出班级总分前三名
|
||||
|
||||
```sql
|
||||
mysql> select *,(ch+math) total from stu order by total desc limit 0,3;
|
||||
+--------+----------+--------+--------+---------+------------+------+------+-------+
|
||||
| stuNo | stuName | stuSex | stuAge | stuSeat | stuAddress | ch | math | total |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+-------+
|
||||
| s25318 | 争青小子 | 男 | 26 | 6 | 天津 | 86 | 92 | 178 |
|
||||
| s25321 | Tabm | 女 | 23 | 9 | 河北 | 88 | 77 | 165 |
|
||||
| s25302 | 李文才 | 男 | 31 | 3 | 上海 | 77 | 76 | 153 |
|
||||
+--------+----------+--------+--------+---------+------------+------+------+-------+
|
||||
```
|
||||
|
||||
多学一招:limit在update和delete语句中也是可以使用的。
|
||||
|
||||
#### 1.6.15 查询语句中的选项
|
||||
|
||||
查询语句中的选项有两个:
|
||||
|
||||
1、 all:显示所有数据 【默认】
|
||||
|
||||
2、 distinct:去除结果集中重复的数据
|
||||
|
||||
```sql
|
||||
mysql> select distinct stuaddress from stu;
|
||||
+------------+
|
||||
| stuaddress |
|
||||
+------------+
|
||||
| 上海 |
|
||||
| 天津 |
|
||||
| 河南 |
|
||||
| 河北 |
|
||||
| 北京 |
|
||||
+------------+
|
||||
5 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
## 1.7 union(联合)
|
||||
|
||||
插入测试数据
|
||||
|
||||
```sql
|
||||
mysql> create table GO1(
|
||||
-> id int primary key,
|
||||
-> name varchar(20));
|
||||
Query OK, 0 rows affected (0.06 sec)
|
||||
|
||||
mysql> insert into Go1 values (1,'李白'),(2,'张秋丽');
|
||||
Query OK, 2 rows affected (0.02 sec)
|
||||
Records: 2 Duplicates: 0 Warnings: 0
|
||||
```
|
||||
|
||||
#### 1.7.1 union的使用
|
||||
|
||||
作用:将多个select语句结果集纵向联合起来
|
||||
|
||||
```sql
|
||||
语法:select 语句 union [选项] select 语句 union [选项] select 语句
|
||||
mysql> select stuno,stuname from stu union select id,name from Go1;
|
||||
+--------+----------+
|
||||
| stuno | stuname |
|
||||
+--------+----------+
|
||||
| s25301 | 张秋丽 |
|
||||
| s25302 | 李文才 |
|
||||
| s25303 | 李斯文 |
|
||||
| s25304 | 欧阳俊雄 |
|
||||
| s25305 | 诸葛丽丽 |
|
||||
| s25318 | 争青小子 |
|
||||
| s25319 | 梅超风 |
|
||||
| s25320 | Tom |
|
||||
| s25321 | Tabm |
|
||||
| 1 | 李白 |
|
||||
| 2 | 张秋丽 |
|
||||
+--------+----------+
|
||||
```
|
||||
|
||||
例题:查询上海的男生和北京的女生
|
||||
|
||||
```sql
|
||||
mysql> select stuname,stuaddress,stusex from stu where (stuaddress='上海' and stusex='男') or (stuaddress='北京' and stusex='女');
|
||||
+---------+------------+--------+
|
||||
| stuname | stuaddress | stusex |
|
||||
+---------+------------+--------+
|
||||
| 张秋丽 | 上海 | 男 |
|
||||
| 梅超风 | 北京 | 女 |
|
||||
+---------+------------+--------+
|
||||
2 rows in set (0.00 sec)
|
||||
|
||||
mysql> select stuname,stuaddress,stusex from stu where stuaddress='上海' and stusex='男' union select stuname,stuaddress,stusex from stu where stuaddress='北京' and stusex='女';
|
||||
+---------+------------+--------+
|
||||
| stuname | stuaddress | stusex |
|
||||
+---------+------------+--------+
|
||||
| 张秋丽 | 上海 | 男 |
|
||||
| 梅超风 | 北京 | 女 |
|
||||
+---------+------------+--------+
|
||||
2 rows in set (0.02 sec)
|
||||
```
|
||||
|
||||
#### 1.7.2 union的选项
|
||||
|
||||
union的选项有两个
|
||||
|
||||
1、 all:显示所有数据
|
||||
|
||||
2、 distinct:去除重复的数据【默认】
|
||||
|
||||
```sql
|
||||
mysql> select name from go1 union select stuname from stu;
|
||||
+----------+
|
||||
| name |
|
||||
+----------+
|
||||
| 李白 |
|
||||
| 张秋丽 |
|
||||
| 李文才 |
|
||||
| 李斯文 |
|
||||
| 欧阳俊雄 |
|
||||
| 诸葛丽丽 |
|
||||
| 争青小子 |
|
||||
| 梅超风 |
|
||||
| Tom |
|
||||
| Tabm |
|
||||
+----------+
|
||||
```
|
||||
|
||||
默认是去重复的
|
||||
|
||||
```sql
|
||||
mysql> select name from go1 union all select stuname from stu; # all不去重复记录
|
||||
+----------+
|
||||
| name |
|
||||
+----------+
|
||||
| 李白 |
|
||||
| 张秋丽 |
|
||||
| 张秋丽 |
|
||||
| 李文才 |
|
||||
| 李斯文 |
|
||||
| 欧阳俊雄 |
|
||||
| 诸葛丽丽 |
|
||||
| 争青小子 |
|
||||
| 梅超风 |
|
||||
| Tom |
|
||||
| Tabm |
|
||||
+----------+
|
||||
```
|
||||
|
||||
#### 1.7.3 union的注意事项
|
||||
|
||||
1、 union两边的select语句的字段个数必须一致
|
||||
|
||||
2、 union两边的select语句的字段名可以不一致,最终按第一个select语句的字段名。
|
||||
|
||||
3、 union两边的select语句中的数据类型可以不一致。
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1054
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,61 @@
|
||||
/*stu测试数据*/
|
||||
create table stu
|
||||
(
|
||||
stuNo char(6) primary key,
|
||||
stuName varchar(10) not null,
|
||||
stuSex char(2) not null,
|
||||
stuAge tinyint not null ,
|
||||
stuSeat tinyint not null,
|
||||
stuAddress varchar(10) not null,
|
||||
ch tinyint,
|
||||
math tinyint
|
||||
);
|
||||
|
||||
|
||||
insert into stu values ('s25301','张秋丽','男',18,1,'北京',80,null);
|
||||
insert into stu values ('s25302','李文才','男',31,3,'上海',77,76);
|
||||
insert into stu values ('s25303','李斯文','女',22,2,'北京',55,82);
|
||||
insert into stu values ('s25304','欧阳俊雄','男',28,4,'天津',null,74);
|
||||
insert into stu values ('s25305','诸葛丽丽','女',23,7,'河南',72,56);
|
||||
insert into stu values ('s25318','争青小子','男',26,6,'天津',86,92);
|
||||
insert into stu values ('s25319','梅超风','女',23,5,'河北',74,67);
|
||||
|
||||
insert into stu values ('s25320','Tom','男',24,8,'北京',65,67);
|
||||
insert into stu values ('s25321','Tabm','女',23,9,'河北',88,77);
|
||||
|
||||
/*stuinfo测试数据*/
|
||||
create table stuinfo
|
||||
(
|
||||
stuNo char(6) primary key,
|
||||
stuName varchar(10) not null,
|
||||
stuSex char(2) not null,
|
||||
stuAge tinyint not null ,
|
||||
stuSeat tinyint not null,
|
||||
stuAddress varchar(10) not null
|
||||
);
|
||||
|
||||
|
||||
insert into stuinfo values ('s25301','张秋丽','男',18,1,'北京');
|
||||
insert into stuinfo values ('s25302','李文才','男',31,3,'上海');
|
||||
insert into stuinfo values ('s25303','李斯文','女',22,2,'北京');
|
||||
insert into stuinfo values ('s25304','欧阳俊雄','男',28,4,'天津');
|
||||
insert into stuinfo values ('s25305','诸葛丽丽','女',23,7,'河南');
|
||||
insert into stuinfo values ('s25318','争青小子','男',26,6,'天津');
|
||||
insert into stuinfo values ('s25319','梅超风','女',23,5,'河北');
|
||||
|
||||
/*stuMarks测试数据*/
|
||||
|
||||
create table stuMarks
|
||||
(
|
||||
examNo char(7) primary key,
|
||||
stuNo char(6) not null ,
|
||||
writtenExam int,
|
||||
labExam int
|
||||
);
|
||||
|
||||
insert into stumarks values ('s271811','s25303',80,58);
|
||||
insert into stumarks values ('s271813','s25302',50,90);
|
||||
insert into stumarks values ('s271815','s25304',65,50);
|
||||
insert into stumarks values ('s271816','s25301',77,82);
|
||||
insert into stumarks values ('s271819','s25318',56,48);
|
||||
insert into stumarks values ('s271820','s25320',66,77);
|
||||
Reference in New Issue
Block a user