精华内容
下载资源
问答
  • 下面表示段定义结束的命令是
    千次阅读
    2021-08-08 15:43:55

    本文为由C语言中文网-C语言预处理命令(宏定义和条件编译)学习摘录笔记,如侵权即删之。

    预处理命令

    在编译和链接之前,还需要对源文件进行一些文本方面的操作,比如文本替换、文件包含、删除部分代码等,这个过程叫做预处理,由预处理程序完成。

    预处理命令是什么?

    以#号开头的命令称为预处理命令。

    在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理、提前处理)。

    预处理主要是处理以#开头的命令,例如#include <stdio.h>等。预处理命令要放在所有函数之外,而且一般都放在源文件的前面。

    #include的用法详解

    #include 的用法有两种,如下所示:

    #include <stdHeader.h>
    #include “myHeader.h”

    使用尖括号< >和双引号" "的区别在于头文件的搜索路径不同:

    • 使用尖括号< >,编译器会到系统路径下查找头文件;
    • 而使用双引号" ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。

    也就是说,使用双引号比使用尖括号多了一个查找路径,它的功能更为强大。

    不管是标准头文件,还是自定义头文件,都只能包含变量和函数的声明,不能包含定义,否则在多次引入时会引起重复定义错误。

    #define的用法 宏定义

    #define叫做宏定义命令,它也是C语言预处理命令的一种。所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。
    例:

    #include <stdio.h>
    #define N 100//宏定义,N为宏名,100是宏的内容
    
    int main(){
        int sum = 20 + N;
        printf("%d\n", sum);//运行结果为120
        return 0;
    }
    

    宏定义的一般形式为:

    #define 宏名 字符串

    #表示这是一条预处理命令,所有的预处理命令都以# 开头。

    宏名是标识符的一种,命名规则和变量相同。(可由字母、数字、下划线构成,只能以字母、下划线开头)

    字符串可以是数字、表达式、if 语句、函数等。

    • 对 #define 用法的几点说明
    1. 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单粗暴的替换。字符串中可以含任何字符,它可以是常数、表达式、if 语句、函数等,预处理程序对它不作任何检查,如有错误,只能在编译已被宏展开后的源程序时发现。

    2. 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换。

    3. 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。例如:

    #define PI 3.14159
    
    int main(){
        // Code
        return 0;
    }
    
    #undef PI
    
    void func(){
        // Code
    }
    

    表示 PI 只在 main() 函数中有效,在 func() 中无效。

    1. 代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替,例如:
    #include <stdio.h>
    #define OK 100
    int main(){
        printf("OK\n");//运行结果:OK
        return 0;
    }
    

    该例中定义宏名 OK 表示 100,但在 printf 语句中 OK 被引号括起来,因此不作宏替换,而作为字符串处理。

    1. 宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名,在宏展开时由预处理程序层层代换。例如:
    #define PI 3.1415926
    #define S PI*y*y    /* PI是已定义的宏名*/
    printf("%f", S);
    

    在宏替换后变为:

    printf("%f", 3.1415926*y*y);

    1. 习惯上宏名用大写字母表示,以便于与变量区别。但也允许用小写字母。

    2. 可用宏定义表示数据类型,使书写方便。例如:

    #define UINT unsigned int
    //在程序中可用 UINT 作变量说明:
    UINT a, b;
    

    应注意用宏定义表示数据类型和用typedef定义数据说明符的区别:
    宏定义只是简单的字符串替换,由预处理器来处理;
    typedef是在编译阶段由编译器处理的,它并不是简单的字符串替换,而给原有的数据类型起一个新的名字,将它作为一种新的数据类型。
    例:

    #define PIN1 int *
    typedef int *PIN2;  //也可以写作typedef int (*PIN2);
    PIN1 a, b;
    PIN2 a,b;
    

    在用宏PIN1代换后变成:int * a, b; 表示a是指向int整型的指针变量,而b只是整型变量
    而用typedef定义的的PIN2代换后变为:int * a, *b; 表示 a、b 都是指向整型的指针变量。

    带参数的宏定义

    C语言允许宏带有参数。在宏定义中的参数称为“形式参数”,在宏调用中的参数称为“实际参数”,这点和函数有些类似。

    对带参数的宏,在展开过程中不仅要进行字符串替换,还要用实参去替换形参。

    带参宏定义的一般形式为:

    #define 宏名(形参列表) (字符串)
    //在字符串中可以含有各个形参
    //为避免歧义,字符串要用括号括起来,后面的例子会具体说

    带参宏调用的一般形式为:

    宏名(实参列表);

    例:

    #include <stdio.h>
    #define MAX(a,b) (a>b) ? a : b
    //用宏名MAX表示条件表达式(a>b) ? a : b,形参 a、b 均出现在条件表达式中
    int main(){
        int x , y, max;
        printf("input two numbers: ");
        scanf("%d %d", &x, &y);
        max = MAX(x, y);
        //宏调用,实参 x、y 将用来代替形参 a、b。宏展开后该语句为:max=(x>y) ? x : y;
        printf("max=%d\n", max);
        return 0;
    }
    

    运行结果:

    input two numbers: 10 20
    max=20

    • 对带参宏定义的说明
    1. 带参宏定义中,形参之间可以出现空格,但是宏名和形参列表之间不能有空格出现
      例:

    #define MAX(a,b) (a>b)?a:b 
    

    写为:

     #define MAX  (a,b)  (a>b)?a:b// MAX和(a,b)中间有空格
    

    将被认为是无参宏定义,宏名 MAX 代表字符串(a,b) (a>b)?a:b

    宏展开时,宏调用语句:max = MAX(x,y);
    将变为:max = (a,b)(a>b)?a:b(x,y);
    这显然是错误的

    1. 在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型。而在宏调用中,实参包含了具体的数据,要用它们去替换形参,因此实参必须要指明数据类型。

    这一点和函数是不同的:在函数中,形参和实参是两个不同的变量,都有自己的作用域,调用时要把实参的值传递给形参;而在带参数的宏中,只是符号的替换,不存在值传递的问题。

    【示例】输入 n,输出 (n+1)^2 的值。

    #include <stdio.h>
    #define SQ(y) (y)*(y)
    int main(){
        int a, sq;
        printf("input a number: ");
        scanf("%d", &a);
        sq = SQ(a+1);
        printf("sq=%d\n", sq);
        return 0;
    }
    

    运行结果:

    input a number: 9
    sq=100

    第 2 行为宏定义,形参为 y
    第 7 行宏调用中实参为 a+1,是一个表达式,在宏展开时,用 a+1 代换 y,再用 (y)* (y)代换 SQ,得到如下语句:

    sq=(a+1)*(a+1);

    这与函数的调用是不同的,函数调用时要把实参表达式的值求出来再传递给形参,而宏展开中对实参表达式不作计算,直接按照原样替换。

    1. 在宏定义中,字符串内的形参通常要用括号括起来以避免出错。例如上面的宏定义中 (y)*(y)表达式的 y 都用括号括起来,因此结果是正确的。如果去掉括号运行结果为:

    input a number: 9
    sq=19

    同样输入 9,但结果却是不一样的。问题在哪里呢?
    这是由于宏展开只是简单的符号替换的过程,没有任何其它的处理。宏替换后将得到以下语句:

    sq=a+1* a+1;
    //由于 a 为 9,故 sq 的值为 9+1*9+1=19。

    这显然与题意相违,因此参数两边的括号是不能少的

    然而即使在参数两边加括号也还是不够的,例如:

    #include <stdio.h>
    #define SQ(y) (y)*(y)
    int main(){
        int a,sq;
        printf("input a number: ");
        scanf("%d", &a);
        sq = 200 / SQ(a+1);
        printf("sq=%d\n", sq);
        return 0;
    }
    

    注意宏调用语句为:sq = 200/SQ(a+1);
    运行程序后,如果仍然输入 9,那么我们希望的结果为 2。但实际情况并非如此:

    input a number: 9
    sq=200

    为什么会得这样的结果呢?

    分析宏调用语句,在宏展开之后变为:
    sq=200/(a+1)*(a+1);
    a 为 9 时,由于“/”和“* ”运算符优先级和结合性相同,所以先计算 200/(9+1),结果为 20,再计算 20*(9+1),最后得到 200。

    为了得到正确答案,应该在宏定义中的整个字符串外加括号:

    #include <stdio.h>
    #define SQ(y) ((y)*(y))
    int main(){
        int a,sq;
        printf("input a number: ");
        scanf("%d", &a);
        sq = 200 / SQ(a+1);
        printf("sq=%d\n", sq);
        return 0;
    }
    

    由此可见,对于带参宏定义不仅要在参数两侧加括号,还应该在整个字符串外加括号。

    带参宏定义和函数的区别

    带参数的宏和函数很相似,但有本质上的区别:
    宏展开仅仅是字符串的替换,不会对表达式进行计算; 宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存。
    而函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码。

    例:计算平方值

    1. 函数
    #include <stdio.h>
    int SQ(int y){
      return ((y)*(y));
    }
    int main(){
        int i=1;
        while(i<=5){
            printf("%d^2 = %d\n", (i-1), SQ(i++));
        }
        return 0;
    }
    

    运行结果:

    1^2 = 1
    2^2 = 4
    3^2 = 9
    4^2 = 16
    5^2 = 25

    #include <stdio.h>
    #define SQ(y) ((y)*(y))
    int main(){
        int i=1;
        while(i<=5){
            printf("%d^2 = %d\n", i, SQ(i++));
        }
        return 0;
    }
    

    运行结果:

    3^2 = 2 //1* 2
    5^2 = 12 //3* 4
    7^2 = 30 //5* 6

    在使用函数的例子中,先把实参 i 传递给形参 y,然后再自增 1,这样每循环一次 i 的值增加 1,所以最终要循环 5 次。

    在使用宏的例子中,宏调用只是简单的字符串替换,SQ(i++) 会被替换为 ((i++)* (i++)),这样每循环一次 i 的值增加 2,所以最终只循环 3 次

    带参数的宏也可以用来定义多个语句,在宏调用时,把这些语句又替换到源程序中

    #include <stdio.h>
    #define SSSV(s1, s2, s3, v) s1 = length * width; s2 = length * height; s3 = width * height; v = width * length * height;
    int main(){
        int length = 3, width = 4, height = 5, sa, sb, sc, vv;
        SSSV(sa, sb, sc, vv);
        printf("sa=%d, sb=%d, sc=%d, vv=%d\n", sa, sb, sc, vv);
        return 0;
    }
    

    运行结果:

    sa=12, sb=15, sc=20, vv=60

    #if、#ifdef、#ifndef条件编译

    引例:假如现在要开发一个C语言程序,让它输出红色的文字,并且要求跨平台,在 Windows 和 Linux 下都能运行,怎么办呢?

    这个程序的难点在于,不同平台下控制文字颜色的代码不一样,我们必须要能够识别出不同的平台。

    Windows 有专有的宏_WIN32,Linux 有专有的宏__linux__

    #include <stdio.h>
    int main(){
        #if _WIN32
            system("color 0c");
            printf("http://c.biancheng.net\n");
        #elif __linux__
            printf("\033[22;31mhttp://c.biancheng.net\n\033[22;30m");
        #else
            printf("http://c.biancheng.net\n");
        #endif
        return 0;
    }
    

    #if#elif#else#endif 都是预处理命令,整段代码的意思是:如果宏_WIN32的值为真,就保留第 4、5 行代码,删除第 7、9 行代码;如果宏 __linux__ 的值为真,就保留第 7 行代码;如果所有的宏都为假,就保留第 9 行代码。

    这些操作都是在预处理阶段完成的,多余的代码以及所有的宏都不会参与编译,不仅保证了代码的正确性,还减小了编译后文件的体积。

    这种能够根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译。 条件编译是预处理程序的功能,不是编译器的功能。

    • #if 的用法

    #if 整型常量表达式1
    程序段1
    #elif 整型常量表达式2
    程序段2
    #elif 整型常量表达式3
    程序段3
    #else
    程序段4
    #endif

    它的意思是:如常“表达式1”的值为真(非0),就对“程序段1”进行编译,否则就计算“表达式2”,结果为真的话就对“程序段2”进行编译,为假的话就继续往下匹配,直到遇到值为真的表达式,或者遇到 #else。这一点和 if else 非常类似。

    需要注意的是,#if 命令要求判断条件为“整型常量表达式”,也就是说,表达式中不能包含变量,而且结果必须是整数;而 if 后面的表达式没有限制,只要符合语法就行。这是 #if 和 if 的一个重要区别。

    • #ifdef 的用法
      #ifdef 用法的一般格式为:

    #ifdef 宏名
    程序段1
    #else
    程序段2
    #endif

    它的意思是,如果当前的宏已被定义过,则对“程序段1”进行编译,否则对“程序段2”进行编译。

    #ifdef可以认为是 #if defined的缩写。

    也可以省略 #else:

    #ifdef 宏名
    程序段
    #endif

    例:

    #include <stdio.h>
    #include <stdlib.h>
    int main(){
        #ifdef _DEBUG
            printf("正在使用 Debug 模式编译程序...\n");
        #else
            printf("正在使用 Release 模式编译程序...\n");
        #endif
        system("pause");
        return 0;
    }
    

    当以 Debug 模式编译程序时,宏 _DEBUG会被定义,预处器会保留第 5 行代码,删除第 7 行代码。反之会删除第 5 行,保留第 7 行。

    • #ifndef 的用法

    #ifndef 宏名
    程序段1
    #else
    程序段2
    #endif

    它的意思是,如果当前的宏未被定义,则对“程序段1”进行编译,否则对“程序段2”进行编译,这与#ifdef的功能正好相反。

    • 三者之间的区别
      最后需要注意的是,#if后面跟的是“整型常量表达式”,而 #ifdef#ifndef后面跟的只能是一个宏名,不能是其他的。

    例如,下面的形式只能用于 #if:

    #include <stdio.h>
    #define NUM 10
    int main(){
        #if NUM == 10 || NUM == 20
            printf("NUM: %d\n", NUM);
        #else
            printf("NUM Error\n");
        #endif
        return 0;
    }
    

    运行结果:

    NUM: 10

    再如,两个宏都存在时编译代码A,否则编译代码B:

    #include <stdio.h>
    #define NUM1 10
    #define NUM2 20
    int main(){
        #if (defined NUM1 && defined NUM2)
            //代码A
            printf("NUM1: %d, NUM2: %d\n", NUM1, NUM2);
        #else
            //代码B
            printf("Error\n");
        #endif
        return 0;
    }
    

    运行结果:

    NUM1: 10, NUM2: 20

    以下代码也能获得同样的运行结果:

    #include <stdio.h>
    #define NUM1 10
    #define NUM2 20
    int main(){
            #ifdef NUM1
            printf("NUM1:%d,",NUM1);
            #else
            printf("error");
            #endif
    
            #ifdef NUM2
            printf("NUM2:%d",NUM2);
            #else
            printf("error");
            #endif
            return 0;
    }
    

    预处理命令总结

    预处理指令是以#号开头的代码行,# 号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和 # 号之间允许存在任意个数的空白字符,整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。

    指令说明
    #空指令,无任何效果
    #include包含一个源代码文件
    #define定义宏
    #undef取消已定义的宏
    #if如果给定条件为真,则编译下面代码
    #ifdef如果宏已经定义,则编译下面代码
    #ifndef如果宏没有定义,则编译下面代码
    #else如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
    #endif结束一个#if……#else条件编译块

    预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的,程序员在程序中用预处理命令来调用这些功能。

    宏定义可以带有参数,宏调用时是以实参代换形参,而不是“值传送”。

    为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。

    文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。

    条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。

    使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计。

    更多相关内容
  • linux awk 命令使用详解

    万次阅读 多人点赞 2022-07-09 12:46:09
    awk 命令使用详解

    前言

    awk是linux的一个强大的命令,具备强大的文本格式化能力,比如对一堆看起来没有什么规律的日志文件,文本文件等,通过awk命令之后,格式化输出为专业的可以做为应用级数据分析的样式;

    awk像是一门编程语言,支持条件判断,数组,循环等诸多的功能;

    linux三剑客

    • grep,擅长单纯的查找或匹配文本内容;
    • sed,擅长文本编辑,处理匹配到的文本内容;
    • awk,适合格式化文本文件,对文本文件进行更复杂的加工处理、分析;

    awk理论基础

    1、awk语法

    awk  [option]  'pattern[action]'  file ...
    
    awk   参数       条件动作           文件
    

    在这里插入图片描述

    action 是指动作,awk擅长文本格式化,且能输出格式化后的结果,因此最常用的动作就是 print 和 printf

    2、awk处理文本内容模式

    • awk默认以空格为分隔符,且多个空格也识别为一个空格,作为分隔符;
    • awk按行处理文件,一行处理完毕之后,再处理下一行;
    • awk可以根据用户指定的分隔符去工作,没有指定,则默认为空格;

    一、awk内置变量

    内置变量说明
    $n指定分隔符后,当前的第n个列所在的字段
    $0完整的一行记录
    FS字段分隔符,默认是空格
    NF(Number of fields)字段分隔后,当前一共多少个字段
    NR(Number of records)当前记录数,行数

    更多的内置变量,可通过 man awk命令进行查看

    简单案例展示

    提前准备一个文本,内容如下

    在这里插入图片描述

    1、输出第二列内容

    awk '{print $2}' alx.txt
    

    在这里插入图片描述

    2、输出多列内容

    直接在第一步后面的基础上追加,中间用 “,” 分割

    awk '{print $2,$3}' alx.txt
    

    在这里插入图片描述
    3、查看第三行内容

    考察对NR的使用,NR表示第N行记录的模式匹配

    awk 'NR==3{print $0}' alx.txt
    

    在这里插入图片描述

    输出多行

    awk 'NR==5,NR==6{print $0}' alx.txt
    

    在这里插入图片描述

    4、输出从第3到第五行,并显示行号

    awk 'NR==3,NR==5 {print NR,$0}' alx.txt
    

    在这里插入图片描述

    5、自定义输出内容

    某些情况下,需要给每一列添加类似于excel的表头信息,就可以考虑使用awk的自定义输出;

    awk '{print "第一列: "$1,"第二列: "$2}' alx.txt 
    

    在这里插入图片描述

    需要注意的是大括号外面的使用 ’ 单引号,括号里面的使用双引号

    二、awk参数

    参数说明
    -F指定分隔字段符
    -v定义或修改一个awk内部变量
    -f从脚本文件中读取awk命令

    上文谈到,awk默认的字段分隔符为空格,但是像下面这样的文本,以 # 为分隔符,就需要用到自定义分隔符;

    在这里插入图片描述

    1、显示第一列和第二列内容

    awk -F "#" '{print $1,$2}' zcy2.txt
    

    在这里插入图片描述

    2、显示文件第一列,倒是第一列,和倒数第二列的内容

    awk '{print $1,$(NF-1),$(NF-2)}' alx.txt
    

    在这里插入图片描述

    3、取出本机的IP地址

    在这里插入图片描述

    使用awk的方式获取的话,如果以空格为分隔符,我们发现目标字段在第二行的第二列,使用下面的命令即可,看起来,比起sed和grep命令似乎更简单;

    ifconfig eth0 | awk 'NR==2{print $2}'
    

    在这里插入图片描述

    4、取出密码文件中的第一列和最后一列

    考察对自定义输入分隔符的使用,可以看到,下面的文本文件中,可以考虑使用 : 进行分割;
    在这里插入图片描述

    awk -F ':' '{print $1,$NF}' pwd2.txt
    

    在这里插入图片描述

    三、OFS输出分隔符

    通过上文的学习,我们知道awk命令执行后,默认采用空格分割字段,而这个空格就是默认的输出分割符,

    单在某些情况下,为了将数据展示的效果更加醒目一些,就可以使用OFS的自定义输出分隔符;

    仍然以上面的密码文本为例,输出第一列和最后一列的字段;

    awk -F ':' -v OFS=' *** ' '{print $1,$NF}' pwd2.txt
    

    该表默认输出分隔符,直接在awk后面使用: -v OFS=‘自定义输出分隔符’

    在这里插入图片描述

    四、awk变量

    awk参数

    参数说明
    -F指定分隔字段符
    -v定义或修改一个awk内部变量
    -f从脚本文件中读取awk命令

    对于awk来讲,变量分为:内置变量和自定义变量

    awk内置变量

    参数说明
    FS输入字段分隔符,默认为空白字符
    OFS输出字段分隔符,默认为空白字符
    RS输入记录分隔符,指定输入时的换行符
    ORS输出记录分隔符,输出时用指定符号替换换行符
    NF当前行的字段个数,字段数量
    NR行号,当前处理文本行的行号
    FNR各文件分别计数的行号
    FILENAME当前文件名
    ARGC命令行参数个数
    ARGV数组,保存的是命令行所给定的各个参数

    比较常用的内置变量包括: NR,NF,FNR

    FILENAME 使用

    FILENAME 为awk的内置变量,通过下面这个命令,可以看到在每行记录之前,输出了当前文件名称;

    awk 'NR==1,NR==3{print FILENAME,$0}' alx.txt
    

    在这里插入图片描述

    ARGV使用

    先来看下面这条命令的执行结果

    awk 'NR==1,NR==3{print ARGV[0],ARGV[1],$0}' alx.txt
    

    在这里插入图片描述
    可以发现,在输出的每一行记录前面,拼上了 awk 和 alx.txt这两个字段,这两个字段就是这行命令整体解析出来的2个内置参数;

    自定义变量

    看下面这条命令输出效果,通过-v参数,可以自定义变量进行参数传递;

    awk -v myname="zcy" 'BEGIN{print "我的名字是?" ,myname}'
    

    在这里插入图片描述

    五、awk格式化输出

    在上文,我们接触的是awk的输出功能,主要使用了 print 这个进行输出,它只能对文本进行简单的输出,但是并不能美化或者修改输出格式;

    printf 格式化输出

    如果对C语言有过了解的同学,对printf 并不陌生,使用这个命令(函数)可以对文本进行格式化输出;

    printf与print的几点区别

    • printf 需要指定format;
    • format 用于指定后面的每个 item输出格式;
    • printf 语句不会自动打印换行符; \n ; print 默认添加换行符;

    如下,假如我们直接使用 printf 这样操作,看下效果

    awk '{printf $0}' alx.txt
    

    在这里插入图片描述
    明显来说,把所有内容都输出到同一行了,这时候,就需要使用 printf的格式化输出来控制;

    awk '{printf "%s\n", $0}' alx.txt
    

    在这里插入图片描述

    再看一个案例,使用 printf 将文本中的每一列添加前置输出

    awk '{printf "第一列:%s   第二列:%s   第三列:%s\n" ,$1,$2,$3}' alx.txt 
    

    在这里插入图片描述

    六、awk模式pattern

    上文了解到,awk的语法如下 :

    awk [option] ‘pattern[action]’ file …

    而且我们了解到,awk是按行处理文本,以上都是关于 print 相关,接下来,聊聊pattern相关的内容;

    在pattern中,有个比较常见的pattern,BEGIN和END;

    • BEGIN 模式是处理文本之前需要执行的动作;
    • END模式是处理完成所有的行之后执行的操作;
    awk 'BEGIN{print "小明在学linux"}'
    

    在这里插入图片描述

    或者下面这样

    awk 'BEGIN{print "小明在学linux"} {print $0}END{print "处理结束"}' alx.txt
    

    在这里插入图片描述

    注意:BEGIN 和 END分别放到处理文本内容前后即可

    awk如果不指定模式是按行处理,如果指定了模式,只有符合模式的才会被处理

    awk常用模式

    关系运算符说明
    <小于
    <=小于等于
    ==等于
    !=不等于
    >=大于等于
    ~匹配正则
    !~不匹配正则

    1、打印前三行的文本内容

    awk 'NR<=3{print $0}' alx.txt
    

    在这里插入图片描述

    2、匹配密码文本中含有 zcy 的行

    awk '/^zcy/{print $0}' pwd.txt
    

    在这里插入图片描述

    3、格式化输出 /etc/passwd 的部分字段

    awk -F ":" 'BEGIN{print"用户名\t\t\t字段1\t\t     字段2\t\t     权限"} {printf "user:%-20s%-20s%-20s%-20s\n", $1,$4,$5,$7}' pwd.txt
    

    在这里插入图片描述

    4、找出pwd文件中nologin的用户

    在这里插入图片描述

    awk '/\/sbin\/nologin$/{print NR,$0}' pwd.txt
    

    在这里插入图片描述

    5、找出 下面这个区间的文本行

    在这里插入图片描述

    awk '/^daemon/,/^operator/{print NR,$0}' pwd.txt
    

    在这里插入图片描述

    七、综合案例:统计nginx的access.log中访问前10的IP

    在这里插入图片描述

    首先来看下该日志文件中的内容格式,简单分析得知,该文件中的内容的每一行,可以看作是由空格分割的,于是可以考虑使用awk来完成需求;
    在这里插入图片描述

    可能用到的额外几个命令

    • sort -n ,数字从大到小排序;
    • wc -l ,统计行数;

    1、访问日志中的访客IP数量

    awk '{print $1}' access.log | sort -n | uniq | wc -l
    

    在这里插入图片描述

    2、查访问最频繁的前10个IP

    awk '{print NR,$1}' access.log | sort -n | uniq -c | sort -nr | head -10
    

    在这里插入图片描述

    展开全文
  • 5.1Makefile显示命令 通常,make 会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个 命令将不被 make 显示出来,最具代表性的例子是,我们用这个功能来像屏幕显示一些信息。...

    5.1Makefile显示命令

    通常,make 会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个
    命令将不被 make 显示出来,最具代表性的例子是,我们用这个功能来像屏幕显示一些信息。

    以make clean为例

    当执行make cleanall时 

    会输出执行命令,当在命令前添加上@

    再次执行时就无输出了。

     在执行make时,带入make参数“-n”或“--just-print”参数,命令只会显示不会执行,用于调试自己写的makefile文件

    而 make 参数“-s”或“--slient”则是全面禁止命令的显示。

    5.2命令执行

    当依赖目标新于目标时,也就是当规则的目标需要被更新时,make 会一条一条的执行其后的命令。而当需要让一条命令的结果应用到下一条命令时,需要用分号隔开而不是另起一行。

    示例一:
    exec:
        cd /home/hchen
        pwd
    示例二:
    exec:
        cd /home/hchen;pwd

    其中示例一第一条命令不起作用。正确写法如示例二。

    5.3命令出错

        有些时候,命令的出错并不表示就是错误的。例如用mkdir创建一个文件,真正的目的是保证该目录的存在而不是当有该目录时创建失败退出makefile,可以通过在命令前加一个“-”(Tab键之后),无论命令成功与否都认为是成功的,继续执行之后命令。如:

    clean:
        -rm-f*.o

        还有一个全局的办法是,给 make 加上“-i”或是“--ignore-errors”参数,那么,Makefile 中所有命令都会忽略错误。而如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。

         make 的参数的是“-k”或是“--keep-going”,这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。

    5.4嵌套执行make

        在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的 Makefile,这有利于让我们的 Makefile 变得更加地简洁,而不至于把所有的东西全部写在一个 Makefile 中,这样会很难维护我们的 Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。

        直接看实例:工程文件如下

    可以看主makefile文件内容如下

    CC =gcc
    
    
    TOP_DIR :=$(PWD)
    INCLUDE :=$(TOP_DIR)/headers
    SRC_DIR :=$(TOP_DIR)/src
    APP_DIR :=$(TOP_DIR)/app
    VPATH := $(SRC_DIR):$(APP_DIR)
    CFLAGS = -I $(INCLUDE)
    
    export CC VPATH CFLAGS
    
    
    .PHONY:all clean
    all:
    	$(MAKE) -C $(SRC_DIR)
    	$(MAKE) -C $(APP_DIR)
    clean:
    	$(MAKE) -C $(SRC_DIR) clean
    	$(MAKE) -C $(APP_DIR) clean

    其中$(MAKE) -C $(SRC_DIR)是到对应的子目录下执行make,使用$(MAKE)是为了方便以后可以添加适当的make参数,-C参数是在进入或者退出目录时打印出来。

    如下

    export的作用是将变量传递给子目录下的Makefile文件以供它们使用。

    看app下面的makefile文件

    OBJ = test.o
    
    $(OBJ):%.o:%.c
    	$(CC) -c $(CFLAGS) $< -o $@
    %.d:%.c
    	@set -e;rm -f $@;\
    	$(CC) -MM $(CFLAGS) $< > $@.$$$$;\
    	sed 's,\($*\)\.o[:]*,\1.o $@:,g' < $@.$$$$ > $@;\
    	rm -f $@.$$$$\
    
    -include $(OBJ:.o=.d)
    	
    .PHONY:clean
    clean:
    	rm $(OBJ) *.d *.d.* -f

    ,其实这么写是有错误的,因为$(OBJ)是第一目标,当本身只有一个目标的时候没问题,但是有两个.o文件的时间只会生成一个.o文件

    src下面的makefile文件如下

    OBJ =main.o fun.o 
    
    .PHONY:all
    all:$(OBJ)
    
    $(OBJ):%.o:%.c
    	$(CC) -c  $< -o $@ $(CFLAGS)
    %.d:%.c
    	@set -e;rm -f $@;\
    	$(CC) -MM $(CFLAGS) $< > $@.$$$$;\
    	sed 's,\($*\)\.o[:]*,\1.o $@:,g' < $@.$$$$ > $@;\
    	rm -f $@.$$$$\
    	
    -include $(OBJ:.o=.d)
    
    .PHONY:clean
    clean:
    	rm $(OBJ) *.d *.d.* -f

    此时,$(OBJ)含有两个.o文件,需要用一个伪目标才可以正确生成,这里面的$(CFLAGS)由主makefile继承过来。

    执行过make之后的工程目录如下:

    5.5定义命令包

    Makefile 中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一个变量。定义这种命令序列的语法以“define”开始,以“endef”结束,如:

    define run-yacc
    yacc $(firstword $^)
    mv y.tab.c $@
    endef

    这里,“run-yacc”是这个命令包的名字,其不要和 Makefile 中的变量重名。在“define”和“endef”中的两行就是命令序列。这个命令包中的第一个命令是运行 Yacc 程序,因为 Yacc 程序总是生成“y.tab.c”的文件,所以第二行的命令就是把这个文件改改名字。还是把这个命令包放到一个示例中来看看吧。

    foo.c:foo.y
        $(run-yacc)

    我们可以看见,要使用这个命令包,我们就好像使用变量一样。在这个命令包的使用中,命令包“run-yacc”中的“$^”就是“foo.y”,“$@”就是“foo.c”(有关这种以“$”开头的特殊变量,我们会在后面介绍),make 在执行命令包时,命令包中的每个命令会被依次独立执行。类似于C语言中的宏定义函数。

     

     

    展开全文
  • Mysql知识体系、命令全集

    🍅 作者主页:不吃西红柿 

     

    🍅 简介:CSDN博客专家🏆、信息技术智库公号作者✌  简历模板、PPT模板、学习资料、面试题库、技术互助【关注我,都给你】

    🍅 欢迎点赞 👍 收藏 ⭐留言 📝   

    🍅 耗时1年整理,硬核文章目录:https://t.1yb.co/zHJ


    目录

    1.MySQL数据库的介绍

    什么是数据库

    作用

    常见的数据库

    认识mysql数据库

    2.安装MySQL

    Mac系统中安装MySQL

    使⽤用Mac中的Homebrew进⾏行行mysql的安装

    Windows安装MySQL5.7.17

     3.认识和操作一下mysql的基本命令

    登录mysql,在终端输入以下命令,进行登录

    查看当前mysql中所有的库

    选择需要操作的库,打开库

    查看表中的数据

    库和表的概念与关系

    如何创建自己的库?

    查看所有库

    创建表的语法

    添加数据

    4.MySQL基础操作

    使用方法:

    SQL ( Structure query language ) 结构化查询语言

    SQL语句中的快捷键

    1.通过命令行连接MySQL

    2. 数据库操作

    3. 数据表操作

    4. 数据操作 增删改查

    退出MySQL

    5.MySQL的数据类型

    一.MySQL的数据类型

    1、字符串数据类型

             2、数值类型

    3、日期和时间类型

    4、二进制数据类型

    二、表的字段约束

    三、MySQL的运算符

    四、主键

    6.MySQL数据库与数据表操作

    数据库的操作

    1.数据库的创建

    2.查看所有库

    3.打开库/进入库/选择库

    4.删除库

    数据表的操作

    1.创建表

    2.修改表结构

    3.修改表名

    4.更改表中的自增的值

    5.修改表引擎

    6.删除表

     7.Mysql数据库表引擎与字符集

    1.服务器处理客户端请求

    2.存储引擎

    3.MyISAM和InnoDB表引擎的区别

    1) 事务支持

    2) 存储结构

    3) 表锁差异

    4) 表主键

    5) 表的具体行数

    6) CURD操作

    7) 外键

    8) 查询效率

    9)MyISAM和InnoDB两者的应用场景

    4.了解一下字符集和乱码

    字符集简介

    5.MySQL中的utf8和utf8mb4

    字符集的查看

    8.MySQL 数据操作 DML

    添加数据

    修改数据

    删除数据

    9.MySQL数据查询SQL

    基础查询

    Where 条件查询

    Like 子句

    Group BY 分组

    Having 子句

    Order by 排序

    Limit 数据分页

    10.Mysql数据库导入导出和授权

    数据导出

    1.数据库数据导出

    2.将数据库中的表导出

    数据导入

    把导出的sql文件数据导入到mysql数据库中

    把导出的表sql 导入数据库

    权限管理

    创建用户的语法格式:

    删除用户


    1.MySQL数据库的介绍

    什么是数据库

    数据库(Database)就是按照数据结构来组织,存储和管理数据的仓库 专业的数据库是专门对数据进行创建,访问,管理,搜索等操作的软件,比起我们自己用文件读写的方式对象数据进行管理更加的方便,快速,安全

    作用

    • 对数据进行持久化的保存
    • 方便数据的存储和查询,速度快,安全,方便

    • 可以处理并发访问

    • 更加安全的权限管理访问机制

    常见的数据库

    数据库分两大类,一类是 关系型数据库。另一类叫做 非关系型数据库。

    • 关系型数据库: MySQL,Oracle,PostgreSQL,SQLserver。。。。
    • 非关系型数据库: Redis内存数据库,MongoDB文档数据库。。。

    认识mysql数据库

    • MySQL是最流行的关系型数据库管理系统
    • 安装mysql 关于数据库的一些概念
    • 数据库 Database 数据表 Tables 数据字段
    • 行 row

    2.安装MySQL

    Mac系统中安装MySQL

    使⽤用Mac中的Homebrew进⾏行行mysql的安装

    1.下载安装mysql

    brew install mysql@5.7

       如果看到以下界⾯面则表示已经下载安装成功

    2.启动mysql mysql.server start

    3.关闭mysql mysql.server stop

    4.登录mysql mysql -u root -p

    Windows安装MySQL5.7.17

    1. 在MySQL官网 http://dev.mysql.com/downloads/mysql/ 上面下载ZIP安装包(第二个:Windows (x86, 64-

    bit), ZIP Archive)。

    2. 下载完成后解压,将其放到想要安装的目录下。

    例如:D:\MySQL5.7\mysql-5.7.17-winx64

    3. 新建一个my.ini配置文件,原始的my-default.ini配置文件只是个模版,不要在里面改动。 my.ini的内容如下:

    [mysql] default-character-set=utf8

    [mysqld] port = 3306 basedir=D:\MySQL5.7\mysql-5.7.17-winx64 datadir=D:\MySQL5.7\mysql-5.7.17- winx64\data max_connections=200 character-set-server=utf8 default-storage-engine=INNODB explicit_defaults_for_timestamp=true

    4. 在安装路径下新建一个空的data文件夹。

    5. 以管理员身份运行cmd,进入bin目录,执行 mysqld --initialize-insecure --user=mysql 命令。不进行这一

      步,安装完成之后无法启动服务。

    6. 依然在管理员cmd窗口的bin目录下,执行 mysqld install 命令安装。完成后会提示安装成功。

    7. 依然在管理员cmd窗口的bin目录下,执行 net start mysql 命令启动MySQL服务。

    8. 修改环境变量,添加"D:\MySQL5.7\mysql-5.7.17-winx64\bin"。

    9. 在普通cmd窗口中,进入bin目录,执行 mysql -u root -p 命令,默认没有密码,回车进入。

     3.认识和操作一下mysql的基本命令

    认识库,表的概念和关系 mysql的基本命令: 登录,查看库,选择库,查看表, 创建库,创建表,添加数据,查询数据。

    登录mysql,在终端输入以下命令,进行登录

    mysql -u root -p
    
        MacBook-Pro:~ yc$ mysql -u root -p
    
    Enter password:
    
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    
    Your MySQL connection id is 4
    
    Server version: 5.7.28 Homebrew
    
    Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    
    affiliates. Other names may be trademarks of their respective
    
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>

    查看当前mysql中所有的库

    库==>数据库==>就像文件夹一样,库里面可以存储很多个表)

    show databases;

    +--------------------+

    | Database           |

    +--------------------+

    | information_schema |

    | mysql              |

    | performance_schema |

    | sys                |

    +--------------------+

    4 rows in set (0.00 sec)

    选择需要操作的库,打开库

    use mysql; 查看当前库中的所有数据表

    show tables;

    +---------------------------+

    | Tables_in_mysql           |

    查看表中的数据

    # 查看user表中的所有数据的所有字段 select * from user;

    # 查看 user表中的所有数据的 host和user字段列 select host,user from user;

    +-----------+---------------+

    | host      | user          |

    +-----------+---------------+

    | localhost | mysql.session |

    | localhost | mysql.sys     |

    | localhost | root          |

    +-----------+---------------+

    库和表的概念与关系

    库就像是文件夹,库中可以有很多个表 表就像是我们的excel表格文件一样 每一个表中都可以存储很多数据

    mysql中可以有很多不同的库,库中可以有很多不同的表 表中可以定义不同的列(字段), 表中可以根据结构去存储很多的数据

    如何创建自己的库?

    create database 库名 default charset=utf8; 创建库

    +---------------------------+

    | columns_priv              |

    | db                        |

    | engine_cost               |

    ....

    | time_zone_name            |

    | time_zone_transition      |

    | time_zone_transition_type |

    | user                      |

    +---------------------------+

    31 rows in set (0.00 sec)

    create database tlxy default charset=utf8;

    -- Query OK, 1 row affected (0.01 sec)

    查看所有库

    show databases;

    +--------------------+

    | Database           |

    +--------------------+

    | information_schema |

    | mysql              |

    | performance_schema |

    | sys                |

    | tlxy               |

    +--------------------+

    5 rows in set (0.00 sec)

    -- 进入库 use tlxy;

    创建表的语法

    create table 表名( 字段名 类型 字段约束, 字段名 类型 字段约束, 字段名 类型 字段约束, )engine=innodb default

    charset=utf8;

    -- 创建用户表 create table user(

        name varchar(20),

        age int,

        sex char(1)

    )engine=innodb default charset=utf8;

    -- Query OK, 0 rows affected (0.16 sec)

    添加数据

    -- 向 user 表中 添加 name,age,sex 数据

    insert into user(name,age,sex) values('admin',26,'男'); -- Query OK, 1 row affected (0.00 sec)

    insert into user(name,age,sex) values('张三',22,'女');

    查看表中的数据

    select * from user; +--------+------+------+ |name |age |sex | +--------+------+------+ |admin| 26|男 | |张三 | 22|女 | +--------+------+------+ 2 rows in set (0.00 sec)

    4.MySQL基础操作

    使用方法:

    • 方式一: 通过在命令行敲命令来操作 ( 有助于命令的掌握)
    • 方式二: 通过图型界面工具,如 Navicat 等(在熟练掌握后再使用)
    • 方式三:通过编程语言(python,php,java,go...)执行mysql命令

    SQL ( Structure query language ) 结构化查询语言

    SQL语言分为4个部分:DDL(定义)、DML(操作)、DQL(查询)、DCL(控制)

    SQL语句中的快捷键

    \G 格式化输出(文本式,竖立显示) \s 查看服务器端信息

    \c 结束命令输入操作

    \q 退出当前sql命令行模式

    \h 查看帮助

    操作数据库的步骤

    连接, 打开库, 操作, 关闭退出

    1.通过命令行连接MySQL

    数据库语法的特点

    1) SQL 语句可以换行, 要以分号结尾

    2) 命令不区分大小写. 关键字和函数建议用大写

    3) 如果提示符为 '> 那么需要输入一个'回车

    4) 命令打错了换行后不能修改, 可以用 \c 取消

    2. 数据库操作

    • 查看数据库 show databases;
    • 创建数据库 create database 库名 default charset=utf8;
    • 删除数据库 drop database 库名;
    • 打开数据库 use 库名;

    3. 数据表操作

    数据库管理系统中, 可以有很多库, 每个数据库中可以包括多张数据表

    查看表: show tables;

    创建表: create table 表名(字段名1 类型,字段名2 类型)engine=innodb default charset=utf8; 创建表: 如果表不存在,则创建, 如果存在就不执行这条命令

    create table if not exists 表名(字段1 类型,字段2 类型);

    create table if not exists users(

    id int not null primary key auto_increment, name varchar(4) not null,

    age tinyint,

    sex enum('男','女')

    ) engine=innodb default charset=utf8;

    删除表: drop table 表名;

    表结构: desc 表名;

    查看建标语句:show create table users;

    4. 数据操作 增删改查

    插入

    insert into 表名(字段1,字段2,字段3) values(值1,值2,值3);

    insert into 表名(字段1,字段2,字段3) values(a值1,a值2,a值3),(b值1,b值2,b值3); 查询

    select * from 表名;

    select 字段1,字段2,字段3 from 表名;

    select * from 表名 where 字段=某个值;

    修改

    update 表名 set 字段=某个值 where 条件;

    update 表名 set 字段1=值1,字段2=值2 where 条件;

    update 表名 set 字段=字段+值 where 条件;

    删除

    delete from 表名 where 字段=某个值;

    四. 退出MySQL

    exit; 或者 quit;

    5.MySQL的数据类型

    一.MySQL的数据类型

    数据类型是定义列中可以存储什么类型的数据以及该数据实际怎样存储的基本规则数据类型限制存储在数据列列中的数据。例如,数值数据类型列只能接受数值类型的的数据在设计表时,应该特别重视所用的数据类型。使用错误的数据类型可能会严重地影响应用程序的功能和性能。

    更改包含数据的列不是一件小事(而且这样做可能会导致数据丢失)。

    数据类型: 整型、浮点型、字符串、日期等

    1、字符串数据类型

    最常用的数据类型是串数据类型。它们存储串,如名字、地址、电 话号码、邮政编码等。 不管使用何种形式的串数据类型,串值都必须括在引号内 有两种基本的串类型,分别为定长串和变长串

    定长串:char

    1. 接受长度固定的字符串,其长度是在创建表时指定的。 定长列不允许存储多于指定长度字符的数据。

    2. 指定长度后,就会分配固定的存储空间用于存放数据 char(7) 不管实际插入多少字符,它都会占用7个字符位置

    变长串 varchar

    存储可变长度的字符串 varchar(7) 如果实际插入4个字符, 那么它只占4个字符位置,当然插入的数据长度不能超过7个字符。

    注意

    既然变长数据类型这样灵活,为什么还要使用定长数据类型? 回答:因为性能,MySQL处理定长列远比处理变长列快得多。

    Text 变长文本类型存储

    2、数值类型

    数值数据类型存储数值。MySQL支持多种数值数据类型,每种存储的数值具有不同的取值范围。支持的取值范围越大,所需存储空间越多

    与字符串不一样,数值不应该括在引号内

     decimal(5, 2) 表示数值总共5位, 小数占2位 tinyint 1字节(8位) 0-255。-128,127 int 4字节。 -21亿,21亿。0-42亿 float.

    MySQL中没有专门存储货币的数据类型,一般情况下使用DECIMAL(8, 2)

    有符号或无符号

    所有数值数据类型(除BIT和BOOLEAN外)都可以有符号或无符号

    • 有符号数值列可以存储正或负的数值
    • 无符号数值列只能存储正数。
    • 默认情况为有符号,但如果你知道自己不需要存储负值,可以使用UNSIGNED关键字

    注意

    如果将邮政编码类似于01234存储为数值类型,则保存的将是数值1234,此时需要使用字符串类型 手机号应该用什么进行存储呢?

    3、日期和时间类型

    MySQL使用专门的数据类型来存储日期和时间值

       

     datetime 8字节1000-01-01 00:00:00 ~ 9999-12-31 23:59:59

    4、二进制数据类型

    二进制数据类型可存储任何数据(甚至包括二进制信息),如图像、多媒体、字处理文档等

    二、表的字段约束

    • unsigned 无符号(给数值类型使用,表示为正数,不写可以表示正负数都可以) 字段类型后面加括号限制宽度
    • char(5). varchar(7) 在字符类型后面加限制 表示 字符串的长度
    • int(4) 没有意义,默认无符号的int为int(11),有符号的int(10)
    • int(4) unsigned zerofill只有当给int类型设置有前导零时,设置int的宽度才有意义。
    • not null 不能为空,在操作数据库时如果输入该字段的数据为NULL ,就会报错 default 设置默认值
    • primary key 主键不能为空,且唯一.一般和自动递增一起配合使用。 auto_increment 定义列为自增属性,一般用于主键,数值会自动加1
    • unique 唯一索引(数据不能重复:用户名)可以增加查询速度,但是会降低插入和更新速度

    三、MySQL的运算符

    • 算术运算符: +、 -、 *、 /、 %
    • 比较运算符: =、 >、 <、 >=、 <=、!=
    • 数据库特有的比较: in、not in、is null、is not null、like、between、and
    • 逻辑运算符: and、or、not
    • like: 支持特殊符号%和_ ;

    其中%表示任意数量的任意字符,_表示任意一位字符

    四、主键

    1、表中每一行都应该有可以唯一标识自己的一列,用于记录两条记录不能重复,任意两行都不具有相同的主键值

    2、应该总是定义主键 虽然并不总是都需要主键,但大多数数据库设计人员都应保证他们创建的每个表具有一个主 键,以便于以后的数据操纵和管理。

    要求

    • 记录一旦插入到表中,主键最好不要再修改
    • 不允许NULL
    • 不在主键列中使用可能会更改的值。

    (例如,如果使用一个名字作为主键以标识某个供应商,当该供应商合并和更改其名字时,必须更改这个主键。)

    • 自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样我们就完全不用担心主键重复,也不用自己预先生成主键
    • 可以使用多个列作为联合主键,但联合主键并不常用。使用多列作为主键时,所有列值的组合必须是唯一的

    6.MySQL数据库与数据表操作

    数据库的操作:数据库创建 ;数据库删除

    数据表的操作:数据表的创建;数据表的修改 (表结构) ;数据表的删除

    数据库的操作

    1.数据库的创建

       # 链接mysql数据库后,进入mysql后可以操作数据

    # 1. 创建库

    create database if not exists tlxy default charset=utf8;

    -- 1. 数据库 tlxy 如果不存在则创建数据库,存在则不创建

    -- 2. 创建 tlxy 数据库,并设置字符集为utf8

    -- 3. 无特殊情况都要求字符集为utf8或者utf8mb4的字符编码

    2.查看所有库

    # 1. 查看所有库 show databases;

    3.打开库/进入库/选择库

    # use 库名 use tlxy

    4.删除库

    删库有风险,动手需大胆(哈哈哈,大不了西红柿带你跑路)

    # 删除库,那么库中的所有数据都将在磁盘中删除。 drop database 库名

    数据表的操作

    1.创建表

    语法格式:

    create table 表名(字段名,类型,【字段约束】,。。。); 实例:

    # 以下创建一个 users 的表 create table users(

    -- 创建ID字段,为正整数,不允许为空 主键,自动递增

    id int unsigned not null primary key auto_increment,

    -- 创建 存储 名字的字段,为字符串类型,最大长度 5个字符,不允许为空 username varchar(5) not null,

    -- 创建存储 密码 的字段,固定长度 32位字符, 不允许为空

    password char(32) not null,

    -- 创建 年龄 字段,不允许为空,默认值为 20

      age tinyint not null default 20

    )engine=innodb default charset=utf8;

    # 查看表结构 desc users;

    #查看建表语句

    show create table users;

    创建表的基本原则:

    • 表明和字段名 尽可能的符合命名规范,并且最好能够‘见名之意’
    • 表中数据必须有唯一标示,即主键定义。无特殊情况,主键都为数字并自增即可
    • 表中字段所对应的类型设置合理,并限制合理长度
    • 表引擎推荐使用innodb,并无特殊情况都要求为utf8或者utf8mb4的字符编码

    2.修改表结构

    语法格式:alter table 表名 action (更改的选项)

    添加字段

    # 语法:alter table 表名 add 添加的字段信息 --在users表中 追加 一个num字段

    alter table users add num int not null;

    -- 在指定字段后面追加字段 在 users 表中 age字段后面 添加一个 email 字段 alter table users add email varchar(50) after age;

    -- 在指定字段后面追加字段,在 users 表中 age字段后面 添加一个 phone alter table users add phone char(11) not null after age;

    -- 在表的最前面添加一个字段

    alter table users add aa int first;

    删除字段

       # 删除字段 alter table 表名 drop 被删除的字段名 alter table users drop aa;

    修改字段

    语法格式: alter table 表名 change|modify 被修改的字段信息 change: 可以修改字段名,

    modify: 不能修改字段名。

    # 修改表中的 num 字段 类型,使用 modify 不修改表名

    alter table users modify num tinyint not null default 12;

    # 修改表中的 num 字段 为 int并且字段名为 nn alter table users change num mm int;

    # 注意:一般情况下,无特殊要求,不要轻易修改表结构

    3.修改表名

    # 语法:alter table 原表名 rename as 新表名

    4.更改表中的自增的值

    # 在常规情况下,auto_increment 默认从1开始继续递增 alter table users auto_increment = 1000;

    5.修改表引擎

    # 推荐在定义表时,表引擎为 innodb。

    # 通过查看建表语句获取当前的表引擎

    mysql> show create table users\G;

    *************************** 1. row ***************************

           Table: users

    Create Table: CREATE TABLE `users` (

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8

    1 row in set (0.00 sec)

    # 直接查看当前表状态信息

    mysql> show table status from tlxy where name = 'users'\G; *************************** 1. row ***************************

               Name: users

             Engine: InnoDB

    # 修改表引擎语句

    alter table users engine = 'myisam';

    6.删除表

    drop table 表名

       

     7.Mysql数据库表引擎与字符集

    1.服务器处理客户端请求

    其实不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送

    一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。那服务器进程对客户

    端进程发送的请求做了什么处理,才能产生最后的处理结果呢?客户端可以向服务器发送增删改查各类请求,我们

    这里以比较复杂的查询请求为例来画个图展示一下大致的过程:

    虽然查询缓存有时可以提升系统性能,但也不得不因维护这块缓存而造成一些开销,比如每次都要去查询缓

    存中检索,查询请求处理完需要更新查询缓存,维护该查询缓存对应的内存区域。从MySQL 5.7.20开始,不

    推荐使用查询缓存,并在MySQL 8.0中删除。

    2.存储引擎

    MySQL 服务器把数据的存储和提取操作都封装到了一个叫 存储引擎 的模块里。我们知道 表 是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是 存储引擎 负责的事情。为了实现不同的功能, MySQL 提供了各式各样的 存储引擎 ,不同 存储引擎 管理的表具体的存储结构可能不同,采用的存取算法也可能不同。

    存储引擎以前叫做 表处理器 ,它的功能就是接收上层传下来的指令,然后对表中的数据进行提取或写入操作。

    为了管理方便,人们把 连接管理 、 查询缓存 、 语法解析 、 查询优化 这些并不涉及真实数据存储的功能划分为MySQL server 的功能,把真实存取数据的功能划分为 存储引擎 的功能。各种不同的存储引擎向上边的 MySQLserver 层提供统一的调用接口(也就是存储引擎API),包含了几十个底层函数,像"读取索引第一条内容"、"读取索引下一条内容"、"插入记录"等等。

    所以在 MySQL server 完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返回给客户端就好了。

    MySQL 支持非常多种存储引擎:

    ARCHIVE 用于数据存档(行被插入后不能再修改)

    BLACKHOLE 丢弃写操作,读操作会返回空内容

    CSV 在存储数据时,以逗号分隔各个数据项

    FEDERATED 用来访问远程表

    InnoDB 具备外键支持功能的事务存储引擎

    MEMORY 置于内存的表

    MERGE 用来管理多个MyISAM表构成的表集合

    MyISAM 主要的非事务处理存储引擎

    NDB MySQL集群专用存储引擎

    3.MyISAMInnoDB表引擎的区别

    1) 事务支持

    MyISAM不支持事务,而InnoDB支持。

    事务:访问并更新数据库中数据的执行单元。事物操作中,要么都执行要么都不执行

    2) 存储结构

    MyISAM:每个MyISAM在磁盘上存储成三个文件。

    • .frm文件存储表结构。
    • .MYD文件存储数据。
    • .MYI文件存储索引。

    InnoDB:主要分为两种文件进行存储

    • .frm 存储表结构
    • .ibd 存储数据和索引 (也可能是多个.ibd文件,或者是独立的表空间文件)

    3) 表锁差异

    MyISAM:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。

     InnoDB:支持事务和行级锁,是innodb的最大特色

    行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。

    4) 表主键

    MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。 InnoDB:如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。

    InnoDB的主键范围更大,最大是MyISAM的2倍。

    5) 表的具体行数

    MyISAM:保存有表的总行数,如果select count() from table;会直接取出出该值。 InnoDB:没有保存表的总行数

    (只能遍历),如果使用select count() from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,

    myisam和innodb处理的方式都一样。

    6) CURD操作

    MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。 InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令。

    7) 外键

    MyISAM:不支持 InnoDB:支持

    8) 查询效率

    MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。

    推荐考虑使用InnoDB来替代MyISAM引擎,原因是InnoDB自身很多良好的特点,比如事务支持、存储 过程、视图、行级锁定等等,在并发很多的情况下,相信InnoDB的表现肯定要比MyISAM强很多。

    另外,任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势。如果不是很复杂的Web应用,非关键应用,还是可以继续考虑MyISAM的,这个具体情况可以自己斟酌。

    9MyISAMInnoDB两者的应用场景

    MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。 InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。现在默认使用InnoDB。

    4.了解一下字符集和乱码

    字符集简介

    我们知道在计算机中只能存储二进制数据,那该怎么存储字符串呢?当然是建立字符与二进制数据的映射关系了,

    建立这个关系最起码要搞清楚两件事儿:

    1. 你要把哪些字符映射成二进制数据?

    也就是界定清楚字符范围。

    2. 怎么映射?

    将一个字符映射成一个二进制数据的过程也叫做 编码 ,将一个二进制数据映射到一个字符的过程叫做 解码 。人们抽象出一个 字符集 的概念来描述某个字符范围的编码规则

    我们看一下一些常用字符集的情况:

    ASCII 字符集

    共收录128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符。由于总共才128个字符,所以可以使用1个字节来进行编码,我们看一些字符的编码方式:

    • 'L' -> 01001100(十六进制:0x4C,十进制:76)
    • 'M' -> 01001101(十六进制:0x4D,十进制:77)

    ISO 8859-1 字符集

    共收录256个字符,是在 ASCII 字符集的基础上又扩充了128个西欧常用字符(包括德法两国的字母),也可以使用1个字节来进行编码。这个字符集也有一个别名 latin1 。

    GB2312 字符集

    收录了汉字以及拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母。其中收录汉字6763个,其他文字符号682个。同时这种字符集又兼容 ASCII 字符集,所以在编码方式上显得有些奇怪:

    • 如果该字符在 ASCII 字符集中,则采用1字节编码。
    • 否则采用2字节编码。

    这种表示一个字符需要的字节数可能不同的编码方式称为 变长编码方式 。比方说字符串 '爱u' ,其

    中 '爱' 需要用2个字节进行编码,编码后的十六进制表示为 0xCED2 , 'u' 需要用1个字节进行编码,编码后的十六进制表示为 0x75 ,所以拼合起来就是 0xCED275 。

    小贴士: 我们怎么区分某个字节代表一个单独的字符还是代表某个字符的一部分呢?别忘了 ASCII 字符集只收录128个字符,使用0~127就可以表示全部字符,所以如果某个字节是在0~127之内的,就意味着一个字节代表一个单独的字符,否则就是两个字节代表一个单独的字符。

    GBK 字符集

    GBK 字符集只是在收录字符范围上对 GB2312 字符集作了扩充,编码方式上兼容 GB2312 。

    utf8 字符集

    收录地球上能想到的所有字符,而且还在不断扩充。这种字符集兼容 ASCII 字符集,采用变长编码方式,编码一个字符需要使用1~4个字节,比方说这样:

    • 'L' -> 01001100(十六进制:0x4C)
    • '啊' -> 111001011001010110001010(十六进制:0xE5958A)

    小贴士: 其实准确的说,utf8只是Unicode字符集的一种编码方案,Unicode字符集可以采用utf8、

    utf16、utf32这几种编码方案,utf8使用1~4个字节编码一个字符,utf16使用2个或4个字节编码一个字符,utf32使用4个字节编码一个字符。更详细的Unicode和其编码方案的知识不是本书的重点,大家上网查查哈~ MySQL中并不区分字符集和编码方案的概念,所以后边唠叨的时候把utf8、utf16、utf32 都当作一种字符集对待。

    对于同一个字符,不同字符集也可能有不同的编码方式。比如对于汉字 '我' 来说, ASCII 字符集中根本没有收录这个字符, utf8 和 gb2312 字符集对汉字 我 的编码方式如下:

    • utf8编码:111001101000100010010001 (3个字节,十六进制表示是:0xE68891)
    • gb2312编码:1100111011010010 (2个字节,十六进制表示是:0xCED2)

    5.MySQL中的utf8utf8mb4

    我们上边说 utf8 字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示了。而在 MySQL 中字符集表示一个字符所用最大字节长度在某些方面会影响系统的存储和性能,所以设计 MySQL的大叔偷偷的定义了两个概念:

    • utf8mb3 :阉割过的 utf8 字符集,只使用1~3个字节表示字符。
    • utf8mb4 :正宗的 utf8 字符集,使用1~4个字节表示字符。

    有一点需要大家十分的注意,在 MySQL 中 utf8 是 utf8mb3 的别名,所以之后在 MySQL 中提到 utf8 就意味着使用1~3个字节来表示一个字符,如果大家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请使用 utf8mb4 。

    字符集的查看

    MySQL 支持好多好多种字符集,查看当前 MySQL 中支持的字符集可以用下边这个语句:

    show charset;

    8.MySQL 数据操作 DML

    数据的DML操作:添加数据,修改数据,删除数据

    添加数据

    格式: insert into 表名[(字段列表)] values(值列表...);

    --标准添加(指定所有字段,给定所有的值)

    mysql> insert into stu(id,name,age,sex,classid) values(1,'zhangsan',20,'m','lamp138');

    Query OK, 1 row affected (0.13 sec)

    --指定部分字段添加值

    mysql> insert into stu(name,classid) value('lisi','lamp138');

    Query OK, 1 row affected (0.11 sec)

    -- 不指定字段添加值

    mysql> insert into stu value(null,'wangwu',21,'w','lamp138');

    Query OK, 1 row affected (0.22 sec)

    -- 批量添加值

    mysql> insert into stu values

    -> (null,'zhaoliu',25,'w','lamp94'),

    -> (null,'uu01',26,'m','lamp94'),

    -> (null,'uu02',28,'w','lamp92'),

    -> (null,'qq02',24,'m','lamp92'),

    -> (null,'uu03',32,'m','lamp138'),

    -> (null,'qq03',23,'w','lamp94'),

    -> (null,'aa',19,'m','lamp138');

    Query OK, 7 rows affected (0.27 sec)

    Records: 7 Duplicates: 0 Warnings: 0

    修改数据

    格式:update 表名 set 字段1=值1,字段2=值2,字段n=值n... where 条件

    -- 将id为11的age改为35,sex改为m值

    mysql> update stu set age=35,sex='m' where id=11;

    Query OK, 1 row affected (0.16 sec)

    Rows matched: 1 Changed: 1 Warnings: 0

    -- 将id值为12和14的数据值sex改为m,classid改为lamp92

    mysql> update stu set sex='m',classid='lamp92' where id=12 or id=14 --等价于下面

    mysql> update stu set sex='m',classid='lamp92' where id in(12,14);

    Query OK, 2 rows affected (0.09 sec)

    Rows matched: 2 Changed: 2 Warnings: 0

    删除数据

    格式:delete from 表名 [where 条件]

    -- 删除stu表中id值为100的数据

    mysql> delete from stu where id=100;

    Query OK, 0 rows affected (0.00 sec)

    -- 删除stu表中id值为20到30的数据

    mysql> delete from stu where id>=20 and id<=30;

    Query OK, 0 rows affected (0.00 sec)

    -- 删除stu表中id值为20到30的数据(等级于上面写法)

    mysql> delete from stu where id between 20 and 30;

    Query OK, 0 rows affected (0.00 sec)

    -- 删除stu表中id值大于200的数据

    mysql> delete from stu where id>200;

    Query OK, 0 rows affected (0.00 sec)

    9.MySQL数据查询SQL

    语法格式:

    select 字段列表|* from 表名

    [where 搜索条件]

    [group by 分组字段 [having 分组条件]]

    [order by 排序字段 排序规则]

    [limit 分页参数]

    基础查询

    # 查询表中所有列 所有数据

    select * from users;

    # 指定字段列表进行查询

    select id,name,phone from users;

    Where 条件查询

    可以在where子句中指定任何条件

    可以使用 and 或者 or 指定一个或多个条件

    where条件也可以运用在update和delete语句的后面

    where子句类似程序语言中if条件,根据mysql表中的字段值来进行数据的过滤

    示例:

    -- 查询users表中 age > 22的数据

    select * from users where age > 22;

    -- 查询 users 表中 name=某个条件值 的数据

    select * from users where name = '王五';

    -- 查询 users 表中 年龄在22到25之间的数据

    select * from users where age >= 22 and age <= 25;

    select * from users where age between 22 and 25;

    -- 查询 users 表中 年龄不在22到25之间的数据

    select * from users where age < 22 or age > 25;

    select * from users where age not between 22 and 25;

    -- 查询 users 表中 年龄在22到25之间的女生信息

    select * from users where age >= 22 and age <= 25 and sex = '女';

    and和or 使用时注意

    假设要求 查询 users 表中 年龄为22或者25 的女生信息

    select * from users where age=22 or age = 25 and sex = '女';

    思考上面的语句能否返回符合条件的数据?

    实际查询结果并不符合要求?

    select * from users where age=22 or age = 25 and sex = '女';

    +------+--------+------+-------+-------+------+------+

    | id | name | age | phone | email | sex | mm |

    +------+--------+------+-------+-------+------+------+

    | 1 | 章三 | 22 | | NULL | 男 | 0 |

    | 1002 | cc | 25 | 123 | NULL | 女 | NULL |

    +------+--------+------+-------+-------+------+------+

    2 rows in set (0.00 sec)

    -- 上面的查询结果并不符合 查询条件的要求。

    -- 问题出在 sql 计算的顺序上,sql会优先处理and条件,所以上面的sql语句就变成了

    -- 查询变成了为年龄22的不管性别,或者年龄为 25的女生

    -- 如何改造sql符合我们的查询条件呢?

    -- 使用小括号来关联相同的条件

    select * from users where (age=22 or age = 25) and sex = '女';

    +------+------+------+-------+-------+------+------+

    | id | name | age | phone | email | sex | mm |

    +------+------+------+-------+-------+------+------+

    | 1002 | cc | 25 | 123 | NULL | 女 | NULL |

    +------+------+------+-------+-------+------+------+

    1 row in set (0.00 sec)

    Like 子句

    我们可以在where条件中使用=,<,> 等符合进行条件的过滤,但是当想查询某个字段是否包含时如何过滤?

    可以使用like语句进行某个字段的模糊搜索,

    例如: 查询 name字段中包含五的数据

    -- like 语句 like某个确定的值 和。where name = '王五' 是一样

    select * from users where name like '王五';

    +----+--------+------+-------+-----------+------+------+

    | id | name | age | phone | email | sex | mm |

    +----+--------+------+-------+-----------+------+------+

    | 5 | 王五 | 24 | 10011 | ww@qq.com | 男 | 0 |

    +----+--------+------+-------+-----------+------+------+

    1 row in set (0.00 sec)

    -- 使用 % 模糊搜索。%代表任意个任意字符

    -- 查询name字段中包含五的

    select * from users where name like '%五%';

    -- 查询name字段中最后一个字符 为 五的

    select * from users where name like '%五';

    -- 查询name字段中第一个字符 为 王 的

    select * from users where name like '王%';

    -- 使用 _ 单个的下划线。表示一个任意字符,使用和%类似

    -- 查询表中 name 字段为两个字符的数据

    select * from users where name like '__';

    -- 查询 name 字段最后为五,的两个字符的数据

    select * from users where name like '_五';

    注意:where子句中的like在使用%或者_进行模糊搜索时,效率不高,使用时注意:

    尽可能的不去使用%或者_

    如果需要使用,也尽可能不要把通配符放在开头处

    Mysql中的统计函数(聚合函数)

    max(),min(),count(),sum(),avg()

    # 计算 users 表中 最大年龄,最小年龄,年龄和及平均年龄

    select max(age),min(age),sum(age),avg(age) from users;

    +----------+----------+----------+----------+

    | max(age) | min(age) | sum(age) | avg(age) |

    +----------+----------+----------+----------+

    | 28 | 20 | 202 | 22.4444 |

    +----------+----------+----------+----------+

    -- 上面数据中的列都是在查询时使用的函数名,不方便阅读和后期的调用,可以通过别名方式 美化

    select max(age) as max_age,

    min(age) min_age,sum(age) as sum_age,

    avg(age) as avg_age

    from users;

    +---------+---------+---------+---------+

    | max_age | min_age | sum_age | avg_age |

    +---------+---------+---------+---------+

    | 28 | 20 | 202 | 22.4444 |

    +---------+---------+---------+---------+

    -- 统计 users 表中的数据量

    select count(*) from users;

    +----------+

    | count(*) |

    +----------+

    | 9 |

    +----------+

    select count(id) from users;

    +-----------+

    | count(id) |

    +-----------+

    | 9 |

    +-----------+

    -- 上面的两个统计,分别使用了 count(*) 和 count(id),结果目前都一样,有什么区别?

    -- count(*) 是按照 users表中所有的列进行数据的统计,只要其中一列上有数据,就可以计算

    -- count(id) 是按照指定的 id 字段进行统计,也可以使用别的字段进行统计,

    -- 但是注意,如果指定的列上出现了NULL值,那么为NULL的这个数据不会被统计

    -- 假设有下面这样的一张表需要统计

    +------+-----------+------+--------+-----------+------+------+

    | id | name | age | phone | email | sex | mm |

    +------+-----------+------+--------+-----------+------+------+

    | 1 | 章三 | 22 | | NULL | 男 | 0 |

    | 2 | 李四 | 20 | | NULL | 女 | 0 |

    | 5 | 王五 | 24 | 10011 | ww@qq.com | 男 | 0 |

    | 1000 | aa | 20 | 123 | NULL | 女 | NULL |

    | 1001 | bb | 20 | 123456 | NULL | 女 | NULL |

    | 1002 | cc | 25 | 123 | NULL | 女 | NULL |

    | 1003 | dd | 20 | 456 | NULL | 女 | NULL |

    | 1004 | ff | 28 | 789 | NULL | 男 | NULL |

    | 1005 | 王五六 | 23 | 890 | NULL | NULL | NULL |

    +------+-----------+------+--------+-----------+------+------+

    9 rows in set (0.00 sec)

    -- 如果按照sex这一列进行统计,结果就是8个而不是9个,因为sex这一列中有NULL值存在

    mysql> select count(sex) from users;

    +------------+

    | count(sex) |

    +------------+

    | 8 |

    +------------+

    聚合函数除了以上简单的使用意外,通常情况下都是配合着分组进行数据的统计和计算

    Group BY 分组

    group by 语句根据一个或多个列对结果集进行分组

    一般情况下,是用与数据的统计或计算,配合聚合函数使用

    -- 统计 users 表中 男女生人数

    -- 很明显按照上面的需要,可以写出两个语句进行分别统计

    select count(*) from users where sex = '女';

    select count(*) from users where sex = '男';

    -- 可以使用分组进行统计,更方便

    select sex,count(*) from users group by sex;

    +------+----------+

    | sex | count(*) |

    +------+----------+

    | 男 | 4 |

    | 女 | 5 |

    +------+----------+

    -- 统计1班和2班的人数

    select classid,count(*) from users group by classid;

    +---------+----------+

    | classid | count(*) |

    +---------+----------+

    | 1 | 5 |

    | 2 | 4 |

    +---------+----------+

    -- 分别统计每个班级的男女生人数

    select classid,sex,count(*) as num from users group by classid,sex;

    +---------+------+-----+

    | classid | sex | num |

    +---------+------+-----+

    | 1 | 男 | 2 |

    | 1 | 女 | 3 |

    | 2 | 男 | 2 |

    | 2 | 女 | 2 |

    +---------+------+-----+

    # 注意,在使用。group by分组时,一般除了聚合函数,其它在select后面出现的字段列都需要出现在grouop by 后面

    Having 子句

    having时在分组聚合计算后,对结果再一次进行过滤,类似于where,

    where过滤的是行数据,having过滤的是分组数据

    -- 要统计班级人数

    select classid,count(*) from users group by classid;

    -- 统计班级人数,并且要人数达到5人及以上

    select classid,count(*) as num from users group by classid having num >=5;

    Order by 排序

    我们在mysql中使用select的语句查询的数据结果是根据数据在底层文件的结构来排序的,

    首先不要依赖默认的排序,另外在需要排序时要使用orderby对返回的结果进行排序

    Asc 升序,默认

    desc降序

    -- 按照年龄对结果进行排序,从大到小

    select * from users order by age desc;

    -- 从小到大排序 asc 默认就是。可以不写

    select * from users order by age;

    -- 也可以按照多个字段进行排序

    select * from users order by age,id; # 先按照age进行排序,age相同情况下,按照id进行排序

    select * from users order by age,id desc;

    Limit 数据分页

    limit n 提取n条数据,

    limit m,n 跳过m跳数据,提取n条数据

    -- 查询users表中的数据,只要3条

    select * from users limit 3;

    -- 跳过前4条数据,再取3条数据

    select * from users limit 4,3;

    -- limit一般应用在数据分页上面

    -- 例如每页显示10条数据,第三页的 limit应该怎么写? 思考

    第一页 limit 0,10

    第二页 limit 10,10

    第三页 limit 20,10

    第四页 limit 30,10

    -- 提取 user表中 年龄最大的三个用户数据 怎么查询?

    select * from users order by age desc limit 3;

    10.Mysql数据库导入导出和授权

    数据导出

    1.数据库数据导出

    # 不要进入mysql,然后输入以下命令 导出某个库中的数据

    mysqldump -u root -p tlxy > ~/Desktop/code/tlxy.sql

    导出一个库中所有数据,会形成一个建表和添加语句组成的sql文件之后可以用这个sql文件到别的库,或着本机中创建或回复这些数据

    2.将数据库中的表导出

    # 不要进入mysql,然后输入以下命令 导出某个库中指定的表的数据

    mysqldump -u root -p tlxy tts > ~/Desktop/code/tlxy-tts.sql

    数据导入

    把导出的sql文件数据导入到mysql数据库中

    # 在新的数据库中 导入备份的数据,导入导出的sql文件

    mysql -u root -p ops < ./tlxy.sql

    # 把导出的表sql 导入数据库

    mysql -u root -p ops < ./tlxy-tts.sql

    权限管理

    mysql中的root用户是数据库中权限最高的用户,千万不要用在项目中。

    可以给不同的用户,或者项目,创建不同的mysql用户,并适当的授权,完成数据库的相关操作。这样就一定程度上保证了数据库的安全。

    创建用户的语法格式:

    grant 授权的操作 on 授权的库.授权的表 to 账户@登录地址 identified by ‘密码’;

    示例:

    # 在mysql中 创建一个 zhangsan 用户,授权可以对tlxy这个库中的所有表 进行 添加和查询 的权限

    grant select,insert on tlxy.* to zhangsan@'%' identified by '123456';

    # 用户 lisi。密码 123456 可以对tlxy库中的所有表有 所有操作权限

    grant all on tlxy.* to lisi@'%' identified by '123456';

    # 删除用户

    drop user 'lisi'@'%';

    热门专栏推荐:

    🥇 大数据集锦专栏:大数据-硬核学习资料 & 面试真题集锦 
    🥈 数据仓库专栏:数仓发展史、建设方法论、实战经验、面试真题 
    🥉 Python专栏:Python相关黑科技:爬虫、算法、小工具 

    (优质好文持续更新中……)✍

    展开全文
  • 函数的定义和使用

    千次阅读 2020-09-02 19:58:41
    那么,我们可以自己定义函数,来实现某项任务。函数的定义格式如下: 返回数据类型函数名(形参列表) { 函数体 } 函数定义格式说明: 函数定义的第一个单词是“返回数据类型”,它说明该函数的返回类型;如果是...
  • 文章目录linux 系统命令总结大全关于作者**作者介绍**0.IP 地址相关命令0.1 ifconfig 命令 ---显示网络设备信息02.ip 命令 ---显示与操作路由03.dhclient 命令 --- 动态获取或释放IP地址04.nmtui ---界面修改网卡...
  • 命令执行漏洞

    千次阅读 2021-11-15 19:10:52
    为什么客户端能直接对服务器执行命令呢,因为在服务器安装的web程序,web框架和web组件等外部程序有时候去需要调用执行命令的函数,所以如果没有对客户端用户输入的命令进行过滤,就会使得用户通过外部程序直接编写...
  • C语言宏定义

    万次阅读 多人点赞 2021-08-03 09:08:04
    1)#define 叫做宏定义命令它也是C语言预处理命令的一种,所谓宏定义,就是用一个标识符来表示一个字符串。如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。 2)#define N 100 就是宏定义,N为...
  • 使用#define指令进行宏定义 宏定义的功能是用一个标识符来表示字符串,标识符称为宏名。在预编译处理时,对程序中出现的宏名,在程序中出现的宏名,都用宏定义中出现的字符串去代替。  #define 指令的形式是: #...
  • 命令执行漏洞详解

    千次阅读 2022-03-08 11:59:57
    一、命令执行漏洞原理 在编写程序的时候,当碰到要执行系统命令来获取一些信息时,就要调用外部命令的函数,比如php中的exec()、system()等,如果这些函数的参数是由用户所提供的,那么恶意用户就可能通过构造命令...
  • verilog数组定义及其初始化

    千次阅读 2020-12-21 23:23:35
    这里的内存模型指的是内存的行为模型。Verilog中提供了两维数组来帮助我们建立内存...这样的数组的定义方式如下:reg [wordsize : 0] array_name [0 : arraysize];例如:reg [7:0] my_memory [0:255];其中 [7:0]是内...
  • 预处理命令

    千次阅读 多人点赞 2019-07-27 22:40:10
    一、预处理命令 二、#include 1.尖括号/引号引入标准头文件区别 2.#include 用法举例 三、C语言宏定义----#define 四、带参数的宏定义 对带参宏定义的说明 五、C语言带参宏定义和函数的区别 六、C语言宏...
  • 下面是条件判断中使用到的一些关键字: 关键字 功能 ifeq 判断参数是否不相等,相等为 true,不相等为 false ifneq 判断参数是否不相等,不相等为 true,相等为 false ifdef 判断是否有值,有值为 true...
  • C语言之预处理命令

    千次阅读 2021-05-21 00:39:13
    原标题:C语言之预处理命令在C语言中,说明语句和可执行语句由来完成程序的功能,除此之外,还有一些预编译处理命令,所有的预编译处理都以#号开头,占用源程序中的一行,一般是放在源程序中的首部。注意:编译...
  • Linux命令大全(常用的命令解析)

    万次阅读 多人点赞 2022-03-24 09:48:42
    Linux命令大全。详细介绍了比较常用的一些命令
  • linux必学的60个命令

    万次阅读 多人点赞 2022-02-18 19:05:21
    Linux提供了大量的命令,利用它可以有效地完成大量的工 ...这里笔者把比较重要和使用频率最多的命令,按照它们在系统中的作用分成下面六个部分一一介绍。 ◆ 安装和登录命令:login、shutdown、hal
  • Linux中常用命令(初学者必备)

    万次阅读 多人点赞 2022-03-14 22:47:12
    2.在职场中,大量的服务器维护工作都是在远程通过SSH客户端来完成的,并没有图形界面,所有的维护工作都需要通过命令来完成在职场中,作为后端程序员,必须要或多或少的掌握一些Linux常用的终端命令。 3.Linux发行...
  • 有关Linux创建用户命令的详细讨论

    千次阅读 2021-05-09 00:57:11
    Linux创建用户命令1:创建新用户useradd命令(也可以使用adduser)用来创建新的用户帐号,其命令格式如下:useradd命令常用选项-d 设置新用户的登陆目录-e 设置新用户的停止日期,日期格式为MM/DD/YY-f 帐户过期几日后...
  • Linux命令大全----常用文件操作命令

    万次阅读 多人点赞 2015-10-19 08:43:25
    本文主要讲了Linux命令大全----常用文件操作命令,并附有实例
  • ADB常用命令及其用法大全

    万次阅读 多人点赞 2019-02-23 22:03:15
    本文主要记述ADB的常用命令,关于ADB用法大全,可参考文末链接 ADB简介: ADB,即 Android Debug Bridge,它是 Android 开发/测试人员不可替代的强大工具,也是 Android 设备玩家的好玩具。安卓调试桥 (Android ...
  • dos命令大全

    万次阅读 2021-10-04 12:21:37
    正如大家所看到的,我把dos命令整理出来了!!! 整整用了我一个星期的时间 建议收藏后阅读 Windows常用工具类 运行程序 运行命令 记事本 notepad 计算器 calc 画图 mspaint 写字板 write Windows放大镜 ...
  • Dos命令大全完整版

    万次阅读 多人点赞 2018-07-18 10:14:03
    DOS(磁盘操作系统)命令,是DOS操作系统的命令,是一种面向磁盘的操作命令,主要包括目录操作类命令、磁盘操作类命令、文件操作类命令和其它命令。 使用技巧 DOS命令不区分大小写,比如C盘的Program Files,在dos...
  • Gcode命令

    千次阅读 2020-10-12 12:02:35
    Gcode命令 https://www.jianshu.com/p/f8a328457a45 简述 研究过3D打印机的朋友,都会用到G-code文件。要使用3D打印机打印东西要经过几个步骤: 1、创建3D模型 2、切片软件处理,生成3D打印机能识别的命令(保存...
  • ftp登陆命令

    千次阅读 2018-10-16 22:19:26
    一、shelll示例: cd /PATH_YOU_WANT_TO_UPLOAD(DOWNLOAD)ftp -niv &amp;lt;&amp;lt;- EOFopen IP_ADDRESSuser USERNAME ...下面详细讲解以下这代码: &amp;nbsp;&amp;nbsp;&amp;nb...
  • Linux系统常用的基本命令

    万次阅读 多人点赞 2018-08-15 15:11:08
    下面开始介绍。 一、查看哪个用户登录的系统 1、users命令 2、whoami命令或者who am i命令 二、查看哪些用户在系统上工作 1、who命令 2、w命令 三、查看登录Linux系统所使用的终端 1、tty命令 四...
  • PyCharm:进程以退出代码0结束

    万次阅读 2020-12-23 15:31:22
    您还可以定义退出代码以进行分析,例如: ERROR_USERNAME, ERROR_PASSWORD, RIGHT_CODE = 683, 11, 0 right_name, right_password = 'xy', 'xy' name, password = 'xy', 'wrong_password' if name != right_name: ...
  • Linux常用操作命令大全

    万次阅读 多人点赞 2022-02-07 20:24:48
    Linux常用操作命令大全
  • 有趣的10个CMD命令

    万次阅读 多人点赞 2022-02-09 11:30:51
    有趣的10个CMD命令
  • awk命令详解

    千次阅读 2022-01-25 19:46:01
    awk命令 参考资料:https://blog.csdn.net/u010502101/article/details/81839519 AWK, 数据过滤工具 (类似于grep,比grep强大),属数据处理引擎,基于模式匹配检查输入文本,逐行处理并输出。通常用在Shell脚本中...
  • 一维数组的定义、初始化和引用

    千次阅读 2021-05-19 08:32:45
    一维数组的定义、初始化和引用一维数组的定义、初始化和引用1.一维数组的定义方式为:类型说明符 数组名[常量表达式](1)数组名的命名方法与变量名相同,遵循标识符命名规则;(2)数组是用方括号括起来的常量表达式,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 228,237
精华内容 91,294
热门标签
关键字:

下面表示段定义结束的命令是