深感从前学过的数据库知识忘的一干二净,遂写下这篇博客用以温故知新,这篇数据库知识笔记以mysql为基准
-
sql查询中,可能会得到重复的数据,如果这个时候你想要消除重复的话,可以加上distinct
select distinct name from Stus
-
sql查询中,order by 关键字可以用于排序(默认是升序),如果要使用降序的话,可以加上desc关键字
select * from Stus order by age (desc), (按age排序后的第二排序基准)
-
update更新列语句
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
-
top语句,选取查询出来结果列表的前n项,top在不同的数据库中使用方式是不一样的,以mysql为例子
select * from Stus limit 2
-
like语句,sql查询中的模糊搜索,和通配符一起使用,not like是like的逆操作
通配符 描述 % 替代一个或多个字符 _ 仅替代一个字符 [charlist] 字符列中的任何单一字符 [!charlist] 不在字符列中的任何单一字符 - like ‘n%’ = 以n开头
- like ‘%n’ = 以n结尾
- like ‘%n%’ = 包含n
- like ‘_n’ = 第一个字符后面是n
- like ‘[abc]%’ 以a或b或者c开头
- like ‘[^abc]%’ 不以a,b和c开头
-
in语句允许我们在 WHERE 子句中规定多个值
SELECT column_name(s) FROM table_name WHERE column_name IN (value1,value2,...)
-
join操作符,用于在两个表中选取相关的数据(分为左链接,内链接,外链接和全链接)
SELECT Persons.LastName, Persons.FirstName,Orders.OrderNo FROM Persons (LEFT JOIN/RIGHT JOIN/INNER JOIN/FULL JOIN) Orders ON Persons.Id_P=Orders.Id_P ORDER BY Persons.LastName
-
union操作符,用于合并两个或多个 SELECT 语句的结果集,请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同
SELECT column_name(s) FROM table_name1 UNION/UNION ALL(union默认会去重,加上all会取出所有的数据) SELECT column_name(s) FROM table_name2
-
select into语句,用于将选取的表或列插入另外一个表格
SELECT * INTO Persons_backup FROM Persons
-
foreign key(用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一)
create table `stus` ( .... PRIMARY KEY (`stu_id`), FOREIGN KEY (`person_id`) references persons (`person_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
check语句,同样,对列表的数值进行一些限制,比如 id > 0
create table `stus` ( ... CHECK (`id` > 0) );
-
auto-increment语句,用于在新纪录插入的时候,自动生成一个唯一的数值,其实在create table的时候,可以设置一个id字段作为primary key,同时将id字段设置为 AUTO-INCREMENT,这样就很省心了,另外AUTO-INCREMENT默认是从1开始计数的,然后依次 + 1,如果想要指定从某个数值开始的话,可以在create table的时候设置AUTO-INCREMENT
CREATE TABLE `stus` ( ... ) ENGINE=InnoDB AUTO-INCREMENT=100 DEFAULT CHAREST=utf8; 还可以通过`alter table stus AUTO_INCREMENT=100`
-
如果表格中的某个列是可选的,那么,当其没有被赋值的时候将以null值保存,null的处理方式和其他值不同,只能用is NULL 或者 not is NULL来过滤,由于mysql中经常对列进行一些计算,如果其中一个参数为null的话,会影响计算出来的结果,mysql提供IFNULL()函数用于处理这种情况
SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0)) FROM Products
-
mysql中的数据类型
-
mysql number类型默认是有符号数的,举个栗子,tinyint是从-128到127的,但是如果create table的时候加上了unsigned标识,那就是从0开始到255,smallint,bigint都是这样
-
mysql中timestamp类型,可以用于记录操作数据库的时间,灰常方便,配置如下
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-
sql函数(最好用as进行重命名)
- AVG() 返回数值列的平均值
SELECT AVG(OrderPrice) AS OrderAverage from Orders
- COUNT() 函数返回匹配指定条件的行数(不返回NULL的行)
SELECT COUNT(*) AS OrderCount from Orders
- FIRST() 函数返回指定的字段中第一个记录的值
SELECT FIRST(OrderPrice) AS FirstOrderPrice FROM Orders
- LAST() 函数返回指定的字段中最后一个记录的值
SELECT LAST(OrderPrice) AS LastOrderPrice FROM Orders
- MAX() 函数返回一列中的最大值。NULL 值不包括在计算中
SELECT MAX(OrderPrice) AS LargestOrderPrice FROM Orders
- MIN() 函数返回一列中的最小值。NULL 值不包括在计算中
SELECT MIN(OrderPrice) AS SmallestOrderPrice FROM Orders
- SUM() 函数返回数值列的总数(总额)
SELECT SUM(OrderPrice) AS OrderTotal FROM Orders
- GROUP BY 用于结合合计函数,根据一个或多个列对结果集进行分组
SELECT Customer,SUM(OrderPrice) FROM Orders GROUP BY Customer
- HAVING 由于where无法与合计函数一起使用,于是要对分组的合计函数的数值进行过滤的时候,就需要使用HAVING了
SELECT Customer,SUM(OrderPrice) FROM Orders GROUP BY Customer HAVING SUM(OrderPrice)<2000
- UCASE() 函数返回大写形式
SELECT UCASE(LastName) as LastName,FirstName FROM Persons
- LCASR() 函数返回小写形式
SELECT LCASE(LastName) as LastName,FirstName FROM Persons
- MID() 函数返回字段的子串
SELECT MID(column_name,start[,length]) FROM table_name
start必填,需要注意的是,起始索引不是0而是1 - LEN() 函数返回文本中字段数值的长度
SELECT LEN(City) as LengthOfCity FROM Persons
- ROUND() 函数用于把数值字段舍入为指定的小数位数
SELECT ProductName, ROUND(UnitPrice,0) as UnitPrice FROM Products
- AVG() 返回数值列的平均值
-
sql索引
- 普通索引,(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHEREcolumn=)或排序条件(ORDERBYcolumn)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引
- 唯一索引,普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个“员工个人资料”数据表里可能出现两次或更多次。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。这么做的好处:一是简化了MySQL对这个索引的管理工作,这个索引也因此而变得更有效率;二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;如果是,MySQL将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复
- 主索引,在前面已经反复多次强调过:必须为主键字段创建一个索引,这个索引就是所谓的“主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE
- 外键索引,如果为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件
-
mysql选取优化的数据类型
- 更小的通常更好,一般情况下,应该尽量使用可以正确存储数据的最小数据类型。更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期也更少,举个栗子,用0,1来区分两种状态,用tinyint类型就能达到目的,这个时候使用int类型就不好。
- 简单就好,简单数据类型的操作通常需要更少的CPU周期。例如,整型比字符操作代价更低,因为字符集和校对规则(排序规则)使字符比较比整型比较更复杂。
- 尽量避免NULL,很多表都包含可为NULL(空值)的列,即使应用程序并不需要保存NULL也是如此,这是因为可为NULL是列的默认属性。通常情况下最好指定列为NOT NULL,除非真的需要存储NULL值。
-
mysql的三大数据类型
- 数字,数字分为整数(whole number)和实数(real number)。整数分为TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别使用8、16、24、32、64bit存储空间,它们可以存储的数值范围从-2^(N - 1)到2^(N - 1) - 1,其中N为存储空间的位数,可以选择UNSIGNED修饰,表示不允许负值,这样可以使得存储的数值范围从0 ~ 2^(N - 1) - 1。定义的时候TINYINT(4)这样写其实对数据库创建没有区别,因为类型需要的空间是固定的,4只是说明可视化数据库管理软件显示的位数。 实数分为FLOAT(32bit)和DOUBLE(64bit),但是float和double不精确,需要存储比BIGINT大的整型数据或者精确的浮点数,可以使用DECIMAL,但是DECIMAL需要的字节数很大,所以在真正需要的时候再使用吧~
- 字符串,CHAR(定长)和VARCHAR(变长),在数据量小或者固定的时候使用CHAR
- 时间,DATETIME和TIMESTAMP,DATETIME这个类型能保存大范围的数值,从1001年到9999年,精度为秒。它把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,与时区无关。使用8个字节的存储空间;TIMESTAMP只使用4个字节的存储空间,只能表示1970年到2038年,除了特殊行为之外,尽量使用TIMESTAMP,它比DATETIME空间效率更高。
-
mysql出现错误”Every derived table must have its own alias”
这句话的意思是说每个派生出来的表都必须有一个自己的别名
一般在多表查询的时,会出现错误。
因为,进行嵌套查询的时候子查询出来的结果是作为一个派生表来进行上一级的查询的,所以子查询的结果必须要有一个别名,把Mysql语句改成:select count(*) from (select * from ….) as total,total这个别名是必须的,下面来看一个实际的例子
写一个SQL query从
Employee
表中得到第二高的薪水SELECT max(p.Salary) AS SecondHighestSalary FROM ( SELECT * FROM Employee WHERE Salary != ( SELECT max(Salary) FROM Employee ) ) AS p;