1、条件查询WHERE
①比较查询
SELECT `emp_no`, `from_date`, `salary` FROM `salaries` WHERE `salary` = 60117;
SELECT `emp_no`, `from_date`, `salary` FROM `salaries` WHERE `salary` < 60117;
//--------------------------
SELECT `emp_no`, `from_date`, `salary` FROM `salaries` WHERE `salary` BETWEEN 60117 AND 60300;
-- 相当于
SELECT `emp_no`, `from_date`, `salary` FROM `salaries` WHERE `salary` <= 60300 AND `salary` >= 60117;
- 找到对应表–>通过where子句查询出符合指定条件的记录,表中该字段的所有记录都会被比较,然后再选取出SELECT语句指定的列
- between and:
- 包含临界值 []: 注意不同的数据库是不同的处理方法,对于mysql,是双闭区间[]
- 两个临界值不要调换顺序
- 对字符串使用不等号时需注意:数据库对字符串型的数据原则上使用字典顺序排序, 比如1, 11, 123, 2, 22, 23, 4, 5。 这时比2大的字符应该是:22, 23, 4, 5
- 不能对NULL使用比较运算符,只能用IS NULL、IS NOT NULL之类判定
②逻辑操作符
可以将多个条件组合起来,用于连接条件表达式
AND & OR & IN & NOT
- AND
- OR
or这样的语句不允许在生产环境中出现,应该在前端缓存。
>#条件必须全部满足
SELECT `emp_no`, `from_date`, `salary` FROM `salaries`
WHERE `from_date` = "2000-01-01" AND `salary` < 40000;
> ***
>#条件满足其中之一就可:结果包含了 "2000-01-01"和"1995-01-01"
SELECT distinct `from_date` FROM `salaries`
WHERE `from_date` = "2000-01-01" OR `from_date` = "1995-01-01";
> ***
> #in与or的意义相同
SELECT distinct `from_date` FROM `salaries`
WHERE `from_date` in ("2000-01-01", "1995-01-01");
> ***
> #not表示对条件取反
SELECT distinct `from_date` FROM `salaries`
WHERE `from_date` not in ("2000-01-01", "1995-01-01");
- AND & OR的计算次序
SELECT row_name FROM table_name WHERE row_name = 值1 OR row_name=值2 AND row_name1 > 值3 ;
where子句中可以用任意个AND和OR来组织过滤条件,但是AND的优先级更高,因此此句相当于SELECT row_name FROM table_name WHERE row_name = 值1 OR (row_name=值2 AND row_name1 > 值3)。
在where子句中使用圆括号:因为圆括号具有比AND和OR操作符高的计算次序,DBMS会先过滤()内的条件。因此:任何时候使用具有AND和OR操作符的where子句,都应该使用()明确分组操作符,不要依赖默认计算次序,使用()没有什么坏处,它能消除歧义。
- 总结:
- 优先级:()>AND>OR
- 当AND和OR结合起来用的时候最好用()指明优先级
逻辑操作符中的NULL
- SQL中的逻辑运算包含:真、假、不确定这三种逻辑。SQL被称为三值逻辑。
- 三值逻辑中的AND与OR的真值表。
NOT
- WHERE中的NOT子句有且只有一个功能,就是否定它之后的所有的任何条件 MYSQL支持使用NOT对IN,BETWEEN和EXISTS子句取反,这与多数其他DBMS允许使用NOT对各种条件取反有很大的差别。
- NOT不能单独使用,必须和其他查询条件组合起来使用。表示对条件取反。
- IN更清楚更直观
- 使用IN时,计算的次序更加容易管理
- IN操作符比OR操作符清单执行更快
- IN的最大优点是可以包含其他SELECT语句,使得能够更动态的建立WHERE子句。
- in列表的值类型必须一致或兼容
- in列表中不支持通配符
③使用like通配符
SELECT `emp_no`, `first_name` FROM `employees` WHERE `first_name` LIKE 'Chri%';
SELECT `emp_no`, `first_name` FROM `employees` WHERE `first_name` LIKE '%ri%';
SELECT `emp_no`, `first_name` FROM `employees` WHERE `first_name` LIKE 'C%el'; -- 用得少
SELECT `emp_no`, `first_name` FROM `employees` WHERE `first_name` LIKE '_ristine';
- 特点:
- 一般和通配符搭配使用
- 通配符:
- % 任意多个字符,包含0个字符
- _ 任意单个字符
- 使用通配符的技巧:
- 不要过度使用通配符,如果其他操作符能够达到相同的目的,应该使用其他通配符。
- 在确实需要使用通配符的时候,除非决定有必要,否则不要把它们用在搜索模式的最开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
- 总结语法:
- select 查询列表 from 表明 where 筛选条件;
- 模糊查询
- like, between and, in, is null/ is not null
④空值检查IS NULL
>SELECT `cust_id` FROM `customers` WHERE `cust_email` IS NULL;
> ***
>SELECT `cust_id` FROM `customers` WHERE `cust_email` IS NOT NULL;
2、处理查询结果
存储在数据库表中的数据一般不是应用程序需要的格式,一般需要对结果进行拼接、大小写转换、计算总和等处理。
再数据库服务器上面完成这些操作比在客户机中完成要快很多,因为DBMS是设计来快速有效的完成这种处理的.
计算字段并不实际存在于数据库表中,计算字段是运行时在select语句内创建的。
① 拼接字段
SELECT CONCAT(
vend_name
, ‘(’,vend_country
, ‘)’) FROMvendors
ORDER BYvend_name
;SELECT CONCAT(RTRIM(
vend_name
), ‘(’, LTRIM(vend_country
), ‘)’) AS vend_title FROMvendors
ORDER BYvend_name
;
注意:多数DBMS使用+或者||来实现拼接,MySQL使用Concat()函数来实现。
② 进行算术运算±*/
包含NULL的运算,其结果也是NULL
SELECT
prod_id
,quantity
,item_price
,quantity
*item_price
AS ‘单价’ FROMorderitems
WHEREorder_num
= 20005;
+的作用:运算符
SELECT 100+90; 两个操作数都是数值型,则做加法运算
SELECT “100”+90; 如果其中一方为字符型,试图将字符型数值转换成数值型,如果转换成功,则做加法运算
SELECT “jo”+90; 如果转换失败,则将字符型数值转换成0
SELECT NULL + 10; 只要其中有一方为null,那么结果一定是null
③IFNULL&ISNULL
SELECT IFNULL(
cust_email
, 0),cust_email
FROMcustomers
;
SELECT ISNULL(cust_email
),cust_email
FROMcustomers
;
- ifnull (
字段
, newValue1):如果所查询的字段为空,则设置为newValue1
④ 文本处理函数
concat:连接
substr:截取子串
upper:大写
lower:小写
replace:替换
length:获取字节长度
trim:去除前后空格
lpad:左填充
rpad:右填充
instr:获取子串第一次出现的索引
⑤日期和时间处理函数
DATA()日期提取
SELECT
cust_id
,order_num
FROMorders
WHEREorder_date
= ‘2005-09-01’; #不建议使用SELECT
cust_id
,order_num
FROMorders
WHERE DATE(order_date
) = ‘2005-09-01’; #推荐使用
#DATE表示从order_date中提取yyyy-mm-dd#查询2005年9月的订单
SELECTcust_id
,order_num
FROMorders
WHERE YEAR(order_date
) = 2005 AND MONTH(order_date
) = 8;
可以获取指定的部分,年,月,日,小时,分钟,秒
SELECT YEAR(NOW()) 年, YEAR(‘1998-1-1’) AS ‘1998’;
SELECT YEAR(NOW()) 年, MONTH(NOW()) 月, DAY(NOW()) 日, HOUR(NOW()) 时, MINUTE(NOW()) 分, SECOND(NOW()) 秒;
SELECT MONTHNAME(NOW()) 月;
now:返回当前系统日期+时间
SELECT NOW();
curdate 返回当前系统日期,不包含时间
SELECT CURDATE();
curdate 返回当前系统时间,不包含时间日期
SELECT CURTIME();
str_to_data:将日期格式的字符转换成功指定格式的字符
SELECT STR_TO_DATE(‘1995-11-15’, ‘%Y-%c-%d’);
SELECT STR_TO_DATE(‘2002 11-15’, ‘%Y %c-%d’);
DATE_FORMAT:将日期转换成字符
SELECT DATE_FORMAT(NOW(), “%y年%m月%d日”);
日期和时间采用相应的数据类型和特殊的格式存储,以便能快速和有效的过滤,并且节省物理存储空间。一般来说,应用程序不使用用来存储日期和时间的格式,因此日期和时间函数总是被用来读取,统计和处理这些值。由于这个原因,日期和时间函数在MySQL语言中具有重要作用。
推荐,当指定插入删除或者过滤时,日期必须为yyyy-mm-dd[首选的日期格式]
⑥ 数据类型转换
varchar类型转换int类型或者浮点数
```sql
select * from gyzd_yysinfo order by cast(yysid as SIGNED INTEGER)
或者
select * from gyzd_yysinfo order by cast(yysid as UNSIGNED INTEGER)
浮点数
select cast("23333.3333" as decimal(9,2));
## 6.11、全文本搜索
并非所有的引擎的支持全文本搜索
两个最常用的引擎是:MyISAM(支持),InnoDB(不支持)
通配符和正则表达式的缺点:
性能:这两个匹配通常要求MySSQL尝试匹配表中所有行,而且这些搜索极少使用表索引--》查询耗时
明确控制:很难明确匹配什么和不匹配什么
等等
全文本搜索优点:
### 启动全文本搜索
```sql
>CREATE TABLE productnotes
(
note_id INT NOT NULL AUTO_INCREMENT,
prod_id CHAR(10) NOT NULL,
note_date DATETIME NOT NULL,
note_text TEXT NULL ,
PRIMARY KEY(note_id),
FULLTEXT(note_text)
) ENGINE=MYISAM;
- 全文本搜索[FULLTEXT(v1, v2)]
- FULLTEXT表示note_text可以作为全文本搜索的索引。
- 在定义之后,MySQL自动维护该索引。在增加,删除更新行时,索引随之自动更新
- 一般在创建表时启用全文本搜索。最好不要在导入数据时使用FULLTEXT
进行全文本搜索
SELECT
note_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(‘raBBit’); #不区分大小写
SELECTnote_text
FROMproductnotes
WHEREnote_text
LIKE ‘%raBBit%’;
LIKE VS 全文本搜索
- LIKE不对结果排序
- 全文本搜索对结果排序,等级高的先返回
- 全文本搜索根据索引搜索,相当快
#不包含raBBit的rank=0,包含的会根据文本算出等级
SELECTnote_text
, MATCH(note_text
) AGAINST(‘raBBit’) AS rank FROMproductnotes
;
查询扩展:增加找到相关匹配的机会
#查询所有提到anvils的注释
#1、全文本搜索:返回包含anvils
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(‘anvils’); #不区分大小写
#2、查询扩展:返回包含使用全文本扩展查询出来的句子中的某些单词的行
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(‘anvils’ WITH QUERY EXPANSION);
布尔文本搜索[不太懂]
即使没有fulltext索引也可以用,但是很慢
#查询包含heavy的所有行
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(‘heavy’ IN BOOLEAN MODE);
#至少包含rabbit或者heavy中的一个的行
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(‘rabbit heavy’ IN BOOLEAN MODE);
#包含rabbit heavy的行。是匹配rabbit heavy一个词
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(’“rabbit heavy”’ IN BOOLEAN MODE);
#查询包含heavy但是不包含任意以extre开始的词的行
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(‘heavy -extre*’ IN BOOLEAN MODE);
SELECTnote_text
FROMproductnotes
WHERE MATCH(note_text
) AGAINST(’+rabbit, +gua*’ IN BOOLEAN MODE);
事务
- 事务时需要在同一个处理单元中执行地一系列更新处理地集合。比如A给B转账。B增加地同时必须A减少。
- DBMS地事务遵循ACID特性,也就是
- 原子性[要么全部执行要么全部不执行]
- 一致性[如果事务不满组数据库提前设置地约束,比如NULL约束就会回滚,事务不会被执行
- 隔离性[事务之间不会相互嵌套;在事务没有提交之前,其他事务看不到新添加地记录地]]
- 持久性[事务结束后,DBMS能够保证该时间点的数据状态会被保存的特性,即使系统故障导致数据丢失hi,也能通过一定手段恢复。最常见的方法就是将事务的执行记录保存到磁盘等存储介质中,。当发生故障时,可以通过日志恢复到故障发生前的状态]
- 事务并没有标准地开始执行,随着DBMS地不同而不同。
–MySQL
START TRANSACTION;
-- 运动T恤的销售单价下调1000日元
UPDATE Product
SET sale_price = sale_price - 1000
WHERE product_name = '运动T恤';
-- T恤的销售单价上浮1000日元
UPDATE Product
SET sale_price = sale_price + 1000
WHERE product_name = 'T恤';
COMMIT;
–SQL Server, PostgreSQL
BEGIN TRANSACTION;
-- 运动T恤的销售单价下调1000日元
UPDATE Product
SET sale_price = sale_price - 1000
WHERE product_name = '运动T恤';
-- T恤的销售单价上浮1000日元
UPDATE Product
SET sale_price = sale_price + 1000
WHERE product_name = 'T恤';
COMMIT;
Oracle, DB2
-- 运动T恤的销售单价下调1000日元
UPDATE Product
SET sale_price = sale_price - 1000
WHERE product_name = '运动T恤';
-- T恤的销售单价上浮1000日元
UPDATE Product
SET sale_price = sale_price + 1000
WHERE product_name = 'T恤';
ROLLBACK;