SQL必知必会学习笔记

SQL笔记

  1. SQL(Structured Query Language)是一种专门用来与数据库沟通的语言

  2. 主键:一列或一组列,其值能够唯一标识表中的每一行表中的任何列都可以作为主键,但必须满足以下条件:

    • 任意两行都不具有相同的主键

    • 每一行都必须具有一个主键值(主键列不允许为NULL值)

    • 主键列中的值不允许修改或更新

    • 主键值不能重用(如果某行从表中删除,它的主键不能赋值给以后的新行)

检索数据

SELECT语句

  • 利用SELECT语句来检索表数据,至少需要给出两条信息—想要找什么,以及从什么地方找,下面是查找[QXYJ].[dbo].[JD_REGION]表中具有NAME,CODE属性的数据,查找结果只返回PROD_ID, PROD_NAME, PROD_PRICE 三列数据。使用*可以检索所有列。

    SELECT PROD_ID, PROD_NAME, PROD_PRICE
    FROM [MASTER].[DBO].[Products]
    

2019-11-28_195021.png

  • 利用DISTINCT关键字检索不同的值,加上DISTINCT关键字后将显示唯一值,相同的值只出现一次

    SELECT distinct VEND_ID
    FROM [MASTER].[DBO].[Products]
    

    2019-11-28_195605.png

  • 使用注释,–和#以及/**/都可以用于SQL语句的注释

排序检索数据

ORDER BY子句

使用SELECT语句的ORDER BY子句,根据需要排序检索出的数据

  • 使用ORDER BY子句可以对输出的检索数据进行排序,其中ORDER BY 子句必须放在SELECT语句的最后面,否则将报错

    SELECT PROD_NAME
    FROM [MASTER].[DBO].[PRODUCTS]
    ORDER BY PROD_NAME
    

    2019-11-28_200356.png

  • 当需要按多个列进行排序时,列名之间用,来隔开,下面是对列的结果先进行价格排序,然后按照名称排序,价格排序的优先级要大于名称排序,还可以根据列的相对位置来排序,下列语句中注释的语句是一样的排序效果

    SELECT PROD_ID,PROD_price,prod_name
    from [master].[dbo].[products]
    order by prod_price,prod_name
    # order by 2,3
    

    2019-11-28_201226.png

DESC关键字

通过DESC关键字(DESCENDING)来指定排序方向,排序默认是升序排序(从A到Z),可以使用DESC来降序排序,但是遇到多列排序的状况,DESC只对它前面的列名有效(只有一个有效),若需要对多个列名降序排序,需要在每个列名后添加DESC,如下列语句,DESC只对prod_price有效 (ASC是升序排序(ASCENDING))

select prod_id,prod_price,prod_name
from [master].[dbo].[products]
order by prod_price DESC, prod_name

2019-11-28_202123.png

过滤数据

WHERE子句

使用SELECT语句的WHERE子句来指定搜索条件,WHERE语句写在FROM子句后面,若碰到ORDER BY子句,ORDER BY子句是放在所有子句的最后面,如下面的搜索语句:

select prod_name,prod_price
from [master].[dbo].[products]
where prod_price=3.49

2019-11-28_202836.png

操作符 说明
= 等于
<> 不等于
!= 不等于
< 小于
<= 小于等于
!< 不小于
> 大于
>= 大于等于
!> 不大于
BETWEEN 在指定的两个值之间
IS NULL 为NULL值
select prod_name,prod_price 
from [master].[dbo].[Products]
where prod_price between 5 and 10

范围值检查:检查5到10之间的值,使用BETWEEN关键字

image-20191129092247521.png

高级数据过滤

使用组合WHERE子句来建立更强,更高级的搜索条件,并学习如何使用NOT和IN操作符

  • 组合WHERE子句:使用AND子句或OR子句来连接
SELECT PROD_ID,PROD_PRICE,PROD_NAME
FROM [MASTER].[DBO].[PRODUCTS]
WHERE VEND_ID='DLL01' AND PROD_PRICE<=4

上面是检索由供应商DLL01制造且价格小于等于4美元的所有产品的名称和价格

  • AND关键字是用来指示检索满足所有给定条件的行;OR关键字用来表示检索匹配任一给定条件的行。但是AND的优先级高于OR,当两个关键字组合使用时,应该考虑到优先级的问题。IN用来指定要匹配值的清单的关键字,功能与OR相当;NOT用来在WHERE子句中否定其后条件的关键字

  • 使用IN操作符:IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配,IN取一组由逗号分隔,括在圆括号中的合法值。

    select VEND_ID,prod_name,prod_price
    from [master].[dbo].[products]
    where vend_id in ('DLL01','BRS01')
    #where vend_id='DLL01' or vend_id='BRS01' 一样的效果
    ORDER BY PROD_NAME
    

    上面的检索语句是检索由供应商DLL01和BRS01制造的所有产品,IN操作符完成了与OR关键字相同的功能,因此上述代码中的or的结果与IN的结果是一样的

    image-20191129100645526.png

    • 使用IN操作符的优点:
      • IN操作符的语法更清楚,更直观
      • 在与其他AND和OR操作符组合使用IN时,求值顺序更容易管理
      • IN操作符一般比一组OR操作符执行速度更快
      • IN操作符能够包含其他的SELECT语句,能够更动态建立WHERE子句
  • NOT操作符:NOT只有一个功能,就是否定其后跟的任何条件,需要与其他操作符一起使用,NOT操作符与<>操作符的功能相似

    select vend_id,prod_name
    from [master].[dbo].[products]
    where not vend_id='DLL01'
    ORDER BY vend_id
    

    列出除DLL01之外的所有供应商制造的产品

image-20191129102010226.png

通配符过滤—%、_、[]、like

使用通配符(%_[]),以及 like操作符进行通配搜索

通配符搜索只能用于文本字段(字符串),非文本数据类型字段不能使用通配符搜索

  • like操作符

  • 百分号(%)通配符是最常使用的,在搜索中,%可以出现任意次数

    找出所有以词Fish起头的产品,搜索语句如下,检索语句将检索以Fish开头的词,%表示可以接受Fish之后的任意字符,不管有多少字符

    select prod_id,prod_name
    from [master].[dbo].[products]
    where prod_name like 'Fish%'
    

    image-20191129160355388.png

    通配符可以在任意位置使用,并且可以使用多个通配符,下面的搜索语句是匹配中间的特定字符的数据

    select prod_id,prod_name
    from [master].[dbo].[products]
    where prod_name like '%bean bag%'
    

    image-20191129160833064.png

  • 下划线(_)通配符:下划线的用途与%一样,但是它只能匹配单个字符

    select prod_id,prod_name
    from [master].[dbo].[products]
    where prod_name like '__ inch teddy bear'
    #上面是两个下划线
    

    上面的搜索语句中有两个下划线,因此匹配的字符都是两位数的,数字在字符串中每个数字都是代表了一个字符

    image-20191129161412584.png

  • 方括号([])通配符:用来指定一个字符集,它必须匹配指定位置的一个字符

    找出所有名字以J或M起头的联系人,[JM]匹配了方括号中的任意一个字符,并且它也只能匹配单个字符,注释的语句是用来匹配除J和M以外的任意字符起头的任意联系人名

    select cust_contact
    from [master].[dbo].[Customers]
    where cust_contact like '[JM]%'
    # where cust_contact like '[^JM]%'
    # where NOT cust_contact like '[JM]%'
    order by cust_contact
    

    image-20191129161944831.png

创建计算字段

当我们需要的数据并不是全部在一个表中时,需要从数据库中检索出转换、计算或格式化的数据。

计算字段并不实际存在于数据表中,而是在运行时在select 语句中创建的

  • 拼接字段:使用+将两个值连接到一起,连接后的字符在表中并不存在,其中的RTRIM函数是去除每个值的右边的空格,LTRIM是去掉字符串左边的空格,TRIM去除字符串左右两边的空格

    select RTRIM(vend_name) + '(' + RTRIM(vend_country) +')'
    from [master].[dbo].[Vendors]
    order by vend_name
    

    将vendors表中的两个列 vend_name和vend_country连接起来

    image-20191129163919563.png

    • 使用别名:给新计算列起一个名字,方便查看,使用AS关键字来给计算字段赋值别名

      select RTRIM(vend_name) + '(' + RTRIM(vend_country) +')' AS vend_title
      from [master].[dbo].[Vendors]
      order by vend_name
      

      image-20191129164509096.png

  • 执行算术计算:对检索的数据进行算术计算

    select order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price
    from [master].[dbo].[orderItems]
    where order_num=20008
    

    2020-05-03_173835.png

使用函数处理数据

函数 语法
提取字符串的组成部分 SQL Server和MySQL使用SUBSTRING();Oracle,PostgreSQL和SQLite使用SUBSTR()
数据类型转换 MySQL和SQL Server使用CONVERT();PostgreSQL使用CAST()
获取当前日期 SQL Server使用GETDATE();MySQL使用CURDATE();SQLite使用DATE()
函数 说明
LEFT() 返回字符串左边的字符
LENGTH()、LEN() 返回字符串的长度
LOWER() 将字符串转换为小写
LTRIM() 去掉字符串左边的空格
RIGHT() 返回字符串右边的字符
RTRIM() 去掉字符串右边的空格
SOUNDEX() 返回字符串的SOUNDEX值
UPPER() 将字符串转换为大写

SOUNDEX是一个将任何文本串转换为描述其语音表示的字母数字模式的算法

函数 说明
ABS() 返回一个数的绝对值
COS() 返回一个角度的余弦
EXP() 返回一个数的指数值
PI() 返回圆周率
SIN() 返回一个角度的正弦
SQRT() 返回一个数的平方根
TAN() 返回一个角度的正切

汇总数据

  • 聚集函数
函数 说明
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和
  1. AVG()函数

    AVG()函数是通过对表中行数进行计数并计算某列值之和,求得该列的平均值。AVG()函数可用来返回所有列的平均值,也可以用来返回特定列或行的平均值

    select AVG(prod_price) as avg_price
    from products
    #where vend_id='DLL01'
    

    返回的值是所有产品的平均价格

    image-20191202155152688.png

    若加上where筛选语句,就是返回的是DLL01产品的均值,若想获得多个列的平均值,就需要多次使用AVG()函数

    image-20191202155413208.png

  2. COUNT()函数

    COUNT()函数用于确定表中行的数目或符合特定条件的行的数目
    COUNT()函数有两种使用方式

  3. 使用COUNT(*)对表中行的数目进行计数,不管列中包含的是空值(NULL)还是非空值

select COUNT(*) AS num_cust
from customers

返回的是Customers表中顾客的总数,在这种用法中,不管行中各列都有什么值,都会进行计数

image-20191202160033237.png

  1. 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值
select COUNT(cust_email) as num_cust
from Customers

该使用方式只对具有电子邮件地址的客户计数

image-20191202160447076.png

  1. MAX()函数

    返回指定列的最大值,该函数要求指定列名

    select MAX(prod_price) AS max_price
    from products
    

    返回的是products表中最贵物品的价格

    image-20191202161154554.png

    注意:若是对非数值数据使用MAX(),MAX将返回该排序后的最后一行

  2. MIN()函数

    返回指定列的最小值,该函数要求指定列名

    select MIN(prod_price) AS min_price
    from products
    

    返回的是products表中最便宜物品的价格

    image-20191202161513958.png

  3. SUM()函数

    用来返回指定列值的总和

    select SUM(quantity) as items_ordered
    from OrderItems
    

    返回订单表中所有物品数量之和,可以添加where子句来查询某个物品订单的数量

    image-20191202162219658.png

    select SUM(item_price*quantity) as total_price
    from orderItems
    where order_num=20005
    

    使用SUM()函数来合计计算值,返回order_num=20005的物品的总的订单金额

    image-20191202162506482.png

  • 聚集不同的值,指定DISTINCT 参数

    select AVG(DISTINCT prod_price) as avg_price
    from products
    where vend_id='DLL01'
    

    排除相同值之后的平均价格,DISTINCT不能用于COUNT(*),只能用于COUNT(column)

    image-20191202163126783.png

  • 组合聚集函数

    select COUNT(*) as num_items,
    	   MIN(prod_price) as price_min,
    	   MAX(prod_price) as price_max,
    	   AVG(prod_price) as price_avg
    from products
    

    执行多个聚集函数,返回不同的结果

    image-20191202163801497.png

分组数据

  • 数据分组

    select COUNT(*) as num_prods
    from products
    where vend_id='DLL01'
    

    image-20191202165946381.png

    上面的只是显示一个供应商提供的产品数量,若需要返回每个供应商提供的产品数目,则需要用到分组。使用分组可以将数据分为多个逻辑组 ,对每个组进行聚集计算

  • 创建分组

    select vend_id, COUNT(*) as num_prods
    from products
    group by vend_id
    

    group by 子句指示DBMS按vend_id排序并分组数据,这就会对每个vend_id而不是整个表计算num_prods一次。

    使用了group by,就不必指定要计算和估值的每个组了,系统会自动完成;group by 子句指示DBMS分组数据,然后对每个组而不是整个结果集进行聚集

    image-20191202185716821.png

    使用group by 子句的一些重要规定:

    • group by 子句可以包含任意数目的列,因而可以对分组进行嵌套,更细致的进行数据分组
    • 在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)
    • group by子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在select中使用表达式,则必须在group by子句中指定相同的表达式,不能使用别名。
    • 大多数SQL不允许GROUP BY列带有长度可变的数据类型(如文本或注释字段)
    • 除聚集计算语句外,SELECT语句中的每一列都必须在group by子句中给出
    • 如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回,如果列中有多行NULL值,它们将分为一组
    • group by子句必须出现在where子句之后,order by子句之前
  • 过滤分组

    除了能用group by子句分组数据外,SQL还允许过滤分组,规定包括哪些分组,排除哪些分组。过滤分组使用的是HAVING子句而不是where子句。HAVING与where十分相似,唯一的差别是where是过滤行,而HAVING是过滤分组,并且HAVING支持WHERE所有的操作符

    select cust_id,COUNT(*) as orders
    from orders
    group by cust_id
    having COUNT(*)>=2
    

    上述代码过滤的是COUNT(*)>=2的那些分组

    image-20191202192255432.png

    • where和having语句的结合使用

      select vend_id,COUNT(*) as num_prods
      from products
      where prod_price>=4
      group by vend_id
      having COUNT(*)>=2
      

      通过where和having子句的结合使用来列出具有两个以上产品且其价格大于等于4的供应商。其中where是过滤所有prod_price>=4的行,然后根据vend_id进行分组,再使用having进行过滤

      image-20191202192729894.png

使用子查询

子查询:嵌套在其他查询中的查询

  • 利用子查询进行过滤

在数据库中查找订购物品RGAN01的所有顾客

  1. 检索包含物品RGAN01的所有订单的编号
  2. 检索具有前一步骤列出的订单编号的所有顾客的ID
  3. 检索前一步骤返回的所有顾客ID的顾客信息
  1. select order_num
    from orderItems
    where prod_id='RGAN01'
    

    将此处查询得到的结果用于下一步骤

    image-20191202194301221.png

  2. select cust_id
    from orders
    where order_num in (20007,20008)
    

    同样将此处查询的结果用于下一步骤,这里使用了IN操作符

    image-20191202194601140.png

  3. select cust_name,cust_contact
    from customers
    where cust_id in('1000000004','1000000005')
    

    得到最终的结果

    image-20191202194710818.png

  4. 使用子查询将三个查询语句结合在一起

    select cust_name,cust_contact
    from customers
    where cust_id in(select cust_id
    				 from orders
    				 where order_num in (select order_num
    									 from orderItems
    									 where 													 prod_id='RGAN01'))
    

    将得到一样的结果

    image-20191202195057447.png

    子查询只能查询单列,检索多个列将报错

  • 作为计算字段使用子查询

    查询customers表中每个顾客的订单总数

    1. 从customers表中检索顾客列表
    2. 对于检索的每个顾客,统计其在orders表中的订单数目
    select cust_name,cust_state,(select count(*)
                                from orders
                                where orders.cust_id=customers.cust_id) as orders
    from customers
    order by cust_name
    

    该子查询会对检索出的每个顾客执行一次,子查询一共执行了5次,因此查询了5个顾客

    image-20191203202417584.png

联结表

关系表:将信息根据类别拆分成多个表,一个类别一个表,避免了数据的冗余,各表通过某些共同的值相互关联。

  • 创建联结

    select vend_name,prod_name,prod_price
    from vendors,products
    where vendors.vend_id=products.vend_id
    
    /*这两个代码检索的结果是一样的*/
    select vend_name,prod_name.prod_price
    from vendors inner join products
    on vendors.vend_id=products.vend_id
    

    上述两个表的关系是以inner join指定的部分from子句,在使用这种语法时,联结条件用特定的on子句而不是用where子句,但传递的条件是与where子句是相同的。这种联结方式也被称为内联结

    与之前的搜索语句不通的是:搜索的列中,vend_name在vendors表中,而 prod_name,prod_price在products表中,from的是两个表 ,而且这 两个表用where子句来联结

    image-20191204165341436.png

  • 联结多个表

    select prod_name,vend_name,prod_price,quantity
    from orderitems,products,vendors
    where products.vend_id=vendors.vend_id
    and orderitems.prod_id=products.prod_id
    and order_num=20007
    

    这个例子是列出订单是20007的物品,这里定义了两个联结条件,最后的是过滤子句

    image-20191204172423749.png

  • 上一节中的子查询可以用联结表来代替

    select cust_name,cust_contact
    from customers
    where cust_id in (select cust_id
                     from orders
                     where order_num in (select order_num
                                        from orderitems
                                        where prod_id='RGAN01'))
    
    select cust_name,cust_contact
    from customers.orders,orderitems
    where customers,cust_id=orders.cust_id
    and orderitems.order_num=orders.order_num
    and prod_id='RGAN01'
    

    子查询与联结表查询得到的结果是一样的

    image-20191204173106546.png

创建高级联结

  • 使用表别名来联结表

列名的表示方法

select RTRIM(vend_name) + '('+RTRIM(vend_country)+')' as vend_title
from vendors
order by vend_name

表名的表示方法

select cust_name,cust_contact
from customers as C ,orders as O, orderitems as OI
where C.cust_id=O.cust_id
and OI.order_num=O.order.num
and prod_id='RGAN01'
  • 外联结

    许多联结将一个表中的行与另外一个表中的行进行关联,但在联结过程中还需要包含那些在相关表中没有关联的行,这种联结就称为外联结

    select customers.cust_id,orders.order_num
    from customers left outer join orders
    on customers.cust_id=orders.cust_id
    

    这里使用的是外联结,检索包括没有订单顾客在内的所有顾客,并使用customers表中的所有行

    在使用OUTER JOIN关键字时,必须使用RIGHT或者LEFT关键字来指定所有行的表(RIGHT指出的是OUTER JOIN右边的表,LEFT指出的是OUTER JOIN左边的表)

    image-20191204193839093.png

    内联结检索的是所有顾客及其订单

    select customers.cust_id,orders.order_num
    from customers inner join orders
    on customers.cust_id=orders.cust_id
    

    image-20191204193933399.png

组合查询

使用组合查询的两种情况:

  1. 在一个查询中从不同的表返回结构数据
  2. 对一个表执行多个查询,按一个查询返回数据
  • 创建组合查询,使用UNION关键字

    select cust_name,cust_contact,cust_email
    from customers
    where cust_state in ('IL','IN','MI')
    UNION
    /*UNION ALL*/   /*使用ALL的话将返回所有的行,重复的不会被过滤*/
    select cust_name,cust_contact,cust_email
    from customers
    where cust_name='Fun4All'
    
    select cust_name,cust_contact,cust_email
    from customers
    where cust_state in ('IL','IN','MI')
    or cust_name='Fun4All'
    

    上述两段代码检索的结果是一样的,顺序可能不同。对于一些复杂的过滤条件,使用UNION处理会更简单

    image-20191204195428387.png

    使用UNION规则:

    • UNION必须由两条或两条以上的select语句组成,语句之间用关键字UNION来分隔
    • UNION中的每个查询必须包含相同的列、表达式或聚集函数(列名最好以相同的次序列出,不然会造成重复)
    • 列数据类型必须兼容:类型不必完全相同,但是必须能够被转换
    • 若想使用order by进行排序,则该语句必须放在最后一个select语句中,并且只允许出现一次order by子句

插入数据

INSERT关键字用来将行插入到数据库表中,有几种插入方式:

  • 插入完整的行
  • 插入行的一部分
  • 插入某些查询的结果
  1. 插入完整的行
INSERT INTO Customers(cust_id,cust_name,cust_address,
                      cust_city,cust_state,cust_zip,
                     cust_country,cust_contact,cust_email)
values('1000000006','Tony Land','123 AAny Street',
 		'New York','NY','11111','USA',NULL,NULL)

插入的结果在最后一行,其中值需要与列名一一对应,列名不需要与原表的列名顺序一样,其中values中的值要完整,即使该值为NULL,但也可以省略

但是若原表在定义允许在INSERT操作中 省略某些列,则可以进行省略,但必须满足以下条件:

  • 该列定义为允许NULL值(无值或空值)
  • 在表定义中给出了默认值,若插入中没有值,则使用默认值

image-20191204201435047.png

  1. 插入检索的数据:可以将select语句中检索的结果插入到表中。(INSERT SELECT)

    INSERT INTO Customers(cust_id,cust_name,cust_address,
                          cust_city,cust_state,cust_zip,
                         cust_country,cust_contact,cust_email)
    select cust_id,cust_name,cust_address,cust_city,                  cust_state,cust_zip,cust_country,                           cust_contact,cust_email 
    from CustNew
    

    该例子是将CustNew中检索得到的结果插入到Customers中,在select中也可以使用where子句来过滤结果

  2. 从一个表复制到另一个表(SELECT INTO)

    INSERT SELECT 与SELECT INTO的区别:前者插入数据,后者导出数据

    select *
    into custCopy
    from customers
    

    上述代码是创建一个custCopy的新表,并把Customers表的整体内容复制到新表中,这里使用的是*通配符,因此是将所有内容都复制,可以选择只复制部分列

更新和删除数据

  • 更新数据:使用UPDATE来更新数据,更新可以选择更新表中的特定行还是更新表中的所有行

    基本上的update语句由三部分组成:

    • 要更行的表(使用update)
    • 列名和它们的新值(set来设置)
    • 确定要更新哪些行的过滤条件(where子句)
    • 改变多行时只需要使用一个set
    update customers
    set cust_email='[email protected]',
    	cust_state='china'
    where cust_id='1000000006'
    

    image-20191205202357748.png

    更新数据时尽量不要省略where子句,否则将会更新整个表

  • 删除数据

    删除数据有两种方法:

    • 将某列的值更新为NULL
    • 使用DELETE来删除数据
      1. 从表中删除特定的行
      2. 从表中删除所有的行
    /**删除cust_id为1000000005的cust_email值,更新为NULL也是删除*/
    update customers
    set cust_email=NULL
    where cust_id='1000000005'
    

    从customers表中删除一行

    delete from customers
    /*若没有where子句,则表中数据将全部删除*/
    where cust_id='1000000006'
    

创建表和操纵表

  • 创建表

使用create table关键字来创建表,必须给出以下信息:

  • 新表的名字,在关键字create table之后给出,新表名字不能与现有表名重复
  • 表列的名字和定义,用逗号隔开
  • 有的DBMS还要求指定表的位置
/*创建Products表*/
/*可以指定某列为NULL值,但是可以为NULL值的列不能作为主键*/
create table products(
	prod_id	char(10)	NOT NULL,
    vend_id	char(10)	NOT NULL,
    prod_name	char(254)	NOT NULL,
    prod_price	DECIMAL(8,2)	NOT NULL,
    prod_desc	varchar(10000)	NULL,
)
create table orderItems(
	order_num	integer	not null,
    order_item	integer	not null,
    /*可以指定默认值,如果插入行的该属性不赋值,将使用默认值*/
    quantity	integer	not null	default 1,
    item_price	decimal(8,2)	not null,
)
  • 更新表

使用ALTER TABLE关键字来更新表,必须要要给出下列信息:

  • 在alter table之后必须要给出更改的表名,该表必须存在,否则将出错
  • 列需要作出哪些更改

小心使用alter table,数据库表的更改不可撤销,一旦增加或删除,将不可撤销

/*给vendors表增加一个名为vend_phone的列,其数据类型为char*/
alter table vendors
add vend_phone char(20)
alter table vendors
/*删除vend_phone列*/
drop column vend_phone
  • 删除表

    使用drop table关键字来删除表,该删除语句一旦执行也无法撤销,将永久删除该表

    drop table custcopy
    

SQL高级特性

  • 约束

    • 主键:是一种特殊的约束,用来保证一列(或一组列)中的值是唯一的,而且永不变动。

      表中任意列只要满足以下条件,就可用于主键

      • 任意两行的主键值都不同
      • 每行都具有一个主键值(即列中不允许NULL值)
      • 包含主键值的列从不修改或更新
      • 主键值不能重用,若从表中删除某一行,其主键值不能分配 给新行
    /*在创建表时就添加主键*/
    create table vendors(
    	vend_id	char(10)	NOT NULL	PRIMARY KEY,
        vend_name	char(50)	not null,
        vend_address	char(50)	null
    )
    
    /*使用constraint关键字来定义主键*/
    alter table vendors
    add constraint primary key (vend_id)
    
    • 外键:是表中的一列,其值必须在另一表的主键中。外键是保证引用完整性,外键在表中不是唯一的
    /*表定义时使用了references关键字 ,表示cust_id中的任何值都必须是customers表的cust_id中的值,这就添加了一个外键*/
    create table orders(
    	order_num integer	not null	primary key,
        order_date	datetime	not null,
        cust_id	char(10)	not null references customers(cust_id)
    )
    
    /*使用constraint关键字来添加外键*/
    alter table orders
    add constraint foreign key (cust_id) references customers(cust_id)
    
    • 唯一约束:用来保证一列(或一组列)中的数据是唯一的。

      唯一约束与主键类似,但有以下区别:

      • 表可以包含多个唯一约束,但只允许有一个主键
      • 唯一约束列可以包含NULL值
      • 唯一约束列可以修改或更新
      • 唯一约束列的值可重复使用
      • 与主键不一样的是,唯一约束不能用来定义外键
    • 检查约束:用来保证一列(或一组列)中的数据满足一组指定的条件

      检查约束通常用于以下几点:

      • 检查最大值和最小值,如防止订单数为负数
      • 指定范围,如特定的日期范围
      • 只允许特定的值,如指定性别
  • 索引:用来排序数据以加快搜索和排序操作的速度

猜你喜欢

转载自blog.csdn.net/qq_31947477/article/details/105906621