数据库是保存表和其他相关SQL结构的容器。
数据库内的信息组成了表。
数据库由表构成。
表是在数据库中包含数据的结构,由列和行组成。
把对象属性分类,某一类信息是表中的一列。
表的行包含了表中某个对象的所有的信息。
列是存储在表中的一块数据。行是一组能够描述某个事物的列的集合。列和行构成了表。
字段(field) 也常用来代称 列,记录(record) 与行也常交替使用。
CREATE DATABASE gregs_list;
USE gregs_list;
CREATE TABLE my_contacts
(
last_name VARCHAR(30) NOT NULL,
first_name VARCHAR(20) NOT NULL,
email VARCHAR(50),
birthday DATE
);
数据类型:
检查创建的表:
DESC my_contacts;
删除表:
DROP TABLE my_contacts;
DROP TABLE会删除你的表和表里面所有的数据!
插入数据到表中:
INSERT INTO your_table (column_name1, column_name2, ...) VALUES ( 'value1', 'value2',...);
注意:数值类型不要加上单引号。
查询数据:
SELECT * FROM my_contacts;
用DEFAULT值填满空白列的值。
SELECT * FROM my_contacts WHERE first_name = 'Anne';
数据类型中,VARCHAR, CHAR, BLOB, DATE, TIME需要单引号,数字类的类型,DEC和INT则不需引号。
单引号是特殊字符,需要加上转义字符\。
不要使用双引号,因为你的SQL语句日后会搭配其他编程语言。在编程语言中使用"“表示"从这里开始是SQL语句”,这样单引号才会被视为SQL语句的一部分,而不是其他编程语言的一部分。
SELECT特定列来限制结果数量并加快结果呈现。
SELECT * FROM easy_drinks WHERE NOT main IS NULL;
LIKE和通配符
BETWEEN等于使用<=和>=
IN和NOT IN
NOT反转查询结果,取得相反的值。
NOT一定要紧接在WHERE后面,和AND或OR一期使用时,则要直接接在AND或OR的后面。
SELECT drink_name FROM drink_info WHERE NOT carbs BETWEEN 3 AND 5;
SELECT date_name from black_book WHERE NOT date_name LIKE 'A%' AND NOT date_name LIKE 'B%';
DELETE子句可以和WHERE子句搭配使用,使用方式和SELECT与WHERE的搭配方式一样。
DELETE FROM clown_info
WHERE
activities = 'dancing';
DELETE的规则:
DELETE FROM your_table;
除非你可以非常确定WHERE只会删除你打算删除的行,否则都应该用SELECT确认情况。
UPDATE your_table
SET first_column = 'newvalue',
second_column = 'another_value'
WHERE column_name = somevalue;
存放的数据量取决于数据的使用方式。
创建表时可供遵循的步骤:
一小块无法或不应分割的信息。
规则一:具有原子性数据的列中不会有多个类型相同的值
规则二:具有原子性数据的表中不会有多个存储同类数据的列
让数据具有原子性是创建一个规范化表的第一步。
规范化表的优点:
第一范式 FIRST NORMAL FORM
每个数据行必须包含具有原子性的值。
每个数据行必须有独一无二的识别项,人称主键。
SHOW CREATE TABLE my_contacts;
ALTER TABLE my_contacts
ADD COLUMN contact_id INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (contact_id);
ALTER TABLE projekts
RENAME TO project_list;
ALTER TABLE project_list
CHANGE COLUMN descriptionofproj proj_desc VARCHAR(100),
CHANGE COLUMN contractoronjob con_name VARCHAR(30);
ALTER TABLE project_list
MODIFY COLUMN proj_desc VARCHAR(120);
ALTER TABLE project_list
DROP COLUMN start_date;
字符串函数
UPDATE movie_table
SET category =
CASE
WHEN drama = 'T' THEN 'drama'
WHEN comedy = 'T' THEN 'comedy'
WHEN action = 'T' THEN 'action'
WHEN cartoon = 'T' AND rating = 'G' THEN 'family'
ELSE 'misc'
END;
!"#$%&’()*+,-./0123:;<=>?@abcd[]^_`abcd{|}~
SELECT title, category, pruchased
FROM movie_table
ORDER BY category, purchased DESC;
SELECT SUM(sales)
FROM cookie_sales
WHERE first_name = 'Nicole';
SELECT first_name, SUM(sales)
FROM cookie_sales
GROUP BY first_name
ORDER BY SUM(sales) DESC;
SELECT first_name, AVG(sales)
FROM cookie_sales
GROUP BY first_name;
SELECT DISTINCT sales_date
FROM cookie_sales
ORDER BY sale_date;
LIMIT 0,4
查询结果起始处,查询返回结果的数量
模式(schema)用于表达数据库的结构,包括表和列,还有各种他们之间相互连接的方式。
外键是表中的某一列,它引用到另一个表的主键。
外键二三事:
插入外键列的值必须已经存在于父表的来源列中,这是引用完整性(referential integrity)。
外键不一定必须是父表的主键,单必须有唯一性。
CREATE TABLE interests (
int_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
interest VARCHAR(50) NOT NULL,
contact_id INT NOT NULL,
CONSTRAINT my_contacts_contact_id_fk //约束的名字
FOREIGN KEY (contact_id) //括号中的列名就代表外键,可以随意命名
REFERENCE my_contact (contact_id) //外键的来源以及在另一张表中的名称
);
一对一,一对多,多对多,找出数据所属的模式后,设计多张表的关系——设计数据库模式,也就变得简单了。
连接线为单纯的实线,表示连接意见事物与另一件事物。例如雇员表和工资表。
我们其实不会经常用到一对一的表。通常,把一对一的数据留在主表更合理,但是某些情况如下:
A表中的某一条记录可以对应到B表中的多条记录,但B表中的某一条记录只能对应到A表中的某一条记录。
连接线应该带有黑色箭头俩表示一对多的连接关系。
比如profession表和my_contacs表。
许多女士拥有许多双鞋。
连接线的两端都带有黑色箭头,代表连接许多事物与许多事物。
在两个多对多的表之间需要一个中间桥梁来存储所有的woman_id与shoe_id,从而把关系简化为一对多。这个中间桥梁就是所谓的junction table(连接表),用来存储两个相关表的主键。
在my_contacts表中,每一个人有多项兴趣,但每一个兴趣可能属于多个人,所以这种关系属于多对多的模式。
数据越规范,以查询取得数据也就越容易,对联接(join)也越有帮助。
有两列以上组成的键称为组合键,就是由多个数据列构成的主键,组合各列后形成具有唯一性的键。
表中的数据列本身对其他列也有关系。这是了解第二范式与第三范式的关键。
当某列的数据必须随着另一列的数据的改变而改变时,表示第一列函数依赖于第二列。
速记符号:
T.x -> T.y
在关系表中,y列函数依赖于x列。
部分函数依赖:非主键列依赖于组合主键的某个部分。
传递函数依赖:任何非键列与另一个非键列有关联。
举个例子:
courses
course_id
course_name
instructor
instructor_phone
在表中加入主键列有助于达成2NF。
第二范式的重点就是表的主键如何与其他数据产生关系。
第二范式:又称2NF
规则一:先符合1NF
规则二:没有部分函数依赖性。
任何具有人工主键且没有组合主键的表都符合2NF。
第三范式:又称3NF
规则一:先符合2NF;
规则二:没有传递函数依赖性。
CREATE TABLE profession
(
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
profession VARCHAR(20)
);
INSERT INTO profession (profession)
SELECT profession FROM my_contacts
GROUP BY profession
ORDER BY profession;
CREATE TABLE profession AS
SELECT profession FROM my_contacts
GROUP BY profession
ORDER BY profession;
ALTER TABLE profession
ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (id);
CREATE TABLE profession
(
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
profession VARCHAR(20)
) AS
SELECT professioin FROM my_contacts
GROUP BY profession
ORDER BY profession;
AS能把SELECT的查询结果填入新表中。
列的别名
CREATE TABLE profession
(
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
mc_prof VARCHAR(20)
) AS
SELECT profession AS mc_prof FROM my_contacts
GROUP BY mc_prof
ORDER BY mc_prof;
以上创建的新表还是会有名为profession的列,而非mc_prof。
表名和列名都可以有别名,也可以省略AS.
SELECT profession mc_prof
FROM my_contacts mc
GROUP BY mc_prof
ORDER BY mc_prof;
交叉联接:CROSS JOIN返回两张表的每一行相乘的结果。
SELECT t.toy, b.boy
FROM toys AS t
CROSS JOIN
boys AS b;
或者可以省略CROSS JOIN
SELECT toys.toy, boys.boy
FORM toys, boys;
问:为什么需要交叉联接?
答:因为当我们乱玩联接时可能意外造成交叉联接。知道交叉联接的存在有益于找出修正联接的方式。交叉联接有事可用于检测RDBMS软件及其配置的运行速度。运行交叉联接所需的时间可以轻易的检测与比较出速度较慢的查询。
内联接:就是通过查询中的条件移出了某些结果数据行后的交叉联接。利用条件判断中的比较运算符结合两张表的记录。
boy_id | boy | toy_id |
---|---|---|
1 | Davey | 3 |
2 | Bobby | 5 |
3 | Beaver | 2 |
4 | Richie | 1 |
toy_id | toy |
---|---|
1 | hula hoop |
2 | balsa glider |
3 | toy soldiers |
4 | harmonica |
5 | baseball cards |
SELECT boys.boy, toys.toy
FROM boys
INNER JOIN
toys
ON boys.toy_id = toys.toy_id;
查询结果如下
boy | toy |
---|---|
Richie | hula hoop |
Beaver | balsa glider |
Davey | toy soldiers |
Bobby | baseball cards |
测试不相等性的内联接
我们可以找出每个男孩没有的玩具
SELECT boys.boy, toys.toy
FROM boys
INNER JOIN
toys
ON boys.toy_id <> toys.toy_id
ORDER BY boys.boy;
自然联接只有在联接的列在两张表中的名称都相同时才会有用。自然联接会识别出每个表里的相同名称并返回相符的记录。
子查询,是被另一个查询包围的查询,也可称为内层查询。
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc
NATURAL JOIN
my_contacts AS mc
WHERE jc.title IN
(
SELECT title
FROM job_listings
);
SELECT mc.first_name, mc.last_name,
(SELECT state
FROM zip_code
WHERE mc.zip_code = zip_code) AS state
FROM my_contacts mc;
如果子查询可以独立运行且不会引用外层查询的任何结果,即称为非关联子查询。
SELECT mc.first_name, mc.last_name, jc.salary
FROM
my_contacts AS mc NATURAL JOIN job_current AS jc
WHERE
jc.salary > (SELECT jc.salary
FROM my_contacts mc NATURAL JOIN job_current jc
WHERE email = '[email protected]');
IN, NOT IN
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURAL JOIN my_contacts AS mc
WHERE jc.title IN (SELECT title FROM job_listings);
内层查询的解析需要依赖外层查询的结果。
SELECT mc.first_name, mc.last_name
FROM my_contacts AS mc
WHERE
3 = (
SELECT COUNT(*) FROM contacts_interest
WHERE contact_id = mc.contact_id
);
关联子查询的用法,是找出所有外层查询结果里不存在于关联表里的记录。
EXISTS, NOT EXISTS
任何子查询能实现的事都能以相同类型的联接来实现。
LEFT OUTER JOIN 会匹配左表中的每一行及右表中符合条件的行
SELECT g.girl, t.toy
FROM girls g
LEFT OUTER JOIN toys t
ON g.toy_id = t.toy_id;
差别是:外连接一定会提供数据行,无论该行能否再另一个表中找出相匹配的行。
左外联接的结果集中的NULL 表示右表中没有找到左边中相符的记录。
右外联接与左外联接完全一样,除了它是用右表与左表比对。
表示它是引用同一张表内另一列的键。自引用外键是个处于其他目的而用于同一张表的主键。
改用自联接(self-join)来模拟联接两张表的效果,自联接能把单一表当成两张具有完全相同的信息的表来进行查询。
SELECT c1.name, c2.name AS boss
FROM clown_info c1
INNER JOIN clown_info c2
ON c1.boss_id = c2.id;
UNION只能接受一个ORDER BY且必须位于语句末端。这是因为UNION已经把多个SELECT语句的查询结果串联起来并分组了。
UNION ALL会返回列的所有内容。
CREATE TABLE my_union AS
SELECT title FROM job_current UNION
SELECT title FROM job_desired
UNION SELECT title FROM job_listings;
INTERSECT交集
只会返回同时在第一个与第二个查询中的列。
EXCEPT差集返回只出现在第一个查询,而不在第二个查询中的列。
可使用INNER JOIN替代包含子查询的WHERE子句。
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURAL JOIN my_contacts AS mc
WHERE jc.title IN (SELECT title FROM job_listings);
转换为
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURAL JOIN my_contacts AS mc
INNER JOIN job_listings jl
ON jc.title = jl.title;
SELECT c1.name,c2.name AS boss
FROM clown_info c1
INNER JOIN clown_info c2
ON c1.boss_id = c2.id
变身后
SELECT c1.name,
(SELECT name FROM clown_info
WHERE c1.boss_id = id) AS boss
FROM clown_info c1;
CHECK约束限定允许插入某个列的值。它与WHERE子句都使用相同的条件表达式。
CREATE TABLE piggy_bank
(
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
coin CHAR(1) CHECK (coin IN ('P', 'N', 'D', 'Q'))
)
MYSQL里,无法以CHECK强化数据完整性。
ALTER TABLE my_contacts
ADD CONSTRAINT CHECK gender IN ('M', 'F');
文件可能被修改,把查询存储在数据库内才是更好的方式。
CREATE VIEW web_designers AS
SELECT mc.first_name, mc.last_name, mc.phone, mc.email
FROM my_contacts mc
NATURAL JOIN job_desired jd
WHERE jd.title = 'Web Designer';
查看视图的内容,可以把它想象成一张表
SELECT * FROM web_designers;
视图也被称为虚拟表
视图的好处:
可更新视图就是可以改变底层表的视图。
带有CHECK OPTION的视图,如过不符合WHERE条i就,插入或者更新操作即被拒绝。
视图使用完毕:DROP VIEW pb_dimes;
事务是一群可完成一组工作的SQL语句。
在事务过程中,如果所有步骤无法不受干扰地完成,则不该完成任何单一步骤。
ACID:
START TRANSACTION;
COMMIT;
ROLLBACK;
`GRANT SELECT ON clown_info TO elsie;
REVOKE DELETE ON chores FROM sleepy CASCADE;
都回被撤销
REVOKE DELETE ON chores FROM sleepy RESTRICT;
两方权限被保留,root用户会收到错误提示。
CREATE ROLE date_entry;
GRANT SELECT, INSERT ON some_table TO date_entry;
GRANT date_entry TO doc;
DROP ROLE date_entry;
管理员权限