下载了书中提供的sqlite数据库内容。
runoob提供的sqlite教程
sqlite3 tysql.sqlite
.help
.show 配置输出样式
.schema 显示create语句
您可以使用下列的点命令来格式化输出
sqlite>.header on
sqlite>.mode column
sqlite>.timer on
sqlite>
更多mode样式参考文章
主表中保存数据库表的关键信息,并把它命名为 sqlite_master。
查看sqlite_master的create语句。
sqlite> .schema sqlite_master
CREATE TABLE sqlite_master (
type text,
name text,
tbl_name text,
rootpage integer,
sql text
);
查看sqlite_master中所有的table(书中例子)
sqlite> select * from sqlite_master where type="table";
type name tbl_name rootpage sql
---------- ---------- ---------- ---------- --------------------------------------------------------------------------------------------------------------------
table Customers Customers 2 CREATE TABLE Customers
(
cust_id char(10) NOT NULL ,
cust_name char(50) NOT NULL ,
cust_address char(50) NULL ,
cust_city char(50) NULL ,
cust_state char(5) NULL ,
cust_zip char(10) NULL ,
cust_country char(50) NULL ,
cust_contact char(50) NULL ,
cust_email char(255) NULL ,
PRIMARY KE
table OrderItems OrderItems 4 CREATE TABLE OrderItems
(
order_num int NOT NULL ,
order_item int NOT NULL ,
prod_id char(10) NOT NULL ,
quantity int NOT NULL ,
item_price decimal(8,2) NOT NULL ,
PRIMARY KEY (or
table Orders Orders 7 CREATE TABLE Orders
(
order_num int NOT NULL ,
order_date datetime NOT NULL ,
cust_id char(10) NOT NULL ,
PRIMARY KEY (order_num) ,
FOREIGN KEY (cust_id) REFERENCES Customers (cust_id)
)
table Products Products 10 CREATE TABLE Products
(
prod_id char(10) NOT NULL ,
vend_id char(10) NOT NULL ,
prod_name char(255) NOT NULL ,
prod_price decimal(8,2) NOT NULL ,
prod_desc text NULL ,
PRIMARY KEY (prod_id) ,
FOREIGN KEY (vend_id) REFERENCES Vendors (vend_id)
)
table Vendors Vendors 12 CREATE TABLE Vendors
(
vend_id char(10) NOT NULL ,
vend_name char(50) NOT NULL ,
vend_address char(50) NULL ,
vend_city char(50) NULL ,
vend_state char(5) NULL ,
vend_zip char(10) NULL ,
vend_country char(50) NULL ,
PRIMARY KEY (vend_id)
)
Run Time: real 0.001 user 0.000166 sys 0.000119
sqlite_mater中还存储了什么?
sqlite> SELECT DISTINCT type FROM sqlite_master;
type
----------
table
index
Run Time: real 0.002 user 0.000127 sys 0.000171
sqlite> select * from sqlite_master where type="index";
type name tbl_name rootpage sql
---------- ---------------------------- ---------- ---------- ----------
index sqlite_autoindex_Customers_1 Customers 3
index sqlite_autoindex_OrderItems_ OrderItems 5
index sqlite_autoindex_Orders_1 Orders 9
index sqlite_autoindex_Products_1 Products 11
index sqlite_autoindex_Vendors_1 Vendors 13
Run Time: real 0.000 user 0.000116 sys 0.000068
假想 婉拒经销商 订单录入系统
销售产品的供应商
sqlite> .schema Vendors
CREATE TABLE Vendors
(
vend_id char(10) NOT NULL ,
vend_name char(50) NOT NULL ,
vend_address char(50) NULL ,
vend_city char(50) NULL ,
vend_state char(5) NULL ,
vend_zip char(10) NULL ,
vend_country char(50) NULL ,
PRIMARY KEY (vend_id)
);
所在城市,所在州(state),邮编(zip)
产品目录
sqlite> .schema Products
CREATE TABLE Products
(
prod_id char(10) NOT NULL ,
vend_id char(10) NOT NULL ,
prod_name char(255) NOT NULL ,
prod_price decimal(8,2) NOT NULL ,
prod_desc text NULL ,
PRIMARY KEY (prod_id) ,
FOREIGN KEY (vend_id) REFERENCES Vendors (vend_id)
);
外键
顾客信息
sqlite> .schema customers
CREATE TABLE Customers
(
cust_id char(10) NOT NULL ,
cust_name char(50) NOT NULL ,
cust_address char(50) NULL ,
cust_city char(50) NULL ,
cust_state char(5) NULL ,
cust_zip char(10) NULL ,
cust_country char(50) NULL ,
cust_contact char(50) NULL ,
cust_email char(255) NULL ,
PRIMARY KEY (cust_id)
);
顾客订单(不是订单细节)
sqlite> .schema Orders
CREATE TABLE Orders
(
order_num int NOT NULL ,
order_date datetime NOT NULL ,
cust_id char(10) NOT NULL ,
PRIMARY KEY (order_num) ,
FOREIGN KEY (cust_id) REFERENCES Customers (cust_id)
);
主键:order_num 订单的唯一编号
外键:cust_id
每个订单中的实际物品,每个订单的每个物品一行。
sqlite> .schema OrderItems
CREATE TABLE OrderItems
(
order_num int NOT NULL ,
order_item int NOT NULL ,
prod_id char(10) NOT NULL ,
quantity int NOT NULL ,
item_price decimal(8,2) NOT NULL ,
PRIMARY KEY (order_num, order_item) ,
FOREIGN KEY (order_num) REFERENCES Orders (order_num) ,
FOREIGN KEY (prod_id) REFERENCES Products (prod_id)
);
order_item 订单的物品号(订单内的顺序)
主键:order_num, order_item
外键:order_num, prod_id
数据库
表 table
列 column vs 字段filed
行 row
主键 primary key
外键 foreign key(第12课)
SQL structured query language
查询 query
结果集 result set
* 通配符
distinct用法 不能部分使用
top 5或者limit 5
注释的方法 ①-- ②# ③/**/
子句(clause),有些子句是必须的,有些子句是可选的。
order by子句的位置
通过非选择列进行排序也是可以的
按列位置排序
排序方向desc asc
where子句操作符
= < <= > >= != <> !> !<
BETWEEN AND
IS NULL
逻辑操作符
AND OR 优先级顺序
IN 功能与OR相当
谓词(predicate)是什么意思?
%可以匹配0个,1个或多个字符。
_只匹配1个字符,不能多也不能少。
[]用来指定一个字符集,匹配1个字符
否定前缀字符^
sqlite不支持
只有微软的Access和SQL Server支持集合。
一般消耗更长的处理时间
field与column一样意思,用于计算字段时通常使用计算字段。
拼接字段,sqlite使用的是||。(另外一种是+)
函数带来的问题,不具有可移植性
LEFT() RIGHT() (sqlite不支持)
LENGTH()
UPPER() LOWER()
TRIM() LTRIM() RTRIM()
SOUNDEX() (sqlite不支持)
可移植性最差!
ABS()
COS() SIN() TAN()
EXP()
PI() (sqlite不支持)
SQRT()
函数 | 单个列 | * | 计算项目 | 忽略NULL | DISTINCT |
---|---|---|---|---|---|
AVG() | √ | √ | 是 | 可以 | |
COUNT() | √ | √ | √ | 是;当使用*时:否 | 不可用于* |
MAX() | √ | √ | 是 | 可以,但没意义 | |
MIN() | √ | √ | 是 | 可以,但没意义 | |
SUM() | √ | √ | 是 |
只能用于单个列
忽略NULL
COUNT(*) 包含null
COUNT(column) 忽略NULL
对非数值,返回排序的最后一行
忽略NULL
对非数值,返回排序的最前面一行
忽略NULL
使用算术操作符,计算多个列
忽略NULL
ALL默认
DISTINCT
##GROUP BY的一些重要规定。
GROUP BY子句可包含任意数目的列,因为可以嵌套???(嵌套是指同时跟着多个列吗?)
GROUP BY子句中列出的每一列都必须是检索列或者有效的表达式(不能是聚集函数),如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式,不能使用别名。
除聚集计算语句外,SELECT语句中的每一列都必须在GROUP BY子句中给出。
以下例子证明了两点……①可以使用别名 ②SELECT语句中的prod_price就不是聚集计算并且没有在GROUP BY子句中,其实是可以的 ,只是正确与否不能保证,在MY SQL中测试过,会取该组的第一个。
sqlite> SELECT
COUNT(*),
prod_price,
prod_price+1 as aa
FROM
Products
GROUP BY
aa; ...> ...> ...> ...> ...> ...> ...>
COUNT(*) prod_price aa
---------- ---------- ----------
3 3.49 4.49
1 4.99 5.99
1 5.99 6.99
1 8.99 9.99
2 9.49 10.49
1 11.99 12.99
如果分组列中包含具有NULL值的行,则NULL作为单独一个分组返回。
GROUP BY子句必须位于WHERE子句之后,ORDER BY之前。
WHERE过滤的是行而不是分组,WHERE没有分组的概念。作用于分组之前进行过滤,即WHERE排除的行是不包含在分组中的。
HAVING过滤分组,作用在分组之后进行过滤。
结合WHERE column IN(子查询的结果)
子查询的SELECT语句只能查询单个列。
sqlite> SELECT
cust_id,
cust_name,
(SELECT
COUNT(*)
FROM
Orders
WHERE
Orders.cust_id == Customers.cust_id) as orders
FROM
Customers
ORDER BY
cust_name; ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...>
cust_id cust_name orders
---------- ---------- ----------
1000000003 Fun4All 1
1000000004 Fun4All 1
1000000002 Kids Place 0
1000000005 The Toy St 1
1000000001 Village To 2
Run Time: real 0.000 user 0.000155 sys 0.000062
注意在此例子中,子查询对每个顾客执行了一次,共执行了5次。
并不是最有效率的方式。
SQL最强大的功能之一
避免相同的数据多次出现——关系数据库设计的基础。
把信息分解成多个表,一类数据一个表。通过某些共同的值相互关联。——关系数据库。
将存储在多个表中的信息,使用一条SELECT语句检索出来。
联结不是物理实体,在实际的数据库表中并不存在。
指定要联结的表和关联他们的方式。
**笛卡尔积:**没有联结条件的表,行数是各表行数的乘积。
**叉联结(cross join):**返回笛卡尔积的联结。
也叫等值联结
联结条件使用ON子句
使用别名,区分多个自己
???没看懂什么是自然联结
sqlite只支持LEFT OUTER JOIN不支持RIGHT OUTER JOIN
LEFT OUTER JOIN和RIGHT OUTER JOIN可以通过交换顺序互相转化
只有少量数据库支持FULL OUTER JOIN.
UNION操作符
多个查询作为一个结果。
两种情况:
UNION中的每个查询必须包含相同的列,表达式或聚集函数(不需要相同的顺序)
UNION:重复的行会被自动取消
UNION ALL:返回所有的匹配行(包括重复)
UNION与多个WHERE相同,UNION ALL完成了多个WHERE不能完成的工作。
一条ORDER BY子句,对所有SELECT语句排序。
插入的方式:
插入完整的行
插入行的一部分
插入某些查询的结果
优点:语法简单
缺点:不安全,高度依赖表中列的定义次序,依赖于容易获得的次序信息。表结构改变后,可能次序信息改变。
sqlite> INSERT INTO
Customers
VALUES(
'1000000006',
'Toy Land',
'123 Any Street',
'New York',
'NY',
'111111',
'USA',
NULL,
NULL); ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...>
Run Time: real 0.013 user 0.000297 sys 0.003732
sqlite> SELECT * FROM Customers;
cust_id cust_name cust_address cust_city cust_state cust_zip cust_country cust_contact cust_email
---------- ------------ -------------- ---------- ---------- ---------- ------------ ------------ ---------------------
1000000001 Village Toys 200 Maple Lane Detroit MI 44444 USA John Smith [email protected]
1000000002 Kids Place 333 South Lake Columbus OH 43333 USA Michelle Gre
1000000003 Fun4All 1 Sunny Place Muncie IN 42222 USA Jim Jones [email protected]
1000000004 Fun4All 829 Riverside Phoenix AZ 88888 USA Denise L. St [email protected]
1000000005 The Toy Stor 4545 53rd Stre Chicago IL 54545 USA Kim Howard
1000000006 Toy Land 123 Any Street New York NY 111111 USA
Run Time: real 0.001 user 0.000155 sys 0.000142
提供了列名,不依赖实际次序,即使结构改变,依然能够工作。
sqlite> INSERT INTO
Customers(
cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES(
'1000000007',
'Toy Land2',
'123 Any Street',
'New York',
'NY',
'111111',
'USA',
NULL,
NULL); ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...>
Run Time: real 0.013 user 0.000203 sys 0.003505
sqlite> SELECT * FROM Customers;
cust_id cust_name cust_address cust_city cust_state cust_zip cust_country cust_contact cust_email
---------- ------------ -------------- ---------- ---------- ---------- ------------ ------------ ---------------------
1000000001 Village Toys 200 Maple Lane Detroit MI 44444 USA John Smith [email protected]
1000000002 Kids Place 333 South Lake Columbus OH 43333 USA Michelle Gre
1000000003 Fun4All 1 Sunny Place Muncie IN 42222 USA Jim Jones [email protected]
1000000004 Fun4All 829 Riverside Phoenix AZ 88888 USA Denise L. St [email protected]
1000000005 The Toy Stor 4545 53rd Stre Chicago IL 54545 USA Kim Howard
1000000006 Toy Land 123 Any Street New York NY 111111 USA
1000000007 Toy Land2 123 Any Street New York NY 111111 USA
Run Time: real 0.000 user 0.000166 sys 0.000153
如果不使用列名,需要给每个列一个值;如果提供列名,必须给列出的列一个值。
省略不提供值的列,前提:
INSERT 语句+SELECT 语句
SELECT语句的列名不重要,重要的是顺序。
SELECT语句可以使用WHERE子句,过滤插入的数据。
SELECT *
INTO CustCopy
FROM Customers;
不同数据库语法不同。
UPDATE
DELETE
TRUNCATE 删除所有行,更快,不记录变动
CREATE TABLE
NOT NULL或者NULL
指定默认值DEFAULT
ALTER TABLE(避免给有数据的修改,都允许增加,有的不允许删改,不同数据库不同,请参阅具体的DBMS文档)。
复杂的表结构更改——手动删除,建新表,复制数据。
视图是虚拟的表,与包含数据的表不一样,视图是包含使用动态检索数据的查询。
不同数据库不同支持情况。
1.联结
sqlite> SELECT
cust_name,
cust_contact,
prod_id
FROM
Customers,
Orders,
OrderItems
WHERE
Customers.cust_id = Orders.cust_id
AND
OrderItems.order_num = Orders.order_num; ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...>
cust_name cust_contact prod_id
------------ ------------ ----------
Village Toys John Smith BR01
Village Toys John Smith BR03
Fun4All Jim Jones BR01
Fun4All Jim Jones BR02
Fun4All Jim Jones BR03
Fun4All Denise L. St BR03
Fun4All Denise L. St BNBG01
Fun4All Denise L. St BNBG02
Fun4All Denise L. St BNBG03
Fun4All Denise L. St RGAN01
The Toy Stor Kim Howard RGAN01
The Toy Stor Kim Howard BR03
The Toy Stor Kim Howard BNBG01
The Toy Stor Kim Howard BNBG02
The Toy Stor Kim Howard BNBG03
Village Toys John Smith BNBG01
Village Toys John Smith BNBG02
Village Toys John Smith BNBG03
Run Time: real 0.001 user 0.000310 sys 0.000286
2.创建视图
sqlite> CREATE VIEW
ProductCustomers AS
SELECT
cust_name,
cust_contact,
prod_id
FROM
Customers,
Orders,
OrderItems
WHERE
Customers.cust_id = Orders.cust_id
AND
OrderItems.order_num = Orders.order_num; ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...> ...>
Run Time: real 0.006 user 0.000277 sys 0.001878
3.通过sqlite_master表确认已经创建成功
sqlite> SELECT * FROM sqlite_master WHERE type = 'view';
type name tbl_name rootpage sql
---------- ---------------- ---------------- ---------- --------------------------------------------------------------------------------------------------------------------
view ProductCustomers ProductCustomers 0 CREATE VIEW ProductCustomers AS
SELECT
cust_name,
cust_contact,
prod_id
FROM
Customers,
Orders,
OrderItems
WHERE
Customers.cust_id = Orders.cust_id
AND
OrderItems.order_num = Orders.order_num
Run Time: real 0.000 user 0.000123 sys 0.000105
4.从view中查询数据
sqlite> SELECT
cust_name,
cust_contact
FROM
ProductCustomers
WHERE
prod_id = 'RGAN01'; ...> ...> ...> ...> ...> ...>
cust_name cust_contact
---------- ------------------
Fun4All Denise L. Stephens
The Toy St Kim Howard
Run Time: real 0.000 user 0.000305 sys 0.000084
sqlite>
比如拼接字符串
比如过滤email为空的客户
从视图检索数据时,如果使用了一条WHERE子句,则两组子句(一组在视图中,一组是传递给视图的)将自动组合。
为以后使用而保存的一条或多条SQL语句。
Microsoft Access和SQLite不支持存储过程。
???为了封装
存储过程以编译过的形式存储
几个术语:
事务(transaction)
回退(rollback)
提交(commit)
保留点(savepoint) 事务处理中设置的临时占位符(placeholder)
可以回退哪些语句?
可以:INSERT UPDATE DELETE
SELECT不能且没必要
不能:CREATE DROP 可以使用这些语句但是进行回退时,这些操作不撤销。
???以后再看
结果集(result set) SQL查询所检索出的结果
游标(cursor)是一个存储在DBMS服务器上的数据库查询,不是一条SELECT语句,而是被该语句检索出来的结果集。可以滚动或浏览其中的数据。
不同DBMS支持不同的游标选项和特性。
Microsoft Access不支持游标。
SQLite支持的游标成为步骤(step),语法可能完全不同。
##21.2 使用游标
DECLARE
OPEN CURSOR
FETCH
CLOSE
管理如何插入或处理数据库数据的规则。
条件:
防止意外删除:不允许删除在另一个表中具有关联行的行。
有的DBMS支持级联删除(cascading delete)特性。
类似主键,但有如下区别:
保证满足条件,常见用途:
索引用来排序数据以加快搜索和排序操作的速度。
使索引有用的因素是:恰当的排序。
索引改善检索操作的性能,但降低了杀入修改删除的性能,因为执行这些操作时DBMS必须动态地更新索引。
索引数据可能要占据大量的存储空间。
并非所有数据都适合做索引。对取值更多的数据做索引得到更多好处。
索引用于数据过滤和数据排序。???
可以在索引中定义多个列
索引必须唯一命名
CREATE INDEX
索引会随着数据增加改变而改变,变得不够效率,应定期检查。
触发器是特殊的存储过程,在特定的数据库活动放生时自动执行。
区别:存储过程是简单的存储SQL语句,触发器与单个表相关联。
触发器具有权限:触发它的操作(INSERT, UPDATE, DELETE)中的所有数据。
常见用途:
开放数据库连接(Open Database Connectivity,ODBC)是为解决异构数据库间的数据共享而产生的,现已成为WOSA(The Windows Open System Architecture ),Windows开放系统体系结构)的主要部分和基于Windows环境的一种数据库访问接口标准
ODBC日期
#参考资料
runoob教程
sqlite时间和日期函数
sqlite字符串和数值处理函数
sqlite官方文档
字符串
TRIM() LTRIM() RTRIM()