C#

微软开发的语言,特点:

  1. 面向对象,跨平台,开源

  2. 安全、稳定、简单

  3. 继承c和c++, 可以用指针但是不建议使用,结合了java的特性

  4. 运行于.Net framework和.Net core上
    .Net 是什么:

    • 运行c#的平台,c#只能运行在该平台,但是该平台可以运行VB, C++等语言

    • .Net提供给c#一些工具,让其更好的运行

    • .Net可以用visual studio ide安装

  5. .Net framework由common language runtime (CLR)和类库构成(有很多现成的类,省去从头造轮子),.Net framework只能运行于Windows下,而.Net core可以跨平台

  6. C#应用领域为游戏软件开发,桌面应用系统开发,智能手机程序开发,web应用开发,物联网开发

vscode开发dotnet:

  • 安装dsk
  • vscode插件c#, material icon,
  • 终端输入dotnet new <模版标签> -o <项目路径> -n <项目名>:生成一个工作目录,<标签模版>:console, avalonia.app, classlib(类库模版), sln(解决方案)等
  • dotnet build [–output] [–framework] <项目名>|<*.csproj>:编译
  • dotnet clean 清除项目
  • 运行dotnet run <项目名>|<*.dll>
  • dotnet add <包> 加NuGet包
  • dotnet new install <包>安装.Net模版命令
  • dotnet workload install <包>安装.Net SDK中的工作负载命令,工作负载是一组相关功能和工具集合
  • dotnet new search <包>
  • dotnet restore <项目名> 还原索引的包packageReference,还原给定应用程序的依赖项
  • c#自带一些默认格式lauch.json和task.json
  • dotnet pack:创建NuGet包
  • botnet publish:发布.Net依赖于框架或独立的应用程序
  • dotnet sln <解决方案名> add|list|remove <项目目录>: 增|列|删解决方案,解决方案是多个项目的集合,.sln文件

UI窗体开发库avalonia
dotnet new avalonia.app -o MyApp创建一个工作目录
dotnet new install Avalonia.Templates创建一个avalonia项目模版
vscode中安装avanolia插件,可预览.axaml文件

语法基础

c sharp的源码文件是.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
using Microsoft.AspNetCore;//引用别人的命名空间或项目,可以直接使用名称空间里的工具
using Microsoft.AspNetCore.Hosting;

namespace WebApplication1 //声明/定义项目的命名空间,一般也是项目本身的名称
{
public class Program //类名
{
public static void Main(string[] args) //方法或函数
{
//方法体
}
}
}
  • c#程序的入口点是Main方法,

  • c#是大小写敏感的语言, 每个语句以";"结尾,

  • 程序的文件名和程序类名可以不一致(java要一致)

  • 注释使用单行"//“,多行”/* */“,文档”///"一般用于描述函数或者类的功能,调用函数或者定义类对象时会告诉我们调用的函数或者定义的对象的类是干什么的

  • 变量或对象先定义后使用

  • c#关键字有:using, class, public, static, private, void, namespace, new, string, char, var

    • 数字类型:
    • 整形:byte,short,int,long
    • 浮点:float, double
      • 数值范围大的类型不能赋给数值范围小的类型, 浮点型包含整数和小数,如果复制给变量的小数不加任何后缀默认为double类型, float后缀F
    • 十进制:decimal
      • 后缀M, 精度比float类型高,注:double,float,decimal,精度损失系统不会提示, decimal不能和double,float做转换
    • 布尔:bool
    • 字符:string, char
      • string必须用双引号,char必须用单引号且只包含一个字符
    • 空类型:null
      • 作右值使用,变量盒子里面放空值,数字类型和布尔类型不可以用null
  • 变量相当于装数据的盒子

  • 命名规范:驼峰命名,多个单词拼接时第一个首字母小写,其他单词首字母大写

  • 隐式转化/显示转化:

    • double price = 16 隐式转化

    • (T)x, (int)x:只截取整数部分

    • int.Parse(String s):将string类型转成int, double.Parse(String s):将string类型转成double等

    • Convert.Toint32(double value):一般尊循四舍五入除了*.5以外,此时取相邻两个整数中的偶数

  • using():自动释放
    通常,我们以下面的形式声明一个非托管资源,当代码块执行完之后,资源会自动释放,那程序是如何做到的呢?

    1
    2
    3
    4
    using (var file = File.Open("filePath", FileMode.OpenOrCreate))
    {
    //do something
    }

    using(…)语句经编译器编译之后,转换了try{…}finally{…}上面的代码,经程序编译后的代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    FileStream file = File.Open("filePath", FileMode.OpenOrCreate);
    try
    {
    //do something
    }
    finally
    {
    if (file!= null)
    {
    ((IDisposable)file).Dispose();
    }
    }

表达式

  • 表达式由操作数和运算符构成
    • 操作数包含:文本、字段、局部变量、表达式
    • 多个运算符涉及优先级,运算符可以重载
  • 运算符
    • 类别 表达式 说明
      基本 x.m 访问成员
      x(…) 方法调用和委托调用
      x[…] 数组和索引器访问
      new T(…) 对象和委托创建
      new T(…){…} 创建对象并设初始值
      new {…} 创建匿名对象并设初始值
      new T[…] 创建数组
      一元 +x 恒等
      -x 求相反数
      !x 逻辑求反
      ~x 按位求反
      ++x 前增
      –x 前减
      x++ 后增
      x– 后减
      (T)x 强制类型转换为T类型
      二元 x*y
      x/y
      x%y 求余
      x+y
      x-y
      x<<y 左移
      x>>y 右移
      x<y
      x>y
      x<=y
      x>=y
      x is T 如果x为T,返回true,否则返回false
      x as T 返回转换为类型T的x, 如果x不是T则返回null
      x == y
      x!=y
      x & y 整型按位and, 布尔逻辑and
      x|y 整型按位or, 布尔逻辑or
      x && y 仅当x为true时,才对y求值, x为真且y为真表达式为真
      x || y x为真或y为真表达式为真
      x ?? y 如果x为null,则计算结果为y,否则计算结果为x
      x+=y
      (T x)=>y 匿名函数(lambda表达式)
      三元 x?y:z 如果x为true,则对y求值,如果x为false,则对z求值
  • 加法:“hello” + 18会得到"hello18", “hello”+“word” 得到"helloword"
  • 字符串比较: “hello” == “word”, “hello” != “word”
  • 且/或

作用域

"{}"括号内的区域为作用域,在作用域内定义的变量只能在作用域中存在,超出作用域不存在,在作用域外定义的变量可以在作用域中使用,作用域内外都定义同一变量则按照从内到外覆盖原有变量

分支语句

  • if
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //1
    if(i>1){
    ...
    }
    //2
    if(i>1){
    ...
    }else{
    ...
    }
    //3
    if(i>1){
    ...
    }else if (i>0 && i<10){
    ...
    }else{
    ...
    }
  • switch
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    switch(i){
    case 1:
    ...
    break;
    case 2:
    ...
    break;
    default:
    ...
    break;
    }
    i必须是整型1,枚举或字符型"abc"/‘a’, case后必须是整型1,枚举或字符型"abc"/‘a’, break非必须,但是没有break不会跳出switch语句而是顺序执行之后的各case

循环语句

  • for
    1
    2
    3
    for(int i=0; i<10; i++){
    ...
    }
  • while
    1
    2
    3
    while(i<10){
    ...
    }
  • do while
    1
    2
    3
    do{
    ...
    }while(i<10)

数组

  • int[] ints = new int[6] 数组声明
  • int[] ints = new int[]{1,2,3,4} 数组声明并初始化
  • string[] strings = new string[5]{“H”, “E”, “L”, “L”, “O”}
  • 数组长度确定后无法修改数组长度,声明数组大小必须使用常量而非变量

函数

  • 对象行为
  • 函数所承担的行为越单一越好
  • 命名规范:大驼峰命名,即开头首字母大写,多个单词拼接式所有单词首字母大写
  • 函数参数
    • 外部需要函数帮忙处理的数据,外部通过参数形式将数据交给函数
    1
    2
    3
    public void Add(int firstCount, int secondCount){//权限:public、private, protect
    int total = firstCount + secondCount;
    }
    • 参数修饰符
      1. 无参数修饰符,参数按值传递,函数内对形参的修改不影响对应的实参
      2. out修饰符,参数按引用传递,函数内对形参的修改影响对应的实参,out实参可以是空值或者非空值,函数内部必须给对应out形参赋值,例如
        1
        2
        3
        4
        5
        6
        7
        8
        9
        //定义
        public void Add(out int firstCount, int secondCount){//权限:public、private, protect
        fisrtCount = 3;//!!!
        int total = firstCount + secondCount;
        }
        //调用
        Add(out int a, 3);//调用函数时创建一个变量
        int b;
        Add(out b, 3);
      3. ref修饰符,参数按引用传递,函数内对形参的修改影响对应的实参,ref实参必须有值不能为空,函数内部可以给对应ref形参赋值或者不赋值
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        //定义
        public void Add1(out int firstCount, int secondCount){//权限:public、private, protect
        int total = firstCount + secondCount;
        }
        //或者
        //定义
        public void Add2(out int firstCount, int secondCount){//权限:public、private, protect
        fisrtCount = 3;
        int total = firstCount + secondCount;
        }
        //调用
        int b=1;//!!!
        Add(ref b, 3);
        注:out和ref修饰的参数必须在函数定义和函数调用时显示给出。
      4. params修饰符,声明一组若干的实参作为一个params形参,一个函数只能有一个params形参,且params形参在函数参数列表的最后位置
  • 函数返回值:外部调用函数行为后的一种反馈

面向对象 OOP

面向过程编程思想:

  • 算法类的,过程类似于函数只能执行没有返回值,函数既能执行也能返回结果,强调怎么做、过程、步骤,不强调指责分工,缺少固定套路
  • 缺点:代码复杂时维护艰难,很难看懂别人的代码

面向对象编程思想:

  • 强调来做, 在一个对象中封装多个方法
  • 代码逻辑是按业务顺序让不同的对象调用不同的方法
  • 注重对象和职责
  • 分析需求中需要哪些类,那些类应有哪些属性和功能

类和对象

  • 类是创建具有相同特征和行为对象的模版,图纸
  • 对象根据图纸造出的实体
  • C#中万物皆对象,是对象就需要一个类型
  • 类的名称按照大驼峰命名方法
  • 声明类
    1
    2
    3
    public class Person{//访问权限public,默认private

    }
  • 属性命名按照大驼峰命名法
    • 如果属性中有get关键字,则可以把该属性用作右值
    • 如果属性中有set关键字,则可以把该属性用作左值
    1
    2
    3
    public class Person{//访问权限public,默认private
    public int Age {get; set;}
    }
  • 方法命名按照大驼峰命名
  • 实例化用new关键字
    •   Person person = new Person();
      
    person.Name = “张三”;
    person.Age = 18;
    person.Height = 175;
    person.Eat();
    person.Run();
    1
    2
    3
    4
    5
    6
    7
    * 对象初始化器
    ```c#
    Person zhangsan = new Person(){
    Age = 18,
    Height = 175,
    Name = "张三"
    };
  • 访问修饰符(能访问的作用域范围)
    • public:公有,所有的类都可以访问
    • private:私有,当前类内部可以访问
    • protected:受保护,当前类以及继承他的子类可以访问
    • internal:内部的,只限于本项目内访问,其他项目不能访问
    • protected internal:内部保护,本项目内部当前类及其子类访问,其他项目或本项目内的其他类不能访问
  • 静态关键字
    • 静态属性和方法通过static关键字
    • 静态属性和方法只能通过类名获取,非静态属性和方法必须通过实例化对象获取
    • 静态方法中只能使用类中的静态字段的属性
    • 静态类:当类型中存在扩展方法时需要使用静态类

集合/字典/列表

数组优劣:

  • 数组连续存储,访问速度快,
  • 在数组中间插入数据很麻烦,使用前数据长度以定义好了,过长会造成内存浪费,过短会造成数据溢出

ArrayList

  • .Net Framework提供的用于存储和检索的专用类
  • 定义在命名空间System.Collections下
  • 优势就是针对数据缺点,1、大小可变,2、便捷添加,插入,移除
  • 常用方法:ArrayList arrayList = new ArrayList()
    • 在结尾处添加数据:arrayList.Add(“abc”), arrayList.Add(123)
    • 修改:arrayList[1] = 345
    • 移除指定索引处的数据:arrayList.RemoveAt(0),移除内容为123的数据arrayList.Remove(123)
    • 在指定索引处插入数据:arrayList.Insert(0,“hello world”)
  • 劣势:
    • ArrayList在存储数据时使用object类型,(object是所有类的父类,父类可以接收子类的对象,但是子类不能接收父类对象),这导致了类型不安全问题(元素类型不匹配)
    • 即使插入的元素类型都一致,我们也需要将他们转化为对应的原类型处理
    • 存储数据存在装箱(把子类赋给父类,失去对象原有类型)和拆箱(父类强制转换成子类)操作,这导致性能低下
      1
      2
      3
      4
      5
      6
      //装箱:int类型或者String等不同类型对象通过隐式转化赋给object对象
      int i = 123;
      object o = i;
      //拆箱:object对象通过显示转换赋给int类型变量
      object o = 123;
      int i = (int)o;
      泛型:
  • c#2.0后出现泛型概念,泛型是用于限制集合能够存储单一类型数据的一种手段。
  • 表示泛型

List集合:

  • List和ArrayList都继承了相同接口, 所以使用方式同ArrayList相似
    • 接口:限制和规定类型行为的一种手段,继承接口的类必须要把接口类的行为都实现
  • 声明List集合时,需要同时给出集合内数据的对象类型
    1
    2
    3
    List<int> intList = new List<int>();
    List<int> intListSecond = new List<int>(){1,2,3};
    List<int> intListThird = new List<int>{1,2,3};
  • List使用自定义类型的泛型时,添加、删除等操作记录的是对象的地址
  • 泛型保证数据类型安全,无装箱拆箱
  • 大小可变

Dictionary集合

  • 声明Dictionary字典时泛型要给出键名和键值的类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Dictionary<int, String> dictionary = new Dictionary<int, String>();
    //键名,键值
    dictionary.Add(1,"98分");
    dictionary.Add(2,"92分");
    dictionary.Add(3,"89分");
    dictionary.Add(1,"88分");//系统报错, 添加了同名键值
    //通过旧键名索引,不是索引序号,以及通过新键名添加
    dictionary[1] = "88分";//系统不报错
    dictionary[4] = "99分";
    //初始化器
    Dictionary<String, String> dictionary2 = new Dictionary<String,String>(){
    {"A", "aa"},
    {"B", "bb"},
    {"C", "cc"}
    };
    Dictionary<int, String> dictionary3 = dictionary;//dictionary3和dictionary是地址间赋值,修改dictionary也会修改dictinoary3
  • 获取键名为1的值 String value = dictionary[1]
  • foreach遍历字典
    *
    1
    2
    3
    4
    foreach (KeyValuePair<int, String> item in dictionary){
    String value = item.Value;
    int name = item.Key;
    }
    • 高效率for循环,因为使用了迭代器
  • 通过键名(不是索引)移除元素dictionary.Remove(1);
  • 字典中键必须是唯一的,值可以不唯一

foreach循环:

  • 数组
    1
    2
    3
    4
    int[] ints = new int[]{1,2,3,4};
    foreach (int item in ints){
    int elem = item;
    }
  • 集合
    1
    2
    3
    4
    List<int> intList = new List<int>(){1,2,3,4};
    foreach (int item in intList){
    int elem = item;
    }
  • 字典
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Dictionary<String, String> dictionary = new Dictionary<String,String>(){
    {"A", "aa"},
    {"B", "bb"},
    {"C", "cc"}
    };
    foreach (KeyValuePair<String, String> item in dictionary){
    String value = item.Value;
    String name = item.Key;
    }

Web基础

理解c/s和b/s:

  • c/s是Client/Server缩写,服务器通常采用高性能的PC,工作站等,并安装大型数据库系统,Orange,SQL Server,客户需要安装专用的客户端软件(如:英雄联盟)。
  • b/s是Browser/Server缩写,客户机只需安装一个浏览器(如:谷歌),服务器安装Oracle,SQL Server数据库,此结构下,用户完全通过浏览器实现,一部分事物逻辑在前端实现,但主要事物逻辑在服务器端实现,浏览器通过网络协议同数据库进行数据交互
  • 开发工具:文本文件,vscode, visual studio等
  • 前端开发语言:HTML, css, js,共同构成了页面的展示

HTML

HTML结构类似人体骨骼,离有血有肉相差甚远image-20231011164908118

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html> <!viscode中输入‘!直接生成模版’>
<html lang="en">
<head>
<meta charset="UTF-8">
<! -- width:可视区域的宽度,值为数字或关键词device-width -->
<! -- intial-scale:页面首次被显示时可视区域的缩放级别,取值1.0则页面按实际尺寸显示,无任何缩放 -->
<! -- maximum-scale=1.0, minimum-scale=1.0:可视区域的缩放级别, 此处1.0禁止用户放大到实际尺寸之上,禁止缩小到实际尺寸之下 -->
<! -- user-scalable:是否可对页面进行缩放,no禁止缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<! 浏览器兼容性模式>
<! 告诉浏览器以“ie=edge”版本来渲染页面,chrome=1说明使用谷歌内核>
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document<\title>
</head>
<body>
/*自此处搭建网页的骨架*/
</body>
</html>

框架标签

  • 定义文档类型html类型
  • 定义HTML文档,开闭标签
  • 定义文档的头部 * 定义文档头部,是所有头部元素的容器,中的元素可以引用脚本,指示浏览器在哪里,找到样式表,提供元信息 * 描述文档的各种属性和信息,包括文档标题、在web中的位置以及和其他文档的关系等,绝大多数文档头部包含的数据都不会真正作为内容显示给读者 * head标签部分可以用:, , , 里面
  • body部分:调用脚本执行; 写在标签里面
  • 外部脚本:定义函数和类型
    • 代码封装到一个扩展名为js的文件中,然后在需要的地方引用;实现一次定义多处引用效果
    • 在文件中不要要写标签
  • 执行顺序:按照从上到下顺序执行(解释型语言)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="javascript1.js"></script>
<script>
alert("这是head区域js代码");
</script>
</head>
<body>
<script>
alert("这是body区域js代码");
</script>
</body>
</html>

基本语法

  • 大小写敏感
  • 弱类型: (c#是强类型语言)定义类型和对像类型一致,(弱类型)定义类型可以用var,既可以接收整型对象也可以接收其他类型的对象(数组,字符串,集合等)。
    • 特点:开发提供便利,想赋什么对象都可以,但是不严谨维护难。JS=>TS,微软封装了JS成为TS(Typescript)目的是将弱类型封装成强类型。Vue3.0兼容TS
  • 分号结尾
  • 注释
    • 单行://
    • 多行:/**/
    • 方法注释:/** 方法名称,参数 */
      1
      2
      3
      4
      5
      6
      7
      8
      /**
      * fun1
      * @param {stirng} param1 这是参数1
      * @param {*} param2
      */
      function fun1(param1,param2){

      }
  • 在 JavaScript 中,varlet 和 const 是用于声明变量的三个关键字。自 ES6 (2015) 引入 let 和 const 以来,它们逐渐取代了 var,成为现代 JavaScript 开发的标准选择。
    • var‌:‌函数作用域‌ (Function Scope)。如果在函数内声明,仅在该函数内有效;
    • let / const‌:‌块级作用域‌ (Block Scope)。仅在声明它们的最近一对花括号 {} 内有效(如 ifforwhile 块)。这能有效避免变量污染外层作用域。
    • var‌:允许在同一作用域内‌重复声明‌同一变量,后续声明会覆盖之前的值(或忽略无赋值的声明)
    • let / const‌:‌禁止‌在同一作用域内重复声明。尝试重复声明会抛出 SyntaxError
    • var / let‌:声明后可以‌重新赋值‌。
    • const‌:声明后‌不可重新赋值‌, 对于对象 (Object) 和数组 (Array),const 保证的是‌引用不变‌,但其内部的属性或元素‌可以修改‌。若要完全冻结对象,需使用 Object.freeze()
    • **var / let**‌:可选初始化。未赋值时默认值为 undefined
    • const‌:‌必须‌在声明时初始化,否则报错。

数据类型

  • 因为是弱类型语言,声明变量类型只需用var关键字即可
  • 其他数据类型
    • boolean布尔
    • number数字
    • string字符串:可以用双引号也可以用单引号
    • Undefined未定义
    • Null空对象
    • Object对象类型
    • Undefined类型和Null类型都是只有一个值的数据类型,值分别为undefined与null
  • typeof用于查看变量类型
    1
    2
    3
    4
    5
    6
    7
    var strValue = "Hello World";
    var valueType = typeof(strValue);
    console.log(valueType);
    alert(valueType);
    var numValue = 123;
    var numType = typeof(numValue);
    alert(numType);

集合

  • 数组:[…]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //初始化方式1
    var array = [1,2,3,4,5,6];
    //初始化方式2
    var array2 = new Array();
    array2[0] = 1;
    array2[1] = 'Hello';
    //初始化方式3
    var array3 = [];
    array3[0] = 1;
    array3[1] = 'Hello';
  • 键值对:{键:值}
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var keyvalue = {"key1":"value1", "key2":"value2", "key3":"value3"};
    var kv = {};
    kv["a"] = "A";//键加引号,json格式的对象
    kv[1] = "B";
    console.log(kv);
    kv.c = "C";
    kv.d = 1;
    console.log(kv)

    var kv1 = {a:"A", b:"B"};//键未加引号, js对象
    console.log(kv1);

    var kv2;
    kv2.a = "a"; //报错, 因为kv2没初值
    kv2['a'] = "a";//报错 因为kv2没初值
    console.log(kv2);

    var kv3 = kv1;
    console.log(kv3);
  • 对象数组:[{属性:值},{},…,{}]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var keyvalue = [
    {"key1":"value1", "key2":"value2", "key3":"value3"},
    {"key1":"value1", "key2":"value2", "key3":"value3"},
    {"key1":"value1", "key2":"value2", "key3":"value3"}
    ];
    //json格式嵌套
    var kv4 = {"aaa":"A", "bbb":{"ba":"BA","bb":"BB"}};
    var arrayKv1 = [{"aa":"A", "bb":"B"},{"aa":"A", "bb":"B"},{"aa":"A", "bb":"B"}];
    var arrayKv2 = [{
    "aaa":"A", "bbb":{
    "ba":"BA",
    "bb":"BB"
    }
    },
    {
    "aaa":"A", "bbb":{
    "ba":"BA",
    "bb":"BB"
    }
    }];
  • array对象属性
    • length设置或返回数组中元素的数目
  • array对象方法
    • concat()连接两个数组
    • join()用分隔符连接数组中的各元素,返回字符串
    • push()数组末尾添加一个元素,返回新的数组长度
    • reverse()颠倒数组中的元素
    • sort()对数组元素排序
    • splice(arg1,arg2,arg3)删除元素,并向数组添加新元素
      • arg1:要删元素的开始索引号
      • arg2:删除元素的数量
      • arg3:在arg1索引号之前插入新的元素内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
//concat()
var ar1 = [2,1,3,4];
var ar2 = [6,5,8,7];
var ar3 = ar1.concat(ar2);
console.log(ar1);
console.log(ar2);
console.log(ar3);
//join()
var ar2Str = ar3.join("|");
console.log(ar2Str);
//push()
var arLength = ar3.push(9);
console.log(arLength);
console.log(ar3);
//reverse()
ar3.reverse();
console.log(ar3);
//sort()
ar3.sort();
console.log(ar3);
//splice()
var array = [1,2,3,4];
console.log(array);
array.splice(1,2,9);
console.log(array);
</script>
</head>
<body>

</body>
</html>
  • 类型转换

    • parseInt()
    • parseFloat()
    • parseJson()
  • for循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var arrayKv2 = [{
"aaa":"A", "bbb":{
"ba":"BA",
"bb":"BB"
}
},
{
"aaa":"A", "bbb":{
"ba":"BA",
"bb":"BB"
}
}];
//普通for循环遍历索引号
for (let index=0; index<arrayKv2.length; index++){
// const element = array[index];
console.log(arrayKv2[index]);
}
console.log("################################################");
//for of循环遍历数组值
for (const kv of arrayKv2){
console.log(kv);
}
console.log("################################################");
//for in循环遍历键,用于键值对或数组(key是数组索引号)
for (const key in kv1) {
console.log(key+": ");
console.log(kv1[key]);
// const element = kv2[key];
}

函数|方法

  • 使用关键字function
  • 函数名:驼峰命名
  • 可以设置参数和返回值,可以不设置参数和返回值类型(弱类型语言)
  • js不存在方法重载,即最后的重名方法会覆盖之前的重名方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
function myFun(p1,p2){
return p1+p2;
}
var res = myFun(1,2);
console.log(res);
</script>
</head>
<body>

</body>
</html>

匿名方法

  • 匿名方法:不需要写方法名称的方法
  • 两种写法
    • 方法一
      把匿名方法赋给变量称为委托,这样做的目的比如sort()函数只接收匿名方法作为参数,直接在sort()括号里写匿名方法有些乱,所以委托给变量
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      //定义
      var fun = function(p1){
      console.log(p1);
      }
      //使用
      fun("Hello");

      var ar1 = [2,1,3,4,6,8,7,9,5];
      ar1.sort(function(a,b){
      return b-a;
      });
      console.log(ar1);
    • 方法二
      定义匿名方法的同时进行调用
      1
      2
      3
      (function (param1, param2){
      console.log(param1+param2);
      })(1,2);

闭包

子方法使用父方法的变量

1
2
3
4
5
6
7
function fn1(){
var p1 = 1;
function fn2{
var p2 = p1;//p1是父函数中定义的,子函数没有定义,向上找p1
}

}

DOM

  • DOM: document object model
  • Dom用于操作html文档,操作html标签内的内容
  • javaScript中将每一个标签当作对象处理
  • 在html中每一个标签都拥有自己的属性,比如style,id, class等,也拥有事件方法。在js中作为对象处理的标签也拥有属性事件方法
  • 操作DOM对象,一般使用document关键字

js获取元素的方法

  • document.getElementById(id);根据标签id获取元素节点,单一对象
  • document.getElementsByClassName(className);根据标签class值获取一组元素节点,一组对象
  • document.getElementsByName(name);根据name获取一组元素节点,一组对象
  • document.getElementsByTagName(tag);根据标签名获取一组元素节点,一组对象

js给html注册事件

注册事件的常用两种方式

  • 元素注册法
    html脚本和javascript脚本混合

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <input type="text" name="" id="text1" value="amao" onclick="clickMe()"> <!-- 注册 -->
    <input type="button" name="" id="" value="按钮" onclick="clickMe()"> <!-- 注册 -->
    </body>
    <script>
    function clickMe(){
    // alert();
    //获取标签对象
    var txt = document.getElementById("text1");
    //通过获取的标签对象获取属性value
    alert(txt.value);
    //event是鼠标点击事件,target是点击的对象, value是点击对象的属性value
    alert(event.target.value);
    }
    </script>
    </html>
  • 对象注册法
    html脚本和javascript脚本分离

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <input type="text" name="" id="txt1" value="阿毛">
    </body>
    <script>
    var change = function (){
    alert(event.target.value);
    }
    var changeClose = function (param){
    return function () {
    alert(event.target.value+param);
    };
    }
    //注册时委托函数不要加括号
    // document.getElementById("txt1").onchange = change("对象注册方法")
    document.getElementById("txt1").onchange = change //注册事件
    //想带参数怎么办: 1.闭包 2. bind
    var change1 = changeClose("对象注册方法:闭包")
    document.getElementById("txt1").onchange = change1 //注册事件
    </script>
    </html>

js动态操作html元素

  • document.createElement();创建元素

  • document.appendChild();添加子元素

  • document.insertBefore(newE1, orgE1);在某元素前添加元素

  • document.firstChild;获取第一个子元素

  • document.childNodes;获取所有子节点元素

    image-20231215165656934

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!-- childNodes把<li></li>前后的空格当成text Node(节点) -->
    <ul id="ulList">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    </ul>
    <ul id="ulList1"><li>1</li><li>2</li><li>3</li></ul>
    <script>
    var list = document.getElementById("ulList1");
    // console.log(list.childNodes);
    // console.log(list.firstChild);
    // console.log(list.lastChild);
    list.removeChild(list.childNodes[0]);
    list.removeChild(list.firstChild);
    list.removeChild(list.lastChild);
    </script>
  • document.removeChild(*);移除指定子节点元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="button" id="btnCreateNewTag" value="">
</body>
<script>
var oriTag = document.getElementById("btnCreateNewTag");
var click = function () {
var newTag = document.createElement("input");
document.body.appendChild(newTag);
document.body.insertBefore(newTag, oriTag);
}
document.getElementById("btnCreateNewTag").onclick = click;
</script>
</html>

js获取html元素内容

(innerHTML)

  • innerHTML用于获取与赋值,对拥有开闭标签的元素中完整的内容,包括开闭标签
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <div id="dv1">
    <span>Hello</span>
    <span>World</span>
    </div>
    <script>

    //获取内容
    var content = document.getElementById("dv1").innerHTML;
    console.log(content);
    function change(params){
    // 赋值内容,原本dv1标签内容被替换
    document.getElementById("dv1").innerHTML = "<b>Hello China!</b>";
    }

    var content1 = document.getElementById("div1").innerHTML;
    console.log(content1);
    </script>
    </body>
    </html>
  • innerText:只获取与赋值开闭标签内的文字内容,不包含开闭标签,innerText不识别标签会对输入的标签转义。

js操作css样式

  1. js操作style属性
    • style属性可以设置或返回样式
    • style设置css特征值时需要把特征的短横命名法改成驼峰命名法。例如:"font-size:12pt;"变为fontSize=“12pt”;
  2. js操作className属性
    • className属性可以设置或返回元素的class属性
  3. js操作多个元素的样式:直接对多个元素设置样式报错
    • 获取多个标签元素给一个变量
      1. getElementsByTagName
      2. getElementsById
      3. getElementsByClass
      4. querySelectAll
    • for循环遍历变量
    • 对子变量设置样式

BOM操作

  • BOM: Browser Object Model
  • BOM用于操作浏览器行为
  • 操作BOM对象,一般使用window关键字调用

常用方法

  • 下述BOM操作对象都是window的成员,注:document对象同样也是window的成员

  • alert():弹出提示对话框

  • confirm():弹出确认对话框,返回bool值类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <script>
    var bool = confirm("你确定要关闭浏览器吗");
    if (bool){
    alert("好吧,再见!");
    window.close();
    }else{
    alert("还可以继续和主人相处,太开心了!");
    }
    </script>
    </body>
    </html>

    image-20240105090625645
    image-20240105090653371

  • prompt():弹出用户输入对话框,返回输入的内容,如果取消则返回null

    1
    2
    3
    4
    5
    6
    7
    8
    <script>
    var s = "";
    alert(s);
    var ss = null;
    alert(ss);
    var text = prompt("你要输入什么");
    alert(text);
    </script>

    image-20240105092017648

  • setInterval(code, milliseconds): 计时器方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。

    • code:需要执行的代码
    • milliseconds:执行代码的周期
    • 方法会不停的调用函数,直到clearInterval() 被调用或窗口关闭。由setInterval()返回的计时器ID值可用作clearInterval()方法的参数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <body>
    <script>
    var i = 0;
    //调用不到34行的按钮因为按钮此时还没创建
    console.log(document.getElementById("btn"));
    var setInterbalId = setInterval(function(){
    console.log(++i);
    }, 1000);
    function clearTime(){
    //可以调用34行按钮因为调用此clearTime事件处理函数时该按钮已创建
    console.log(document.getElementById("btn"));
    clearInterval(setInterbalId);
    }
    </script>
    <input type="button" id="btn" value="停止计时" onclick="clearTime()">
    </body>

    image-20240105170701115

  • setTimeout(code, milliseconds):一次性的计时器,用于在指定的毫秒数后调用函数或计算表达式

    • code:需要执行的代码
    • milliseconds:执行代码的周期
    • clearTimeout()方法来阻止函数的执行。由setTimeout()返回的计时器ID值作为clearTimeout()方法的参数。
  • location:浏览器地址栏对象,下述为其属性成员

    • hash:返回一个url的锚部分
    • host:返回一个url的主机名和端口
    • hostname:返回一个url的主机名
    • $\star$href:返回完整的url
    • pathname:返回的url路径名
    • $\star$port:返回一个url服务器使用的端口号
    • protocol:返回一个url协议
    • search:返回一个url的查询部分
  • onload:页面加载完成后调用,所以可以把head中调用标签的js语句放到onload匿名函数中,这样等body中标签都定义了以后就可以获取了

1
2
3
4
5
6
7
8
9
10
<head>
<script>
window.onload = function(){
console.log(document.getElementById("btn"));
}
</script>
</head>
<body>
<input type="button" id="btn" value="去百度" onclick="goBaidu()">
</body>

数据库

学习内容:数据库基本知识,基本概念,数据库组成,数据类型,数据库操作,数据库管理

数据库基本概念

  • 什么是数据库:按照一定的数据结构组织、存储和管理数据的仓库。
  • 数据库管理系统:为管理数据库而设计的应用软件系统。
    • 类型:1. 关系数据库:建立在关系模型基础上的数据库:sqlserver, mysql, oaracle, access; 2.非关系数据库:不使用sql结构语言作为查询语言:mongo, redis。
  • 数据库系统:由数据库和数据库管理系统组成的系统。

创建数据库

  • 使用软件工具创建数据库,dbeaver, sqlserver
    • 服务器名称:
      1. 本地:local . 或 127.0.0.1
      2. 远程:ip加端口号
    • 身份验证:
      1. 登录名+密码
      2. 用户权限
        1.管理员方式:windows登录,可以给用户名赋权限
        2.用户名方式:无法给自己和别人赋权限
  • 脚本创建数据库
    1. mysql -uuser@ip -p
    2. CREATE DATABASE <database_name>;

数据库组成

创建完的数据库最终以文件和文件组形式存储在硬盘上

  • 文件形式(linux下没有这些文件)
    1. .mdf主要数据文件:存放数据和数据库的初始化信息,每个数据库有且只有一个主要数据文件。
    2. .ndf次要数据文件:存放除了主要数据文件意外的所有数据的文件。可以没有次要数据文件也可以有多个次要数据文件。
    3. .ldf事务日志文件:存放用于恢复数据库的所有日志信息。每个数据库至少要有一个日志文件
  • 文件组: 数据库文件的逻辑管理单位,他将数据库文件分成不同的文件组,方便对文件的分配和管理。
    1. 主文件组Primary: 包含主要数据文件和没有明确指派给其他文件组的文件。
    2. 用户自定义的文件组:在create database或alter database语句中使用filegroup关键字指定的文件组
  • 文件设计原则
    1. 文件只能是一个文件组的成员。
    2. 文件或文件组不能由一个以上的数据库使用。
    3. 数据和日志信息不能属于同一个文件或文件组。
    4. 日志文件不能作为文件组的一部分

数据库里的对象

  • 表:包含数据库中所有数据的对象,由行和列构成,用于组织和存储数据
  • 字段:表中的列,代表一种属性,例如:数据类型,大小(长度)
  • 视图:虚拟表,从一张或多张表中筛选出需要的内容组成一张表(导出的表),用户查看数据的一种方式,结构和数据是建立在对表的查询基础之上的。
  • 索引:为了给用户提供一种快速访问数据的途径,索引是依赖于表建立,快速定位查询无需遍历表。
  • 存储过程:一组为了完成特定功能的sql语句集合(可以有查询、插入、修改、删除等),编译后,以名称的形式存储到数据库中,之后执行该存储过程时直接用名称调用就会执行特定功能的sql语句集合。
  • 触发器:在数据库中用户自定义的sql事物命令集合,当对表执行增删改操作时,事物命令会自动触发而去执行。比如打印信息
  • 约束:对数据表中的列进行的一种限制(主键约束,数量限制等),更好规范表中的列。
  • 缺省值:对表中的列指定一个默认值。
    image-20240108154126107

数据类型

  • 数值型:
    1. 整型:bigint, int, smallint, tinyint
    2. 浮点型:float(n)近似数值, real即float(24), decimal(p,s)精确数值
  • 字符型:
    • char(n)(长度8000), varchar(n), text(长度2G)
    • unicode字符:nchar(n)(长度4000), nvarchar(n), ntext
  • 日期型:datetime(精度到3.33ms), datetime2(精度到100ns), smalldatetime(精确到1min), date,time(精度100ns), datetimeoffset, timestamp
  • 货币类型:smallmoney, money
  • 二进制类型:bit, binary(n), varbinary(n), image
  • 其他类型:sql variant, uniqueidentifier(全局标识符,不重复), xml, cursor(数据库指针引用), table

主键

主键的作用是唯一标识一条记录,不能为空也不能重复。标识列的值不是手动插入的而是自动生成的。数据类型必须是整型。一个表只能有一个主键。

  • 标识列
    1. 标识种子:开始值
    2. 增量:在上一条记录上增加量
      联合主键:多个列唯一标识一条记录

外键

外键:两个表之间建立关联时的列。在从表中一个列设为外键的条件是该列必须在另一个主表中作为主键。从表中可以有多个外键或者没有。

约束

约束就是给表中的数据一系列规则,如果数据存在违反规则的行为,则该行为就会被阻止。

  • 创建约束:可以在表创建前或者表创建后创建约束
  • 分类:
    • 主键 primary key
    • 外键 foreign key:连接两个表中的一列或多列。主表限制了从表的更新和插入,当删除主表中的数据时必须先删除从表中相关数据
    • unique约束:确保表中的一列数据没有相同的值,与主键不同的是,unique列可以有多个。
    • check约束:通过逻辑表达式来判断数据的有效性,用来限制输入一列或多列值得范围。
    • default约束:如果用户没有设定值,那么系统将默认值赋给该列,如果没有设置default约束则赋null。

数据库脚本

数据库脚本:用于创建数据库对象的语句集合。无需使用应用软件创建数据库对象。
sql: structured query language, 用于应用程序和数据库之间沟通的编程语言。
sql特点:

  1. 高级的非过程化的编程语言
  2. 可以写成脚本后然后执行
  3. 提高访问效率
  4. 可以交互式的处理数据
    sql基本语法:
  • 分号结尾
  • –代表注释
  • 大小写都可
  • \c取消输入
  • \p打印输入
  1. 查询:select from where ;
  2. 插入:insert into <column1,column2,…> values <value1, value2,…>;
  3. 更新:update set =, = where ;
  4. 删除:delete from where ;
  5. 定义、创建,修改,删除数据库对象:create/alter/drop database/table/view/proc/index ;
  6. 控制数据库、处理事物:
    • commit 提交
    • rollback 回滚
    • grant 授权
  7. 显示数据库:show databases;
  8. 使用数据库:use ;
  9. 显示表:show tables;
  10. 显示表的列:show columns from ;

终端创建表

image-20240109162611736

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--数据库对象定义DDL
--表1
create table productInfos(
id int identity(1001,1) primary key not null, --1001是标识种子,1是增量, linux为auto_increment
proNo varchar(50) not null,
proName nvarchar(50) not null,
typeId int not null,
price decimal(18,2) null,
proCount int null
);
--更新列
alter table productInfos change price price decimal(18,2) default 0.00 null; --设置默认值
alter table productInfos change proCount proCount int default 0 null;
--表2
create table productType(
typeId int auto_increment primary key not null,
typeName varchar(20) not null
);
--添加外键约束
alter table productInfos add constraint productInfos_typeId_FK foreign key(typeId) references productType(typeId);

终端修改表

1
2
3
4
5
6
--增加一列
alter table productInfos add proRemark varchar(20) null;
--删除一列
alter table productInfos drop column proRemark;
--修改列名
alter table productInfos rename column proCount to count;

终端建立约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
--主键约束
--方法一:建表时直接
create table st_info1(
st_id int(10) primary key,
name varchar(20),
class varchar(10),
gender varchar(4),
age int(2)
);
--方法二:建表时间接
create table st_info2(
st_id int(10),
name varchar(20),
class varchar(10),
gender varchar(4),
age int(2),
primary key(st_id)
);
--方法三:建表后修改
alter table st_info3 add primary key(st_id,name); --两个列设为主键
--删除主键
alter table st_info4 drop primary key;
--#####################################################################
--外键约束
--方法1:建表时间接
--CONSTRAINT <约束名> FOREIGN KEY <外键名>(字段名1,字段名2...) REFERENCES <主表名>(主键字段名)
create table tb_1(
course_id int(8) not null auto_increment,
course_name varchar(25) not null,
constraint course_Choosing foreign key fk_course(course_id) references st_info5(st_id)
) auto_increment=20015001;
--方法2: 建表后修改
alter table tb_1 add constraint course_Choosing foreign key fk_course(course_id) references st_info5(st_id);
--删除外键
--alter table <表名> drop foreign key <外键约束名>;
alter table tb_1 drop foreign key fk_course;
--#####################################################################
--unique约束
--方法1:建表时直接
create table book_info(
bk_id int primary key,
ISBN varchar(17) unique,
author varchar(50),
Publisher varchar(20)
);
--方法2:建表后
--alter table <数据表名> add constraint <唯一约束名> unique(<列名>);
alter table book_info add constraint uni_author unique(author);
--删除
--alter table <表名> drop index <唯一约束名>;
alter table book_info drop index uni_author;
--#####################################################################
--check约束
--方法1:建表时间接
create table persons(
id_p int not null,
lastname varchar(255) not null,
firstname varchar(255),
address varchar(255),
city varchar(255),
check (id_p>0)
);
--方法2:建表后修改
--alter table <表名> add constraint <检查约束名> check(<检查约束>)
alter table persons add constraint chk_ct check(city='上海');
--删除
--alter table <表名> drop constraint <检查约束名>;
alter table persons drop constraint chk_ct;
--#####################################################################
--默认值约束
--方法1:建表时直接
create table st_info(
st_id int(10) primary key,
name varchar(20) not null,
class varchar(10),
gender varchar(4),
age int(2) default 18
);

--方法2:建表后修改
--ALTER TABLE <数据表名>CHANGE COLUMN <旧字段名> <新字段名> <数据类型> DEFAULT <默认值>;

插入数据

  • 单条数据
    1. insert into (,) values (, );
    2. insert into (,) select <value2_1>, <value2_2> from ; 注设置的类型和<value2_1>必须是同一类型,是一一对应的
  • 批量操作
    1. insert into (,) values (, ), (<value1_1>, <value2_1>), (<value1_2>, <value2_2>);
    2. insert into (,) select <value2_1>, <value2_2> from union
      select <value3_1>, <value3_2> from ; 注:union用于连接会去重复记录,union all不会去重复
  • 克隆数据
    1. insert into () select <column2_1> from ;
    2. select <column2_1> into from ; 注<column2_1>是中的列插入到表中

数据更新和删除,主键不可以修改

  • update set =, = where
    :=, and, or, >, <, >=, <=
  • 删除
    1. 只删数据,表还在
      1. 条件删除,
        delete from where ; 标识列(主键)值是接着删除的最后一个值开始自增,不是从初始值开始, 可恢复
      2. 删除整个表的数据
        truncate table ; 表清空,恢复初始化,不可恢复
    2. 删除表
      drop ; 不可恢复

查询

  1. 所有列
    select * from where
  2. 部分列
    select , from where
  3. 表子段,中文名,给列命别名
    1. select as 别名 from
    2. select 别名 from
    3. select 别名= from

排序

select , from where order by asc|desc

模糊查询

select , from where like
匹配模式:

  1. %:0个或多个
  2. _:匹配单个字符
  3. []:范围匹配,括号中所有字符中的一个
  4. [^]:不在括号中的所有字符之内的单个字符
  5. 举例:‘%ad%’,‘%in’,‘on%’, ‘_ycch_n’,‘ad[m|n|d]in’,‘ad[mnd]in’, ‘ad[m-p]in’, ‘ad[^ab]in’

范围查询

  1. select from where ;
    : >, <, >=, <=, <>, and, or, in (,), not in (,)
  2. 前/后面多少条,百分比等
    • select top|bottom 10 from ;
    • select top|bottom 50 percent * from ;
  3. 子查询
    select from
    where in (
    select from where
    );
  4. between and
    select from where between and ;

聚合函数

聚合函数:对一个列或一个组执行计算并返回单一的值
五种聚合函数

  1. count: 统计表的记录数,空值为Null, 常与group by结合使用,分组语句
    select count() from ;
    select count() from ;
    select count(1) from ; 1是伪造列,比使用
    速度快
  2. sum: 求和
  3. avg: 求平均
  4. max: 求最大值
  5. min: 求最小值

分组查询

  • 使用分组和聚合函数时,select列表中只能包含出现在group子句中的列或者出现在聚合函数中
  • group语句和order语句必须放到where语句后
  1. select , from where group by , ;

  2. select , count(), from where group by , ;

  3. select , count(1) <别名> from

    group by

    having count(*) > 10 --针对分组后的组进行筛选

    order by <别名> asc|desc;

select语句处理顺序

  1. from
  2. on --关联条件
  3. join --连接
  4. where
  5. group by
  6. with cube 或 with rollup
  7. having
  8. select
  9. distinct
  10. order by
  11. top

连接查询

根据两个或多个表之间的列关系,从这些表中查询数据,目的多表查询

分类:内连接,左|右外连接,全连接,交叉连接,结果展现方式不同

  1. 内连接:inner join使用比较运算符:>=,<=,>,<,<>进行表间的比较,查询与条件相匹配的数据。结果是左右表相匹配的行
    • 显式内连接:
      select <column1_1>, <column1_2>, <column1_3>, <column1_4>
      from
      inner join on .<column1_2>=.<column2_3>;
    • 隐式内连接:
      select UserId, UserName, Age, u.DeptId, DeptName
      from UserInfos u, DeptInfos d
      where d.DeptId=u.DeptId and Age > 25;
  2. 外连接:
    1>. 左外连接left join on: 返回结果是左表中的所有行,右表匹配左表,右表中显示的行数和左表相同,没有匹配上的列显示空值Null
    select * from UserInfos u --左表
    left join DeptInfos d --右表
    on u.DeptId=d.DeptId
    2>. 右外连接
    右外连接left join on: 返回结果是右表中的所有行,左表匹配右表,左表中显示的行数和右表相同,没有匹配上的列显示空值Null
    select * from UserInfos u --左表
    right join DeptInfos d --右表
    on u.DeptId=d.DeptId
  3. 全连接full join:返回结果是左右表的所有行,左右表相互匹配,匹配不上的各自显示空值
    select * from UserInfos u --左表
    full join DeptInfos d --右表
    on u.DeptId=d.DeptId
  4. 交叉连接cross join:笛卡尔积,返回结果:不带where筛选时返回的行数是两个表行数的乘积,即左表中每一行连接右表中的所有行。注:不带on
    select * from UserInfos u --左表
    cross join DeptInfos d --右表
    where u.DeptId=d.DeptId

字符串函数

select upper();
select lower();
select len();
select ltrim(); --去左侧空格
select rtrim(); --去右侧空格
select left(, ); --左起若干字符
select right(, );
select substring(,,);
select replicate(, ); --重复若干次
select reverse();
select replace(,,);
select stuff(,,,);

数据库索引对象(相当于目录索引)

  1. 索引目的:数据查询、处理速度是系统成败的标准。索引就是一种优化查询速度的方式。
  2. 索引是什么:类似书的目录,快速找到标题页码,无需一页一页翻书找标题。
  3. 索引缺点:占用存储空间,合理建立索引。
  4. 分类:
    • 聚集索引clustered:存储的逻辑顺序和物理顺序是连续的
    • 非聚集索引:存储的逻辑顺序或物理顺序是非连续的

创建索引

  • create clustered index
    on ()
    with(
    drop_existing=on|off --on删除原有的,off不删除原有的并提示错误索引已存在
    )
  • create unique nonclustered index
    on ()
    with(
    pad_index=on, --填充
    fillfactor=50, --用于指定创建索引时,每个索引页的数据占索引页大小的百分比,例如读写比例100:1填充因子100,读小于写填充因子50~70,读写各一半填充因子80~90。索引页满后会分页增加系统开销。
    ignore_dup_key=on --避免重复键插入
    )
  • 多个字段创建复合索引
    create unique nonclustered index
    on (, )
    with(
    drop_existing=on
    )

视图对象(相当于虚表)

  • 视图是一个虚拟表,由一个或多个表通过查询而定义的,将查询定义保存起来,实际不包含数据。
  • 与表的区别:表存储数据,视图存储查询语句
  • 作用:简化查询,部分显示表的内容
  • 分类:
    1. 标准视图:存储查询定义,没有存储数据
    • 脚本创建视图
      create view
      as
      select <column1_1>, <column1_2>
      from <别名1>
      inner joint <别名2>
      on <别名1>.<column1_1>==<别名2>.<column2_1>
    • 创建完后使用视图
      select * from
      where >1
      order by desc
    1. 索引视图 (被具体化了的视图,创建了索引了,有实际数据,所以对该视图的增删改会影响原表)
      • 创建
        create view with schemabinding
        as
        select , from --select后不允许用*,且表名要加所有者
      • 使用
        select * from
      • 基于视图建索引
        create unique clustered index
        on ()
    2. 分区视图:一台或多台服务器间垂直连接成一组成员表的分区数据
    • 创建
      create view
      as
      select * from
      union all
      select * from
    • 使用
      select * from

存储过程对象(相当于函数)

  • 存储过程:为了完成特定功能的一个或一组sql语句集合。可加速sql语句的执行,调用存储过程名称,传入参数来执行。
  • 分类:
    1. 系统存储过程:在master数据库中,可以在其他数据库中直接调用master数据库而且不必在前面添加数据库名(因为没创建一个数据库,master的存储过程会自动添加进新的数据库中)。
    2. 用户自定义存储过程:用户自己创建,不是自动添加
    • 创建命令:
      create procedure
      @ ,
      @
      as
      begin
      <SQL语句>
      end
    • 修改命令
      alter procedure
      @ ,
      @
      as
      begin
      <SQL语句>
      declare @ ; --函数内声明变量
      set @ = ; --函数内赋值变量
      insert into (<column1_1>,<column1_2>) values (@, @);
      delete from where =;
      end
    • 删除命令
      drop procedure
    • 调用命令:execute|exec (, )
  • 优点:提高程序的通用性和可以执行,因为可以多次调用,不用重新编写。

C#访问数据库

windows

  • Ado.Net(ActiveX Data Object)可以连接到数据库的技术,并以各种方式来操作其中的数据,一个COM组件库,基于.Net体系架构。
  • 组成:
    1. Dataset: 非连接核心组件,独立于数据源的数据访问
    2. Data Provider:数据连接,执行命令,检索结果
  • 命名空间System.Data
  • 连接字符串:
    • sqlserver身份验证:Data Source 数据源; Initial Catalog 数据库名; User Id 账号; Password 密码;
    • windows身份验证:Data Source 数据源; Initial Catalog 数据库名; Integrated Security=True|SSPI; Trusted Connection=True;
  • 配置文件
    • C#的配置文件为app.config|web.conig
    • 在*.config中添加连接字符串节点,类似html文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <connectionStrings>
    <add name="MyConnectionString"
    providerName="MySql.Data.MySqlClient"
    connectionString="Server=your_mysql_server;Port=your_port_number;Database=your_database;Uid=your_username;Pwd=your_password;"/>
    </connectionStrings>
    <appSettings>
    <add key="MyConnectionString" value="Server=your_mysql_server;Port=your_port_number;Database=your_database;Uid=your_username;Pwd=your_password;"/>
    </appSettings>
    </configuration>
    • 使用节点,在其中添加一个 元素,包含连接字符串的名称MyConnectionString、提供访问数据库包的名称(例如 MySql.Data.MySqlClient)和实际连接字符串。
    • 也可使用节点,一般该节点用于应用程序配置。
    • 在c#中使用ConfigurationManager.ConnectionStrings读取配置文件中连接字符串名字。注意,为了使用 ConfigurationManager,你需要在项目中添加对 System.Configuration 程序集的引用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    using System;
    using System.Configuration;//
    using MySql.Data.MySqlClient;

    class Program
    {
    static void Main()
    {
    try
    {
    // 从配置文件中获取连接字符串
    string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;

    // 创建MySQL连接对象
    using (MySqlConnection connection = new MySqlConnection(connectionString))
    {
    // 打开连接
    connection.Open();
    Console.WriteLine("MySQL连接成功!");

    // 这里可以执行其他数据库操作

    // 关闭连接
    connection.Close();
    }
    }
    catch (Exception ex)
    {
    Console.WriteLine($"连接到MySQL时发生错误:{ex.Message}");
    }
    }
    }

macos

流程

  1. dotnet new console -n mysqlTest

  2. donet build 在当前目录下编译 | donet build <工作目录> 在工作目录下编译 | dotnet build <*.csproj> 编译该文件

  3. // Program.cs文件
    // See https://aka.ms/new-console-template for more information
     using System;
     using MySql.Data.MySqlClient;
     class Program
     {
         static void Main()
         {
             string connectionString = "Server=127.0.0.1;Database=studentDB;User ID=root;Password=liuchuanxi;";
             //"server=127.0.0.1;port=3306;database=studentDB;uid=root;pwd=liuchuanxi;";
             using (MySqlConnection connection = new MySqlConnection(connectionString)) //using()自动释放资源
             {
                 connection.Open();
    
                 // 在这里执行与数据库的交互操作
                 // 例如,可以执行查询、插入、更新等操作
                 // Executing a command
                 using (MySqlCommand command = new MySqlCommand("SELECT * FROM your_table", connection))
                 {
                     using (MySqlDataReader reader = command.ExecuteReader())
                     {
                         while (reader.Read())
                         {
                             // Access data using reader.GetString(), reader.GetInt32(), etc.
                         }
                     }
                 }
                 // Using DataSet and DataAdapter
                 DataSet dataSet = new DataSet();
    
                 using (MySqlDataAdapter adapter = new MySqlDataAdapter("SELECT * FROM your_table", connection))
                 {
                     adapter.Fill(dataSet, "YourTable");
                 }
    
                 // Now, dataSet.Tables["YourTable"] contains the retrieved data.
    
                 connection.Close();
             }
    
             Console.WriteLine("Hello, World!");
         }
    
     }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    4. donet run 自动找.dll文件运行 | dotnet run /Users/liuchuanxi/c#_test/lesson2/mysqlTest/bin/Debug/net7.0/mysqlTest.dll

    * MySqlConnection:连接对象
    * MySqlCommand:命令对象
    * MySqlDataReader:从数据源中提供快速、只读的数据流,用于数据检索
    * DataSet: 独立于数据源的数据访问
    * MySqlDataAdapter:提供DataSet对象与数据源的桥梁,用于不连接数据库时的DataSet对象与数据源之间进行交互
    * 数据库访问步骤:
    1. 连接数据库
    * 方法1:
    ```c#
    MySqlConnection conn = new MySqlConnection();
    conn.ConnectionString = "Server=127.0.0.1;Database=studentDB;User ID=root;Password=liuchuanxi;"; //连接字符串,相当于一把钥匙//"server=127.0.0.1;database=studentDB;uid=root;pwd=liuchuanxi;";
    * 方法2:
    1
    2
    string connectionString = "Server=127.0.0.1;Database=studentDB;User ID=root;Password=liuchuanxi;";//"server=127.0.0.1;database=studentDB;uid=root;pwd=liuchuanxi;";
    MySqlConnection connection = new MySqlConnection(connectionString)
    * 方法3:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    MySqlConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder();
    connectionStringBuilder.Server = "127.0.0.1";
    connectionStringBuilder.Database = "studentDB"
    connectionStringBuilder.UserID = "root"
    connectionStringBuilder.Password = "liuchuanxi"
    // 获取连接字符串
    string connectionString = connectionStringBuilder.ConnectionString;
    // 创建MySQL连接对象
    MySqlConnection connection = new MySqlConnection(connectionString)
    * 常用属性:
    1
    2
    3
    4
    5
    6
    MySqlConnection conn = new MySqlConnection();
    //访问属性时只能获取不能赋值
    //conn.DataBase "数据库名";
    //conn.DataSource "服务器IP,端口号";
    //conn.State 连接状态:Closed, Open, Connecting, executing正在执行命令, Fetching正在检索数据, Broken连接中断;
    //conn.ConnectionTimeout 等待连接时间默认15秒;
    * 连接字符串:一组被格式化了的键值对每个键值对之间用分号;连接,描述数据源在哪里,数据库名是什么,提供什么样的访问信任级别等其他信息 * 修改连接字符串后需要重新编译,所以灵活性差,使用将连接字符串放到配置文件中可以解决此问题。 1. 创建appsettings.json文件,放到项目根目录下
    1
    2
    3
    4
    5
    {
    "ConnectionStrings": {
    "MyConnectionString": "Server=your_mysql_server;Port=your_port_number;Database=your_database;Uid=your_username;Pwd=your_password;"
    }
    }
    2. 项目添加配置包
    1
    2
    dotnet add package Microsoft.Extensions.Configuration
    dotnet add package Microsoft.Extensions.Configuration.Json
    3. C\#读取配置文件,代码会在你的项目根目录下或者项目的.dll文件所在目录下查找 `appsettings.json` 文件,并读取其中的连接字符串。注:如果读不出给出文件的绝对路径。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    using System;
    using Microsoft.Extensions.Configuration;

    class Program
    {
    static void Main()
    {
    try
    {
    // 创建配置构建器
    IConfigurationBuilder builder = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

    // 构建配置
    IConfigurationRoot configuration = builder.Build();

    // 获取连接字符串
    string connectionString = configuration.GetConnectionString("MyConnectionString");

    // 连接到数据库或执行其他操作
    Console.WriteLine($"Connection String: {connectionString}");
    }
    catch (Exception ex)
    {
    Console.WriteLine($"Error: {ex.Message}");
    }
    }
    }

  4. 打开连接
    * conn.Open()

  5. 创建执行命令对象
    * 方法1:MySqlCommand command = new MySqlCommand(“SELECT * FROM your_table”, conn)
    * 方法2:conn.CreateCommand()

  6. 执行命令

  7. 关闭连接
    * conn.Close();关闭连接
    * conn.Dispose();释放连接
    * 两种方法差别:Close()后还可以访问属性,可以继续Open(),Dispose()后无法再访问属性, 也无法Open()