SQL基础语法
一、SELECT 查询
1.SELECT 查询某些属性列(specific columns)的语法
SELECT column(列名), another_column, …
FROM mytable(表名);
SELECT查询所有列
SELECT *
FROM mytable(表名);
2.条件查询 (constraints)
条件查询语法
SELECT column, another_column, …
FROM mytable
WHERE condition
AND/OR another_condition
AND/OR …;
注:这里的 condition 都是描述属性列的,具体会在下面的表格体现。
Operator(关键字) | Condition(意思) | SQL Example(例子) |
---|---|---|
=, !=, < <=, >, >= | Standard numerical operators 基础的 大于,等于等比较 | col_name != 4 |
BETWEEN … AND … | Number is within range of two values (inclusive) 在两个数之间 | col_name BETWEEN 1.5 AND 10.5 |
NOT BETWEEN … AND … | Number is not within range of two values (inclusive) 不在两个数之间 | col_name NOT BETWEEN 1 AND 10 |
IN (…) | Number exists in a list 在一个列表 | col_name IN (2, 4, 6) |
NOT IN (…) | Number does not exist in a list 不在一个列表 | col_name NOT IN (1, 3, 5) |
下面这个表格对字符串操作符有详细的描述:
Operator(操作符) | Condition(解释) | Example(例子) |
---|---|---|
= | Case sensitive exact string comparison (notice the single equals)完全等于 | col_name = “abc” |
!= or <> | Case sensitive exact string inequality comparison 不等于 | col_name != “abcd” |
LIKE | Case insensitive exact string comparison 没有用通配符等价于 = | col_name LIKE “ABC” |
NOT LIKE | Case insensitive exact string inequality comparison 没有用通配符等价于 != | col_name NOT LIKE “ABCD” |
% | Used anywhere in a string to match a sequence of zero or more characters (only with LIKE or NOT LIKE) 通配符,代表匹配0个以上的字符 | col_name LIKE “%AT%”(matches “AT”, “ATTIC”, “CAT” or even “BATS”) “%AT%” 代表AT 前后可以有任意字符 |
_ | Used anywhere in a string to match a single character (only with LIKE or NOT LIKE) 和% 相似,代表1个字符 | col_name LIKE “AN_”(matches “AND”, but not “AN”) |
IN (…) | String exists in a list 在列表 | col_name IN (“A”, “B”, “C”) |
NOT IN (…) | String does not exist in a list 不在列表 | col_name NOT IN (“D”, “E”, “F”) |
在字符串表达式中的字符串需要用引号 " 包含,如果不用引号,SQL会认为是一个属性列的名字
3.查询结果filtering过滤和sorting排序
(1)用 DISTINCT 关键字来指定某个或某些属性列唯一返回。
选取出唯一的结果的语法
SELECT DISTINCT column, another_column, …
FROM mytable
WHERE condition(s);
因为 DISTINCT 语法会直接删除重复的行, 我们还会学习 GROUP BY 语句, GROUP BY 也会返回唯一的行,不过可以对具有相同的 属性值的行做一些统计计算。
(2)用 ORDER BY col_name 排序的语法来让结果按一个或多个属性列做排序。
结果排序(ordered results)
SELECT column, another_column, …
FROM mytable
WHERE condition(s)
ORDER BY column ASC/DESC;
ORDER BY col_name 这句话的意思就是让结果按照 col_name 列的具体值做 ASC升序 或 DESC 降序,对数字来说就是升序 1,2,3,… 或降序 … 3,2,1。
对于文本列,升序和降序指的是按文本的字母序。
ORDER BY 条件1,条件2
代表条件1相同时,再按条件2排序。
(3)通过Limit选取部分结果
LIMIT 和 OFFSET 子句通常和 ORDER BY 语句一起使用,当我们对整个结果集排序之后,我们可以 LIMIT来指定只返回多少行结果 ,用 OFFSET来指定从哪一行开始返回。你可以想象一下从一条长绳子剪下一小段的过程,我们通过 OFFSET 指定从哪里开始剪,用 LIMIT 指定剪下多少长度。
LIMIT查询
SELECT column, another_column, …
FROM mytable
WHERE condition(s)
ORDER BY column ASC/DESC
LIMIT num_limit OFFSET num_offset;
LIMIT 3 OFFSET 1 等价于 LIMIT 1,3 即从1位置向后取3条记录。
4.用JOIN进行多表联合查询
(1)数据库范式(normalization)
数据库范式是数据表设计的规范,在范式规范下,数据库里每个表存储的重复数据降到最少(这有助于数据的一致性维护),同时在数据库范式下,表和表之间不再有很强的数据耦合,可以独立的增长 (ie. 比如汽车引擎的增长和汽车的增长是完全独立的)。
(2)用JOIN进行多表联合查询
主键(primary key), 一般关系数据表中,都会有一个属性列设置为 主键(primary key)。主键是唯一标识一条数据的,不会重复(想象你的身份证号码)。一个最常见的主键就是auto-incrementing integer(自增ID,每写入一行数据ID+1, 当然字符串,hash值等只要是每条数据是唯一的也可以设为主键。
借助主键(primary key)(当然其他唯一性的属性也可以),我们可以把两个表中具有相同 主键ID的数据连接起来(因为一个ID可以简要的识别一条数据,所以连接之后还是表达的同一条数据)(你可以想象一个左右连线游戏)。具体我们用到 JOIN 关键字。我们先来学习 INNER JOIN。
(3)用INNER JOIN 连接表的语法
SELECT column, another_table_column, …
FROM mytable (主表)
INNER JOIN another_table (要连接的表)
ON mytable.id = another_table.id (想象一下刚才讲的主键连接,两个相同的连成1条)
WHERE condition(s)
ORDER BY column, … ASC/DESC
LIMIT num_limit OFFSET num_offset;
通过ON条件描述的关联关系;INNER JOIN 先将两个表数据连接到一起。两个表中如果通过ID互相找不到的数据将会舍弃。此时,你可以将连表后的数据看作两个表的合并,SQL中的其他语句会在这个合并基础上继续执行。
INNER JOIN 可以简写做 JOIN。两者是相同的意思,但我们还是会继续写作 INNER JOIN 以便和后面的 LEFT JOIN, RIGHT JOIN等相比较。
5.外连接(OUTER JOIN)
INNER JOIN 只会保留两个表都存在的数据
左连接LEFT JOIN,右连接RIGHT JOIN 和全连接FULL JOIN。这几个连接方式都会保留不能匹配的行。
用LEFT/RIGHT/FULL JOIN做多表查询
SELECT column, another_column, …
FROM mytable
INNER/LEFT/RIGHT/FULL JOIN another_table
ON mytable.id = another_table.matching_id
WHERE condition(s)
ORDER BY column, … ASC/DESC
LIMIT num_limit OFFSET num_offset;
和INNER JOIN 语法几乎是一样的. 我们看看这三个连接方法的工作原理:
在表 A 连接 B,
LEFT JOIN保留A的所有行,不管有没有能匹配上B,
反过来 RIGHT JOIN则保留所有B里的行。
最后FULL JOIN 不管有没有匹配上,同时保留A和B里的所有行。
如果某一行在另一个表不存在,会用 NULL 来填充结果数据。
所有在用这三个JOIN时,你需要单独处理 NULL。
这些JOIN也可以写作:
LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN
和 LEFT JOIN, RIGHT JOIN, FULL JOIN 等价。
6.关于特殊关键字 NULL
在数据库中,NULL表达的是 "无"的概念,或者说没有东西。因为 NULL的存在,我们需要在编写SQL时考虑到某个属性列可能是 NULL的情况,这种特殊性会造成编写SQL的复杂性,所以没有必要的情况下,我们应该尽量减少 NULL的使用,让数据中尽可能少出现 NULL的情况。
如果某个字段你没有填写到数据库,很可能就会出现NULL 。所有一个常见的方式就是为字段设置默认值,比如数字的默认值设置为0,字符串设置为 ""
但是在一些NULL 表示它本来含义的场景,需要注意是否设置默认值还是保持NULL。 (比如, 当你计算一些行的平均值的时候,如果是0会参与计算导致平均值差错,是NULL则不会参与计算)。
还有一些情况很难避免 NULL 的出现, 比如之前说的 OUTER JOIN 多表连接,A和B有数据差异时,必须用 NULL 来填充。这种情况,可以用IS NULL和 IS NOT NULL 来选在某个字段是否等于 NULL。
在查询条件中处理 NULL
SELECT column, another_column, …
FROM mytable
WHERE column IS/IS NOT NULL
AND/OR another_condition
AND/OR …;
7.在查询中使用表达式
之前我们在SQL中的出现col_name(属性名)的 地方,我们都只是写上col_name自身。其实在SQL中可以用col_name的地方,都可以用表达式来指定对属性进行一定的计算或处理。
SELECT particle_speed / 2.0 AS half_particle_speed
FROM physics_data
WHERE ABS(particle_position) * 10.0 >500;
每一种数据库(mysql,sqlserver等)都有自己的一套函数,包含常用的数字,字符串,时间等处理过程。具体需要参看相关文档。
当我们用表达式对col属性计算时,很多事可以在SQL内完成,这让SQL更加灵活,但表达式如果长了则很难一下子读懂。所以SQL提供了AS关键字, 来给表达式取一个别名。
AS使用别名
SELECT col_expression AS expr_description, …
FROM mytable;
实际上AS不仅用在表达式别名上,普通的属性列甚至是表(table)都可以取一个别名,这让SQL更容易理解。
属性列和表取别名的例子
SELECT column AS better_column_name, …
FROM a_long_widgets_table_name AS mywidgets
INNER JOIN widget_sales
ON mywidgets.id = widget_sales.widget_id;
8.在查询中进行统计
对全部结果数据做统计
SELECT AGG_FUNC(column_or_expression) AS aggregate_description, …
FROM mytable
WHERE constraint_expression;
如果不指明如何分组,那统计函数将对查询结果全部数据进行统计,当然每一个统计也可以像之前用AS来取一个别名,以增加可读性。
下面介绍几个常用统计函数:
Function | Description |
---|---|
COUNT(*), COUNT(column) | 计数!COUNT(*) 统计数据行数,COUNT(column) 统计column非NULL的行数 |
MIN(column) | 找column最小的一行 |
MAX(column) | 找column最大的一行 |
AVG(column) | 对column所有行取平均值 |
SUM(column) | 对column所有行求和 |
分组统计
GROUP BY 数据分组语法可以按某个col_name对数据进行分组,如:GROUP BY Year指对数据按年份分组, 相同年份的分到一个组里。如果把统计函数和GROUP BY结合,那统计结果就是对分组内的数据统计了。
GROUP BY 分组结果的数据条数,就是分组数量,比如:GROUP BY Year,全部数据里有几年,就返回几条数据,不管是否应用了统计函数。
用分组的方式统计
SELECT AGG_FUNC(column_or_expression) AS aggregate_description, …
FROM mytable
WHERE constraint_expression
GROUP BY column;
在 GROUP BY 分组语法中,我们知道数据库是先对数据做WHERE,然后对结果做分组,如果我们要对分组完的数据再筛选出几条如何办? (想一下按年份统计电影票房,要筛选出>100万的年份?)
一个不常用的语法 HAVING 语法将用来解决这个问题,他可以对分组之后的数据再做SELECT筛选。
用HAVING进行筛选
SELECT group_by_column, AGG_FUNC(column_expression) AS aggregate_result_alias, …
FROM mytable
WHERE condition
GROUP BY column
HAVING group_condition;
HAVING 和 WHERE 语法一样,只不过作用的结果集不一样. 在我们例子数据表数据量小的情况下可能感觉 HAVING没有什么用,但当你的数据量成千上万属性又很多时也许能帮上大忙。
如果你不用GROUP BY
语法, 简单的WHERE
就够用了。
练习题:
Table(表): Employees
Role | Name | Building | Years_employed |
---|---|---|---|
Engineer | Becky A. | 1e | 4 |
Engineer | Dan B. | 1e | 2 |
Engineer | Sharon F. | 1e | 6 |
Engineer | Dan M. | 1e | 4 |
Engineer | Malcom S. | 1e | 1 |
Artist | Tylar S. | 2w | 2 |
Artist | Sherman D. | 2w | 8 |
Artist | Jakob J. | 2w | 6 |
Artist | Lillia A. | 2w | 7 |
Artist | Brandon J. | 2w | 7 |
Manager | Scott K. | 1e | 9 |
Manager | Shirlee M. | 1e | 3 |
Manager | Daria O. | 2w | 6 |
Engineer | Yancy I. | null | 0 |
Artist | Oliver P. | null | 0 |
按角色分组算出每个角色按有办公室和没办公室的统计人数(列出角色,数量,有无办公室,注意一个角色如果部分有办公室,部分没有需分开统计)
--请输入sql
SELECT count(Name) AS count,
role,
CASE WHEN Building is not null then '1' else '0' end as Bn
FROM employees
group by role,bn
9.查询执行顺序
这才是完整的SELECT查询
SELECT DISTINCT column, AGG_FUNC(column_or_expression), …
FROM mytable
JOIN another_table
ON mytable.column = another_table.column
WHERE constraint_expression
GROUP BY column
HAVING constraint_expression
ORDER BY column ASC/DESC
LIMIT count OFFSET COUNT;
写法顺序:select–from–where–group by–having–order by
执行顺序:from–where–group by–having–select–order by
就是select要放后面,如果有order by,则order by放最后,因为order by 是对结果进行排序。
查询执行顺序
- FROM 和 JOINs
FROM 或 JOIN会第一个执行,确定一个整体的数据范围. 如果要JOIN不同表,可能会生成一个临时Table来用于 下面的过程。总之第一步可以简单理解为确定一个数据源表(含临时表) - WHERE
我们确定了数据来源 WHERE 语句就将在这个数据源中按要求进行数据筛选,并丢弃不符合要求的数据行,所有的筛选col属性 只能来自FROM圈定的表. AS别名还不能在这个阶段使用,因为可能别名是一个还没执行的表达式 - GROUP BY
如果你用了 GROUP BY 分组,那GROUP BY 将对之前的数据进行分组,统计等,并将是结果集缩小为分组数.这意味着 其他的数据在分组后丢弃 - HAVING
如果你用了 GROUP BY 分组, HAVING 会在分组完成后对结果集再次筛选。AS别名也不能在这个阶段使用 - SELECT
确定结果之后,SELECT用来对结果col简单筛选或计算,决定输出什么数据 - DISTINCT
如果数据行有重复DISTINCT 将负责排重 - ORDER BY
在结果集确定的情况下,ORDER BY 对结果做排序。因为SELECT中的表达式已经执行完了。此时可以用AS别名 - LIMIT / OFFSET
最后 LIMIT 和 OFFSET 从排序的结果中截取部分数据
练习题:
Table: Movies
Id | Title | Director | Year | Length_minutes |
---|---|---|---|---|
1 | Toy Story | John Lasseter | 1995 | 81 |
2 | A Bug’s Life | John Lasseter | 1998 | 95 |
3 | Toy Story 2 | John Lasseter | 1999 | 93 |
4 | Monsters, Inc. | Pete Docter | 2001 | 92 |
5 | Finding Nemo | Finding Nemo | 2003 | 107 |
6 | The Incredibles | Brad Bird | 2004 | 116 |
7 | Cars | John Lasseter | 2006 | 117 |
8 | Ratatouille | Brad Bird | 2007 | 115 |
9 | WALL-E | Andrew Stanton | 2008 | 104 |
10 | Up | Pete Docter | 2009 | 101 |
11 | Toy Story 3 | Lee Unkrich | 2010 | 103 |
12 | Cars 2 | John Lasseter | 2011 | 120 |
13 | Brave | Brenda Chapman | 2012 | 102 |
14 | Monsters University | Dan Scanlon | 2013 | 110 |
Table: Boxoffice
Movie_id | Rating | Domestic_sales | International_sales |
---|---|---|---|
5 | 8.2 | 380843261 | 555900000 |
14 | 7.4 | 268492764 | 475066843 |
8 | 8 | 206445654 | 417277164 |
12 | 6.4 | 191452396 | 368400000 |
3 | 7.9 | 245852179 | 239163000 |
6 | 8 | 261441092 | 370001000 |
9 | 8.5 | 223808164 | 297503696 |
11 | 8.4 | 415004880 | 648167031 |
1 | 8.3 | 191796233 | 170162503 |
7 | 7.2 | 244082982 | 217900167 |
10 | 8.3 | 293004164 | 438338580 |
4 | 8.1 | 289916256 | 272900000 |
2 | 7.2 | 162798565 | 200600000 |
13 | 7.2 | 237283207 | 301700000 |
找出每部电影和单部电影销售冠军之间的销售差,列出电影名,销售额差额
--请输入sql
SELECT Title,
(SELECT(MAX(Domestic_sales+International_sales)) FROM Boxoffice)-SUM(Domestic_sales+International_sales) as diff
FROM Movies
INNER JOIN Boxoffice
ON Movies.Id=Boxoffice.Movie_id
GROUP BY Title;
10.SELECT INTO
SELECT INTO语句从一个表中选取数据,然后把数据插入另一个表中。常用于创建表的备份复件或者用于对记录进行存档。
把所有的列插入新表 :
SELECT *
INTO new_table_name [IN externaldatabase]
FROM old_tablename
只把希望的列插入新表 :
SELECT column_name(s)
INTO new_table_name [IN externaldatabase]
FROM old_tablename
二、其余语法
1.SQL INSERT INTO 语法
INSERT INTO 语句可以有两种编写形式。
第一种形式无需指定要插入数据的列名,只需提供被插入的值即可:
INSERT INTO table_name
VALUES (value1,value2,value3,...);
第二种形式需要指定列名及被插入的值:
INSERT INTO table_name (column1,column2,column3,...)
VALUES (value1,value2,value3,...);
2.SQL UPDATE 语句
UPDATE 语句用于更新表中已存在的记录。
UPDATE table_name
SET column1=value1,column2=value2,...
WHERE some_column=some_value;
3.SQL DELETE 语句
DELETE 语句用于删除表中的行。
DELETE FROM table_name
WHERE some_column=some_value;
4.SQL UNION 操作符
纵向合并两个表的数据,这时会用到UNION和UNION ALL关键字。
其区别就是:
UNION会进行数据的排序和去重,查询效率低。
UNION ALL没有进行去重和排序,查询效率高。
需要注意的是:合并的两个或多个表需要保证他们字段的个数相同,否则会报错。
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。
SQL UNION 语法
SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
SQL UNION ALL 语法
SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;
注释:UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
5.SQL INSERT INTO SELECT 语句
INSERT INTO SELECT 语句从一个表复制数据,然后把数据插入到一个已存在的表中。目标表中任何已存在的行都不会受影响。
我们可以从一个表中复制所有的列插入到另一个已存在的表中:
INSERT INTO table2
SELECT * FROM table1;
或者我们可以只复制希望的列插入到另一个已存在的表中:
INSERT INTO table2
(column_name(s))
SELECT column_name(s)
FROM table1;
6.SQL CREATE DATABASE 语句
CREATE DATABASE 语句用于创建数据库。
CREATE DATABASE dbname;
7.SQL CREATE TABLE 语句
CREATE TABLE 语句用于创建数据库中的表。
表由行和列组成,每个表都必须有个表名。
CREATE TABLE table_name
(
column_name1 data_type(size),
column_name2 data_type(size),
column_name3 data_type(size),
....
);
8.SQL 约束(Constraints)
SQL 约束用于规定表中的数据规则。
如果存在违反约束的数据行为,行为会被约束终止。
约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。
SQL CREATE TABLE + CONSTRAINT 语法
CREATE TABLE table_name
(
column_name1 data_type(size) constraint_name,
column_name2 data_type(size) constraint_name,
column_name3 data_type(size) constraint_name,
....
);
在 SQL 中,我们有如下约束:
NOT NULL - 指示某列不能存储 NULL 值。
UNIQUE - 保证某列的每行必须有唯一的值。
PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。
CHECK - 保证列中的值符合指定的条件。
DEFAULT - 规定没有给列赋值时的默认值。
9.charindex函数,判断一个字符串中是否包含另一个字符串
charindex(用于判断一个字符串中是否包含另一个字符串)
基本语法如下:
CHARINDEX ( expressionToFind , expressionToSearch [ , start_location ] )
expressionToFind :目标字符串,就是想要找到的字符串,最大长度为8000 。
expressionToSearch :用于被查找的字符串。
start_location:开始查找的位置,为空时默认从第一位开始查找。
例题:
查询显示雇员的姓名和姓名中是否含有字母A的信息,满足如下条件
如果字符A在姓名的首位,则显示’字符A在首位’
如果字符A在姓名的末位,则显示’字符A在末位’
如果字符A在姓名中不存在,则显示’没有字符A’
其他情况显示’字符A在中间’
sql语句:
select ename, case charindex(‘A‘,ename)
when 1 then ‘字符A在首位‘
when len(ename) then
‘字符A在末位‘
when 0 then ‘没有字符A‘
else ‘字符A在中间‘
end 名称类别 from emp;
10.字符串拼接
直接'要拼接字符串'+原来字段+'要拼接字符串'
例:
select 'EPC-'+ LTRIM(str(po.id)) +'-1' as EPC_ID
11.字符串截取substring
如substring(name,5,3) 截取name这个字段,从第五个字符开始,只截取之后的3个字符
例:
select substring(ReferenceNumber, 5, 7) as Id
12.字符串替换REPLACE
REPLACE(String,from_str,to_str)
即:将字段String中所有出现的from_str替换为to_str
如,
REPLACE(length,'m','')
表示将length字段中的m替换为空,即删除length字段中所有的长度单位m。
可在SELECT查询中使用,如:
select replace(length,'m','') AS rep
from test
replace函数返回替换之后的字符串
replace也可以进行嵌套使用,如:
replace(replace(length,'m',''), char(13), '')
表示将length字段中的m替换为空,即删除length字段中所有的长度单位m。
之后再将处理后的字符串中的回车替换为空,即删除所有空格。
13.COALESCE函数返回第一个非空值
COALESCE(expression_1, expression_2, ...,expression_n)
返回第一个非空值
如果所有的表达式都是空值,最终将返回一个空值。
如:
coalesce(1, 2,3); --return 1
coalesce(null,2,3); --return 2
coalesce(null,null,3); --return 3
coalesce(null,null,3,null,5); --return 3
select coalesce(a,b,c);
表示,如果a为NULL,则选择b;如果b为NULL,则选择c;如果a!=NULL,则选择a;如果a、b、c都为null,则返回为null。
其他作用:
select coalesce(test, 'a') from tableA
即将字段test中为NULL的显示为a,不为NULL的还显示原来的真实值。
select coalesce(testA,testB,'a') from tableB
即,
只要字段testA不为NULL,都将返回testA的真实值(因为testA是第一个参数)
当字段testA为NULL,而字段testB不为NULL时,返回testB的真实值。
只有当字段testA和字段testB均为NULL的时候,才返回1。
14.EXISTS函数
EXISTS (subquery)
如果子查询包含任何行,则EXISTS运算符返回true。 否则它返回false。
EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False
select 1
如果表里有记录,select 1语句就会返回相应的记录行数的结果集,并且列名为1,每一行的值也都是1。它可以替换成任意的常量,此时返回的列名和值都是该常量。比如select 2。
select 1可以用来查询表中是否有符合条件的记录(比如select 1 from table where id = 100;)
select 1一般用来当作条件使用,比如exists( select 1 from 表名)等。
select 1的效率比select列名和select*快,因为不用查字典表。
select null
select null 和select 1类似,只是返回的列名和值变成了NULL。
在子查询中使用 NULL 仍然返回结果集
select * from table where exists(select null)
等同于:
select * from table
INSERT INTO SELECT FROM DUAL WHERE NOT EXISTS
先检查资料是否重复再来决定是否 INSERT,如果不重复,则INSERT
INSERT INTO 要插入的表名 (要插入的列名)
SELECT '要插入的数据' FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM 要插入的表名 WHERE 要插入的列名='要插入的数据' LIMIT 1
);
一般 INSERT后面接的是 VALUE()
如果接SELECT,表示:SELECT 的返回值就是INSERT的VALUE() 值。
SELECT FROM DUAL
DUAL 是一种特别的只有1行1列的表。
如果从其他表中读取数据时,会依据返回的行数来决定其要插入几行资料。
LIMIT 1只需要第一行数据来确认是否有该记录即可。
15.IFNULL函数
IFNULL(expression_1,expression_2);
如果expression_1不为NULL,则IFNULL函数返回expression_1; 否则返回expression_2。