数据库与SQL

本文内容主要来自Sololearn的SQL课程以及课程的评论区
自动生成数据可使用GenerateData

主要内容:

本文所涉及的内容及顺序:

  1. 数据库和SQL都是什么?
  2. 数据库查询。
  3. 数据操作。怎么修改一个表中的数据,即插入数据、更新数据、删除数据
  4. 表结构的操作。表的创建、修改与删除,列的增加、删除、和修改。

概念

数据库

数据库是一个便于访问的数据组织形式,同时可以高效管理和升级。以的形式存储相关信息。
数据表以行和列的结构来存储和显示数据,看起来就行Excel那样。数据库一般包含多张表,每张表根据要存储的数据不同,包含它自己的字段集合。

SQL

Structured Query Language 结构化查询语言,方便访问和操作数据库。 SQL是一个ANSI标准。就是说说SQL只是一个语言标准,但不是语言。它在不同的数据库引擎上,有不同的实现版本。每个都在主要命令的基础上有自己的扩展。本文使用MySQL引擎。

SQL常用于:

  1. 插入、更新、删除数据。
  2. 创建新的数据库、表、存储过程、视图。
  3. 从数据库取回数据。

注意:

  1. 关于大小写:
    1. SQL语句大小写不敏感。在SQL语句中:大小写无关执行效率,Oracle推荐大写,具体看个人,保持统一的写法就好,不仅方便阅读理解,也会减少不必要的缓存。事实上,即使是小写,经过词法分析后也会自动转换为大写,只是可能会增加一丁点的编译时间。
    2. 数据库内部表名列名,一些人说的是大小写敏感的,可能在一些引擎确实如此。但在MySQL(我使用的是5.7.20)所有的表名、列名都会被转换为小写,不管是创建还是查询。所以你无法同时添加Name和name两个字段,查询NAme和name也没有区别。所以这样看,至少可以说MySQL 5.7.20(截至2017.10.30日,最新的稳定版本)是完全大小写不敏感的。
  2. 词之间的空格和空行会自动被忽略,所以分成多行写SQL会使语句比较清晰,在一些数据库中如果使用tab缩进的话需要在后面加上空格,不然会被识别为一个词。
  3. 每个完整的语句都由一个';'结尾,切记。
  4. 值为文本时,需要将值用单引号包裹起来。不能用双引号。
  5. 关于存储过程,课程里没有提及。查了一下,我大致说一下。首先数据库指令是先编译后执行的,这也是为什么上边说大小写不敏感。就像在写程序的时候我们会把一些代码提取成一个方法(为了复用、稳定性等),存储过程也就像一个方法块或者说脚本,只不过他是编译过的,不需要再次编译,可以直接拿来执行一些操作。我们不需要每次都去写一些重复的SQL语句。

先从用的最多的查开始。事实上,当一个人进入一家公司,需要接触已有的数据库时,这也是需要最先掌握的。

这一部分有这些内容:

  1. USE语句
  2. SHOW语句
  3. SELECT语句
  4. 多个查询
  5. DISTINCT标识
  6. LIMIT语句
  7. ORDER BY语句
  8. 自定义数据列
  9. 子查询
  10. 多表操作,JOIN、UNION

USE语句

选择当前要使用的数据库。之后可以在该数据库执行增加表、修改表等操作。

Tips:

  1. 选完数据库后,在操作表时可以直接使用表名,类似文件中的相对路径。
  2. 如果想要选择到别的数据库中的表,也可以使用全称表名(databaseName.tableName),数据库名和表名之间用','隔开。就像我们说文件中的绝对路径。即使你选择了数据库B,也可以使用这种方式选择到数据库A中的某张表。

SHOW语句

显示数据库或表中的信息,帮助你跟踪了解数据库的内容,提醒你表的结构。

  1. SHOW DATABASES; 显示所有的数据库。
  2. SHOW TABLES;显示某个数据库中的所有表。需要先使用USE databaseName 选择到特定数据库。
  3. SHOW COLUMNS FROM tableName;显示某个表中的所有列信息。DESCDESCRIBE直接加表名有同样效果。(MySQL 5.7.20)。显示的信息如下(注意空和NULL的区别,NULL是应该有值但是现在还没有,空这是没有那个属性。):
    1. Field,列名
    2. Type,列的数据类型,数字字符等。比如char(1),int(11)等。
    3. Null,指示列是否可以为空。对应NOT NULL。比如:NO,YES。
    4. Key,指示列是否被索引。目前发现:设置了主键的为PRI,其他为空。
    5. Default,列的默认值。比如NULL。
    6. Extra,可能包含给定列的所有附加信息,比如自增长。也可能为空。

SELECT语句

用于从一个数据库选择数据,结果会被存储在一个结果表(result table)中,被称为result-set
一次查询可能会从一列或多列中取回数据。

SELECT column_lists FROM table_name

column_lists包含会被返回的列;table_name指示从哪个表获取数据。

多个查询

可以同时执行多个查询。

SELECT column1 FROM table1;
SELECT column2 FROM table1;

这种写法会返回两个结果集。
也可以一次选择多列,用,隔开。需要选择所有可以用*(all)替换列名。

SELECT column1,column2 FROM table1;

这种写法会把之前那种方式的两个结果集整合为一个结果集。

DISTINCT标识

SELECT DISTINCT age FROM students;

去掉重复的结果。

LIMIT语句

限制返回的数据条目,要放在语句最后。

SELECT * FROM table1 LIMIT 3,5;

上边的句子中,LIMIT 3,5,代表把第三行看作第0行(第0行不是实际的行,而是一个作为起始点的假定行),并开始显示第4行,一共显示5行。

Tips:

  1. LIMIT 100相当于LIMIT 0,100;
  2. 平常的查询中,不做特殊声明的情况下,一般会有一个默认的Limit。可以发现不写limit其实会被执行为... LIMIT 0,1000。也就是默认返回前1000条数据。

ORDER BY语句

配合SELECT 对返回的数据依据某个字段进行排序。默认升序排列(ASC),也可以在列名(字段)后面加上DESC,降序排列。

ORDER BY Age

也可以指定多个排序列名,用,分开。当第一个字段有重复的时候,会根据第二个字段对重复的进行排序...
因为升序降序是对列名起作用的。所以你可以这样写:

ORDER BY age, weight DESC
//意思是:先按照age 升序排列,再安装weight 降序排列。

WHERE语句

过滤结果集,用来提取符合条件的记录。

SELECT column_lists
FROM table_name
WHERE condition;
表达式的构建

比较操作符,用于构建基础的表达式。

操作符 意义
= 相等
!= 不等, 在ANSI中的标准写法是<>
> 大于
< 小于
<=/>= 小于等于/大于等于
BETWEEN 在一个范围之内,需要配合and使用,前面的需要比后面的小。 有的引擎会排除第一个和最后一个,所以如果不确定的话,结合使用>=和<=会更加稳定。

连词操作符,连接不同的基础表达式,构建一个复合表达式。

操作符 意义
AND 与,两边都为TRUE时,结果为TRUE
OR 或,两边有一个为TRUE时,结果即为TRUE
IN 操作与一组表达式中的一个相等,结果即为TRUE
NOT 如果表达式不为TRUE,则结果为TRUE

注意:IN,需要用 '()' 将内容包裹起来,可以看作多个OR的简化写法。比如选出家在A,B,C的学生

SELECT *
FROM students
WHERE address IN ('A','B','C');

同理,NOT IN 为排除。需要注意,请确保你不需要隐藏NULL值,比如上边的情况,如果address为NULL的使用NOT IN也会被添加到结果集中。

Like表达式

LIKE用于特征匹配。
_匹配单个字符,%匹配任意数量个字符。
比如:

SELECT name, cost
FROM items
WHERE name LIKE  '%boxes of frogs' AND seller_id IN  (68, 6, 18);
自定义数据列

对返回的数据进行一些处理

CONCAT

SELECT CONCAT("id为",id,"的同学,名字是:",name)
FROM students;

将students里的每个学生信息以 id为1的同学,名字是:张二狗 这样的格式返回,如下图,注意表头。注意这里面的自定义文字不是数据值,需要使用双引号。

使用CONCAT

AS ALIASING,别名。
可以用于将返回的结果的列起一个别名。比如重新写上边的那个语句,注意表头。

SELECT concat("id为",id,"的同学,名字是:",name) AS Detail
FROM students;
使用AS
数字运算符,+-*/

就是可以对返回的数据做一些处理, 只影响返回的数据,不影响数据库里的数据。

SELECT ID, FirstName, LastName, Salary+500 AS Salary
FROM employees;
方法
  • UPPER/LOWER对返回的数据进行大小写转换处理。
  • SQRT,求平方根
  • AVG,求平均
  • SUM,求和。
  • MIN,查找最小值

子查询/嵌套查询

比如查出平均后,再查出高于平均的数据。

SELECT FirstName, Salary FROM employees
WHERE  Salary > (SELECT AVG(Salary) FROM employees)
ORDER BY Salary DESC;

多表操作

之前的所有查询都是一次针对一张表进行的。而SQL最大的好处之一是多表查询。
多表查询,在遇到比较长的表名时,对表名使用别名会更加方便。 这种情况下AS可以省略

SELECT ct.ID, ct.Name, ord.Name, ord.Amount
FROM customers AS ct, orders ord
WHERE ct.ID=ord.Customer_ID
ORDER BY ct.ID;
JOIN

joining tables意思是连接多个表的数据,Join创建了一个临时的表用于展示被连结的数据。 在JOIN中的条件需要使用ON关键字。

Join的类型(注意在使用时,OUTER是可以省略的):

  • INNER JOIN,相当于JOIN,返回各个表中匹配的部分。

  • LEFT OUTER JOIN,即使右侧的表中没有匹配的数据,也会显示左侧表中所有条目。比如要统计学生选了什么课,有些学生即使没有选课也会被显示出来(选课表中没有该学生选课的信息,显示在查询结果里会是某某某选课为NULL)。

  • RIGHT OUTER JOIN,同理,即使左侧表中没有匹配的数据,也会显示右侧表中所有条目。

比如我们查出所有同学的成绩:

SELECT stu.name,scores.score
FROM students stu LEFT JOIN scores
ON stu.name=scores.stu_name;
UNION数据整合

UNION也是针对多表,JOIN一般用于查询数据的关联部分,比如通过一家医院的病人信息表和药品销售表,查出哪些病人买了什么药。而UNION一般用于整合数据,比如查出市里所有医院的病人信息,需要整合各个医院的病人信息表。使用UNION,或许需要把多个表的数据连结到一个综合数据表里,有时候需要跨数据库,甚至跨服务器。

UNION的类型:

  • UNION 连结多个数据集到一个单独的数据集,并且移除重复的。
  • UNION ALL 类似UNION,但不移除重复的。所以它要比UNION 快一点。

连结多个SELECT语句的数据集,使用:

SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;

需要使用UNION合并的查询结果集必须具有相同的列、列名、数据格式、以及一致的列顺序。如果你需要一种信息,但在另外的数据库里没有该信息,你可以在加一个NULL列来匹配查询。比如下边的:

SELECT FirstName, LastName, Company FROM businessContacts
UNION
SELECT FirstName, LastName, NULL FROM otherContacts;

数据的增删改

这一部分有这些内容:

  • 往表里插入数据

  • 更新表中的数据

  • 删除表中的数据

插入数据

INSERT INTO tableName(columnsName)
VALUES(a,b,'c',12);

关于columnsName:

  • 可以不指定,则按照列的顺序来,需要确保和列的顺序、数据类型都一致。
  • 按照一定的顺序指定某几个列,则后面添加数据时也要按照指定的顺序。如果未给表中某列分配数据,请确保它有默认值或可以为NULL

列名和值都用' , '隔开。

支持多行同时插入:

INSERT INTO customer (ID, FirstName, LastName, Age)
VALUES
(1, `Emily`, `Adam`, 34),
(2, `Chloe`, `Anderson`, 27),
(3, `Daniel`, 'Harris`, 30),
(4, ` James`, `Robert`, 31),
(5, `John`, `Smith`, 35),
(6, `Andrew`, `Thomas`, 45),
(7, `David`, `Williams`, 23),
(8, `Anthony`, `Young`, 35);

Tips:使用时可能会发现有VALUES和VALUE,它们效果一样,没有区别,都是合法的。

更新数据

UPDATE table_name
SET column1=value1, column2=value2, ...
WHERE condition;

注意:

  • 如果不跟WHERE则所有的数据都会被修改。
  • 默认是安全模式,而在安全模式下,必须有WHERE,且条件必须是主键。
  • 在SET里,可以不按顺序来。

插入或更新数据

把 INSERT 换为 REPLACE,其他和插入的语法一样。比较好用。

REPLACE INTO tableName(columnsName)
VALUES(a,b,'c',12);

删除数据

DELETE FROM table_name
WHERE condition;

限制类似Update;
Tips:该操作是永久的,所以在执行DELETE之前,先将DELETE替换为SELECT * ,看看你会删除什么数据。确定可以删除再执行DELETE。


涉及表结构的增删改

这一部分有这些内容:

  • 表的创建、删除和重命名。
  • 列的增加、删除、修改。

支持的数据类型:

  • 数字
    • INT,正常大小的数字。可以被标记为有符号或没符号。
    • FLOAT(M,D),单精度浮点数,不能被标记。可以定义显示长度M和小数位数D
    • DOUBLE(M,D),双精度浮点数,其他同上。
  • 时间和日期
    • DATE - YYYY-MM-DD 格式
    • DATETIME - YYYY-MM-DD HH:MM:SS格式
    • TIMESTAMP - Linux时间戳,从1970年1月1日午夜开始计算。
    • TIME - HH:MM:SS时间格式
  • 字符类型
    • CHAR(M),固定长度字符串。M为指定的长度,最大255bytes.
    • VARCHAR(M), Variable-length character string 可变长度字符串,括号指定最大值。
    • BLOB,二进制对象,一般用于存储大量的二进制数据。比如图片其他文件等。
    • TEXT,大量的文字。

一个数据库里可以存放多个表,每个都扮演着自己独特的角色。
表由行和列组成,每列负责存储不同的数据类型,包括数字、文字、数据,甚至是文件。

约束语句

作用与表中数据的需要遵守的规则,在表创建时,可以在某列的数据类型后面指定约束。

  • PRIMARY KEY : 强制表中某列只接受独特的值,不能为空。并且为之创建索引可用于快速访问。是表中数据的独特标识,每张表只允许有一个主键。
  • NOT NULL:指示该列不能包含任何NULL值
  • UNIQUE:该列不能插入重复的值。
  • CHECK : 通过一个逻辑表达式决定值是否有效。 EmployeeId int Not Null Check (EmployeeId > 0),如果数据中该值大于0则拒绝插入该数据。
  • DEFAULT:插入数据时,如果没有向该列提供值,则该列从DEFAULT获取值。
  • AUTO INCREMENT:自增长允许我们在插入数据的时候自动生成一个独特的数字。通常我们都将其用于主键。默认情况下,它从1开始,每次增加1。注意:数据库不一样实现方式可能也不一样,比如MS SQL中使用的是 IDENTITY标识。

创建表

CREATE TABLE语句用于创建一个新表。创建表意味着三件事

  • 命名新表。
  • 确定有哪些字段(列)。
  • 确定每列的数据类型和大小。

比如下边的建表语句(注意该语句对表是否存在做了判断,并且单独设置了主键,其实也可以像其他的约束一样,写在某列的数据类型后面):

CREATE TABLE IF NOT EXISTS table_name
(
column_name1 data_type(size) NOT NULL AUTO_INCREMENT,
column_name2 data_type(size),
column_name3 data_type(size),
....
columnN data_type(size),
PRIMARY KEY(column_name1)
);

删除表

DROP TABLE tableName;

重命名表

RENAME TABLE People TO Users

ALTER TABLE/列的修改
用于表中列的增删改(ADD、DROP、CHANGE,CHANGE包含了重命名、增加和删除约束。名字不变时,即修改了列定义)。

ALTER TABLE tableName
ADD newColumn date NOT NULL;

ALTER TABLE tableName
DROP COLUMN columnName;

ALTER TABLE tableName
CHANGE columnName newName datatype(size) NULL;

Tips: 在MySQL中,如果新添加的列指定了NOT NULL,会为已经有的数据添加列的数据类型的默认值。比如列的数据为date,不指定NOT NULL则该列为null,否则值为0000-00-00。


VIEW

VIEW是一个基于结果集的虚拟的表。就像一个真实的表一样,它也有行和列,它里面的数据都来自一个或多个真实的表。

我们可以使用View:

  • 结构化数据,以使各种用户可以直观自然的查找数据。
  • 限制数据访问,使用户可以只接触和操作到他们可以需要的数据。
  • 汇总各个表格的数据,生成报表。

创建

CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition;

之后可以通过SELECT语法去访问该view。

注意:

  • View的名称不能和表相同。
  • View的数据都是最新的,每次你去查询一个view的时候,数据库引擎都会使用view的SQL语句去重新创建它的数据。
  • View并非只读的,在一些情况下,你也可以通过它对基础表的数据进行插入、删除操作(MySQL - Updatable and Insertable Views)。比如我建了一个View,使用的是SELECT * ,也就是说我的View和基础表是完全对应的。之后我做了插入数据的操作,执行更新,发现View的数据包含了我插入的数据,去查询表,发现数据确实已经更新。

修改View

CREATE OR REPLACE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition;

删除View

DROP VIEW viewName;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容