https://code.tutsplus.com/articles/sql-for-beginners–net-8200 https://code.tutsplus.com/articles/sql-for-beginners-part-2–net-8274 https://code.tutsplus.com/articles/sql-for-beginners-part-3-database-relationships–net-8561
两张表:
CREATE TABLE customers( customers_id INT AUTO_INCREMENT PRIMARY KEY, customers_name VARCHAR(100) );
//明确声明 customer_id 字段为外键,并关联 customers表的 customer_id 字段 CREATE TABLE orders( orders_id INT AUTO_INCREMENT PRIMARY KEY, customer_id INT FOREIGN KEY (customer_id) REFERENCES customers(customer_id) );
关系sql语句说明FOREIGN KEY 外键CREATE TABLE orders(…FOREIGN KEY (customer_id) REFERENCES customers(customer_id));使用 JOIN 查询检索数据时即使数据库引擎不知道该关系,仍然可以将此列视为外键Cross Join全外连接SELECT * FROM customers CROSS JOIN orders;结果是“笛卡尔积”第一张表每一行 都与 第二张表中的每一行匹配。假设每个表有 4行,最终会得到 16行 的结果Natural JoinSELECT * FROM customers NATURAL JOIN orders;使用这种JOIN查询,表要具有名字相同的列名Demo中,两个表都具有 _id 列,仅当此列 _id 的值在两条记录上匹配时,才会加入记录 (根据相同列名来匹配)Inner Join等值连接 / 内连接SELECT * FROM customers JOIN orders WHERE customers.customers _id = orders.customers _id;只返回 两个表中 连接字段相等 的行ON 语句SELECT * FROM customers JOIN orders ON (customers.customers_id = orders.customers_id) WHERE orders.amount > 15;USING 语句SELECT * FROM customers JOIN ordersUSING (customers_id) WHERE orders.amount > 15;类似 ON 语句两个表,有相同名字的字段 时,可用 USING 来指定Left (Outer) JoinSELECT * FROM customers LEFT OUTER JOIN ordersUSING (customers_id);左表所有记录 + 右表连接字段相等的记录Right (Outer) JoinSELECT * FROM customers RIGHT OUTER JOIN ordersUSING (customers_id);右表所有记录 + 左表中连接字段相等记录1)创建/删除/使用数据库
CREATE DATABASE my_first_db; /* EFAULT CHARACTER SET utf8:设置字符集 utf8 * COLLATE utf8_general_ci(后缀"_cs"或者"_ci"意思是区分大小写和不区分大小写(Case Sensitive & Case Insensitve)) * 这里utf8_general_ci表示不区分大小写 */ CREATE DATABASE my_first_db DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; //列出所有数据库 SHOW DATABASES; //删除数据库 DROP DATABASE my_first_db; //选择一个数据库 USE my_first_db;2)创建/删除表
//创建users表,字段 username 字符类型,字段 create_date 日期类型 CREATE TABLE users (username VARCHAR(20), create_date DATE); //user_id INT AUTO_INCREMENT PRIMARY KEY:主键 user_id INT类型 自增长 CREATE TABLE users (user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(20), create_date DATE); //列出所选数据库的所有表 SHOW TABLES; //展示表结构 EXPLAIN users; //删除表 DROP TABLE users; //修改表-增加字段:在 username字段后面增加 email 字段 ALTER TABLE users ADD email VARCHAR(100) AFTER username; //修改表-删除字段 ALTER TABLE users DROP email; //修改表-修改字段:把username 字段 改为 user_name 字符长度改为30 ALTER TABLE users CHANGE username user_name VARCHAR(30)3)插入表数据
//插入数据 VALUES 方式 INSERT INTO users VALUES(NULL, 'johndoe', 'john@doe.com', '2009-12-14'); //插入数据 SET 方式 INSERT INTO users SET user_name = 'nettuts', email = 'nettuts@gmail.com',create_date = '2019-12-14'; //插入数据 INSERT INTO users (email, user_name, create_date) VALUES ('foo@bar.com', 'foobar','2019-12-16'); //NOW() 关键字 INSERT INTO users SET create_date = NOW(), user_name = 'batman', email = 'bat@man.com';4)查询表数据
//LAST_INSERT_ID():查询最后一次插入数据的ID SELECT LAST_INSERT_ID(); //查询当前时间 SELECT NOW(); //查询表中所有字段 SELECT * FROM users; //查询表中指定字段 SELECT user_name, email FROM users; //WHERE 条件语句 SELECT email FROM users WHERE user_name='nettuts'; SELECT * FROM users WHERE user_id <= 2; SELECT * FROM users WHERE create_date != '2009-12-14'; //AND、OR 关键字 SELECT * FROM users WHERE user_id = 1 OR user_name = 'nettuts'; //IN() 语句 SELECT * FROM users WHERE create_date IN ('2009-12-15', '2019-12-15'); //LIKE 关键字 %作为通配符 SELECT * FROM users WHERE email LIKE '%TUTS%'; //ORDER BY 语句 SELECT * FROM users ORDER BY create_date; //DESC降序排列;默认是 ASC升序排列 SELECT * FROM users ORDER BY user_name DESC; /* LIMIT ... OFFSET ... * LIMIT 1,表示获取 1 条结果 * OFFSET 2,表示从头两条数据之后开始算起 */ SELECT * FROM users LIMIT 1 OFFSET 2;5)更新表数据
//修改某条数据 UPDATE users SET email = 'changed@gmail.com', user_name = 'barfoo' WHERE user_name = 'foobar'; UPDATE users SET create_date = '2009-12-01' WHERE create_date = '2009-12-14' LIMIT 1;6)删除表数据
//DELETE DELETE FROM users WHERE user_name = 'batman'; //TRUNCATE:重置表,自增长的字段数据也会被重置 TRUNCATE TABLE users; //DELETE:删除表数据,不会重置自增长的字段数据 DELETE FROM users;7)特殊字符
i. 反斜杠 \ 转义字符 INSERT INTO users SET user_name = 'O\'Reilly'; 插入后,表中 user_name 的值 为 O'Reilly,把 ' 当作字符串写入数据库。 ii. 关键字(select、delete、insert等)不能作为表的字段,否则会报错8)主键 PRIMARY KEY
//创建主键的方式 CREATE TABLE states ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20) ); CREATE TABLE states ( id INT AUTO_INCREMENT, name VARCHAR(20), PRIMARY KEY (id) );9)唯一不可重复 UNIQUE
//设置 name 字段唯一,索引名默认为字段名 name CREATE TABLE states ( id INT AUTO_INCREMENT, name VARCHAR(20), PRIMARY KEY (id), UNIQUE (name) ); //设置 name 字段唯一,并且索引名为 state_name CREATE TABLE states ( id INT AUTO_INCREMENT, name VARCHAR(20), PRIMARY KEY (id), UNIQUE state_name (name) );10)INDEX 索引
//创建索引 CREATE TABLE states ( id INT AUTO_INCREMENT, name VARCHAR(20), join_year INT, PRIMARY KEY (id), UNIQUE (name), INDEX (join_year) ); //可以用 KEY 关键字 代替 INDEX 关键字 CREATE TABLE states ( id INT AUTO_INCREMENT, name VARCHAR(20), join_year INT, PRIMARY KEY (id), UNIQUE (name), KEY (join_year) );11)GROUP BY 分组:BY 后面跟字段名,表示根据某个字段分组
//根据 join_year 字段分组,join_year值相同的数据会分为一组 SELECT * FROM states GROUP BY join_year;12)COUNT(*) 计数函数,常与 GROUP BY配合使用
//根据join_year进行分组,并计算每组数量,返回 每组数量 和 join_year SELECT COUNT(*), join_year FROM states GROUP BY join_year; //返回 states表数据条数 SELECT COUNT(*) FROM states; //查询 join_year = 1787 的数据条数 SELECT COUNT(*) FROM states WHERE join_year = 1787;13)MIN()最小值函数, MAX()最大值函数, AVG()平均数函数
//查询states表中 population的最小值、最大值、平均值 SELECT MIN(population), MAX(population), AVG(population) FROM states;14)GROUP_CONCAT() 将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
/* 查询states表,根据join_year进行分组,把每个分组所有元素的name用逗号','分隔拼接成字符串返回, * 还有返回join_year */ SELECT GROUP_CONCAT(name SEPARATOR ', '), join_year FROM states GROUP BY join_year;15)SUM() 求和
//查询 states表中所有元素的 population 之和,以 usa_population为别名返回 SELECT SUM(population) AS usa_population FROM states;16)IF() 语句
该语句有三个参数,参数一:条件 参数二:条件为true时的返回值 参数三:条件为false时的返回值 //返回 foo SELECT IF(true, 'foo', 'bar'); //返回 bar SELECT IF(false, 'foo', 'bar'); /* 每次查到 population > 5000000 的数据 big_states 的结果+1, * population <=5000000的数据 big_states的结果+0 * * 每次查到 population <= 5000000 的数据 small_states 的结果+1, * population >5000000的数据 small_states 的结果+0 * * 最后返回 big_states、small_states的值 */ SELECT SUM( IF(population > 5000000, 1, 0) ) AS big_states, SUM( IF(population <= 5000000, 1, 0) ) AS small_states FROM states;17)CASE
/* 计数,返回 state_size字段和数量, * population > 5000000 时 state_size 的值为 big * population > 1000000 时 state_size 的值为 medium * population <= 1000000时 state_size 的值为 small */ SELECT COUNT(*), CASE WHEN population > 5000000 THEN 'big' WHEN population > 1000000 THEN 'medium' ELSE 'small' END AS state_size FROM states GROUP BY state_size;18)HAVING
//与GROUP BY 配合使用的条件句 SELECT COUNT(*), join_year FROM states GROUP BY join_year HAVING COUNT(*) > 1;19)多重查询
//从一个查询语句的结果中查询 SELECT * FROM states WHERE join_year = ( SELECT MAX(join_year) FROM states );20)IN() 在IN(…)条件之内的数据
SELECT * FROM states WHERE join_year IN ( SELECT join_year FROM states GROUP BY join_year HAVING COUNT(*) > 1 ) ORDER BY join_year;21)UNION 合并数据
(SELECT * FROM states WHERE name LIKE 'n%') UNION (SELECT * FROM states WHERE population > 10000000);22)INSERT … ON DUPLICATE KEY UPDATE
前提条件设置: 创建表,name字段唯一 CREATE TABLE products ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20), stock INT, UNIQUE (name) ); //插入数据 name = 'breadmaker', stock = 10 INSERT INTO products SET name = 'breadmaker', stock = 10; 此时如果再插入 name = 'breadmaker' 的数据会报错,Dup里擦忒entry 'breadmaker' for key 'name' 需要执行以下SQL语句: INSERT INTO products SET name = 'breadmaker', stock = 1 ON DUPLICATE KEY UPDATE stock = stock + 1;23)REPLACE INFO
该语句类似INSERT 语句的作用,但是对于UNIQUE字段的数据,INSERT 插入该字段重复的数据时会报错。 REPLACE INFO 插入UNIQUE字段重复的数据时,不会报错, 会先删除旧数据,然后插入本条数据,id会自增。 REPLACE INFO products SET name = 'breadmaker', stock = 5;24)INSERT IGNORE
该语句可以避免插入UNIQUE字段重复的数据时报错,但是只是不再报错,并不能插入成功 INSERT IGNORE INTO products SET name = 'breadmaker', stock = 1;1)整数 数据类型
类型 字节数 最小值 最大值 TINYINT 1 -128 127 SMALLINT 2 -32768 32767 MEDIUMINT 3 INT 4 BIGINT 82)非整数 的数字数据类型
FLOAT 4 字节 DOUBLE 8 字节 DECIMAL(M,N) 最多包含M个整数和N个小数位3)字符串数据类型
CHAR(N) VARCHAR(N) TEXT4)日期类型
DATE 范围 '1001-01-01' 到 '9999-12-31' DATETIME 范围 '1001-01-01 00:00:00' 到 '9999-12-31 23:59:59' TIMESTAMP 范围 '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC TIME 只能保存'时分秒' YEAR 只能保存 '年' 比如 '2019'1)FOREIGN KEY 外键
CREATE TABLE customers ( customer_id INT AUTO_INCREMENT PRIMARY KEY, customer_name VARCHAR(100) ); //明确声明customer_id字段为外键,并关联 customers表的customer_id字段 CREATE TABLE orders ( order_id INT AUTO_INCREMENT PRIMARY KEY, customer_id INT, amount DOUBLE, FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ); //不需要明确声明customer_id为外键,而是声明为索引 CREATE TABLE orders ( order_id INT AUTO_INCREMENT PRIMARY KEY, customer_id INT, amount DOUBLE, INDEX (customer_id) ); //使用JOIN查询检索数据时,即使数据库引擎不知道该关系,您仍然可以将此列视为外键。 SELECT * FROM orders JOIN customers USING(customer_id)2)Cross Join (全外连接):返回左右表中所有的记录和左右表中连接字段相等的记录。 /* 下面是有外键关系时的写法 * 结果是“笛卡尔积”,第一张表中的每一行都与第二张表中的每一行匹配。 * 由于每个表有4行,因此最终得到16行的结果 */ SELECT * FROM customers JOIN orders; 等同于: SELECT * FROM customers, orders;
3)Natural Join
使用这种JOIN查询,表需要具有匹配的列名。 在我们的例子中,两个表都具有 customer_id 列。 因此,仅当此列 customer_id 的值在两条记录上匹配时,才会加入记录 SELECT * FROM customers NATURAL JOIN orders;4)Inner Join (等值连接或者叫内连接):只返回两个表中连接字段相等的行。 指定连接条件后,将执行内部连接。 在这种情况下,最好使两个表上的customer_id字段都匹配。 结果应类似于自然联接。
SELECT * FROM customers JOIN orders WHERE customers.customer_id = orders.customer_id;5)ON 语句
SELECT * FROM customers JOIN orders ON (customers.customer_id = orders.customer_id) WHERE orders.amount > 15;6)USING 语句 类似 ON 语句,当两个表有名字相同的字段时,可以通过USING 来指定
SELECT * FROM customers JOIN orders USING (customer_id) WHERE orders.amount > 15;7)Left (Outer) Join 左联接是外联接的一种。 返回包括左表中的所有记录和右表中连接字段相等的记录。
SELECT * FROM customers LEFT OUTER JOIN orders USING (customer_id); SELECT * FROM customers LEFT OUTER JOIN orders USING (customer_id) WHERE orders.order_id IS NULL; SELECT * FROM customers LEFT OUTER JOIN orders USING (customer_id) WHERE orders.amount > 15; SELECT * FROM customers LEFT OUTER JOIN orders USING (customer_id) WHERE orders.amount > 15 OR orders.order_id IS NULL; SELECT * FROM customers LEFT OUTER JOIN orders ON (customers.customer_id = orders.customer_id AND orders.amount > 15);8)Right (Outer) Join 右联接是外联接的一种。 返回包括右表中的所有记录和左表中连接字段相等的记录。
SELECT * FROM customers RIGHT OUTER JOIN orders USING (customer_id); SELECT * FROM orders RIGHT OUTER JOIN customers USING (customer_id);推荐阅读: 数据库基础1 数据库基础2 数据库基础3