SQL比知必会笔记

SQL比知必会笔记

创建相关表

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 
);

-- -----------------------
-- Create OrderItems table
-- -----------------------
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 
);


-- -------------------
-- Create Orders table
-- -------------------
CREATE TABLE Orders
(
  order_num  int      NOT NULL ,
  order_date datetime NOT NULL ,
  cust_id    char(10) NOT NULL 
);

-- ---------------------
-- Create Products table
-- ---------------------
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 
);

-- --------------------
-- Create Vendors table
-- --------------------
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 
);


-- -------------------
-- Define primary keys
-- -------------------
ALTER TABLE Customers ADD PRIMARY KEY (cust_id);
ALTER TABLE OrderItems ADD PRIMARY KEY (order_num, order_item);
ALTER TABLE Orders ADD PRIMARY KEY (order_num);
ALTER TABLE Products ADD PRIMARY KEY (prod_id);
ALTER TABLE Vendors ADD PRIMARY KEY (vend_id);


-- -------------------
-- Define foreign keys
-- -------------------
ALTER TABLE OrderItems ADD CONSTRAINT FK_OrderItems_Orders FOREIGN KEY (order_num) REFERENCES Orders (order_num);
ALTER TABLE OrderItems ADD CONSTRAINT FK_OrderItems_Products FOREIGN KEY (prod_id) REFERENCES Products (prod_id);
ALTER TABLE Orders ADD CONSTRAINT FK_Orders_Customers FOREIGN KEY (cust_id) REFERENCES Customers (cust_id);
ALTER TABLE Products ADD CONSTRAINT FK_Products_Vendors FOREIGN KEY (vend_id) REFERENCES Vendors (vend_id);

了解SQL

  1. 表由列组成,列也称为字段,表的行称为一个记录

  2. 表名是唯一的,应该总是定义主键,SQL不区分大小写。

  3. 所有的空格都被忽略,所以SQL语句可以写成多行。

  4. 查询基本用法:

    1. 选择单列(返回的数据没有特定的顺序):
      SELECT prod_name FROM Products;

    2. 选择多列:
      SELECT prod_id, prod_name, prod_price FROM Products

    3. 检索所有的列(建议少用)
      SELECT * FORM Products

    4. 检索不同的值:
      下面的检索会有重复
      SELECT vend_id FROM Products
      去除重复(DISTINCT关键字作用域所有列):
      SELECT DISTINCT vend_id FROM Products;

    5. 限制结果(第5行起的5行数据,行数从0算):

      SELECT prod_name FORM Products LIMIT 5 OFFSET 5

  5. 注释

    行内注释:– 或 #

    多行注释:/*commemt*/

排序检索数据

  1. 排序

    指定一条order by语句时,应该保证它是select语句的最后一条子句,同时用非检索(不是查出来的)的列排序数据是完全合法的。

    select prod_name form Products order by prod_name
  2. 按多个列排序(prod_price相同时,按照prod_name排序)

    select prod_id, prod_price, prod_name from Products order by prod_price, prod_name
  3. 按列位置排序(先按第二列排序,再按第三列排序,可以混用实际列名和相对位置)

    select prod_id, prod_price, prod_name from Products order by 2, 3
  4. 指定排序方向(DESC指定降序)

    在字典排序顺序中,A被视为与a相同

    select prod_id, prod_price, prod_name from Products order by prod_price desc
    
    select prod_id, prod_price, prod_name from Products order by prod_price DESC, prod_name

过滤数据

  1. 使用where子句(order by位于where子句后面)

    select prod_name, prod_price from Products where prod_price=3
  2. where子句操作符(有冗余的)

    操作符说明操作符说明
    =等于>大于
    <>不等于>=大于等于
    !=不等于!>不大于
    <小于BETWEEN在指定的两个值之间
    <=小于等于IS NULL为NULL值
    !<不小于
  3. 检查单个值

    select prod_name, prod_price from Products where prod_price < 10
  4. 不匹配检查

    单引号用来限定字符串,如果将值与字符串类型的列进行比较,就需要限定引号,用来与数值列进行比较的值不用引号

    select vend_id, prod_name from Products where vend_id <> 'DLL01'
  5. 范围值检查

    select prod_name, prod_price from Products where prod_price between 5 and 10
  6. 空值检查

    select prod_name from Porducts where prod_prices IS NULL

高级数据过滤

  1. 组合where子句(可以多个and, or进行连接)

    select porod_id, prod_price, prod_name from Products where vend_id = 'DLL01' and prod_price <= 4
  2. 注意and结合优先级大于or

    select prod_name, prod_price from Products where (vend_id = 'DLL01' or vend_id = 'BRS01') and prod_price >= 10
  3. IN操作符(与or功能相同,IN操作符的语法更清楚)

    select prod_name, prod_price from Products where vend_id IN ('DLL01', 'BRS01') order by prod_name
  4. NOT操作符,否定后面的条件(在复杂语句中使用有优势)

    select prod_name from Products where NOT vend_id = 'DLL01' order by prod_name
    也可以:
    select prod_name from Products where vend_id <> 'DLL01' order by prod_name

通配符进行过滤

  1. %号通配符(接受Fish之后的任意字符,0个或多个,一条语句可以写多个%)

    select prod_id, prod_name from Products where prod_name LIKE 'Fish%'
  2. 有些数据库会用空格来填充剩下的字段空间,这时候注意:

    LIKE 'f%y' 可能匹配不上f开头,y结尾的内容,要用:
    LIKE 'f%y%'
  3. %不能匹配NULL

  4. 下划线匹配单个字符

    select prod_id, prod_name from Products where prod_name LIKE '_ inch teddy bear'
  5. 方括号[]指定一个字符集,必须配置指定的位置(只有微软的支持)

    select cust_contact from customers where cust_contact LIKE '[JM]%' order by cust_contact
    匹配JM中任意一个字符,也是只能匹配单个字符
    可以用[^JM]来表示否定
  6. 创建计算字段(使用+号拼接结果,+号也可以用||替换),下面查询的结果将会显示:name空格…(country空格…)

    select vend_name + '(' + vend_country + ')' from Vendors ordery by vend_name

    Mysql或MariaDB则需要使用以下语句:

    select Contact(vend_name, '(', vend_country,')') from Vendors order by vend_name

    许多数据库保存填充为列宽的文本值(即会填充空格),mysql中括号中的空格可以这样去掉:

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

    使用别名(别名既可以是一个单词,也可以是一个字符串,如果是后者,要放在括号中):

    select RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title from Vendors order by vend_name

    执行算术操作:

    select prod_id, quantity, 
    item_price,
    quantity*item_price AS expand_price
    from OrderItems where order_num = 20008

使用函数

  1. 文本处理函数

    select vend_name, UPPER(vend_name) as vend_name_upcase from Vendors order by vend_name

    常见的文本处理函数:

    LEFT():返回字符串左边的字符

    LENGTH():返回字符串的长度

    LOWER():将字符串转换为小写

    LTRIM():去掉字符串左边的字符

    RIGHT():返回字符串右边的字符

    SOUNDEX():返回字符串的SOUNDEX值

    UPPER():将字符串转为大写

    select cust_name, cust_contact from Customers where cust_contact='Michael Green'
    //匹配所有发音类似的联系名
    select cust_name, cust_contact from Customers where SOUNDEX(cust_contact)=SOUNDEX('Michael Green')
  2. 日期和时间处理函数

    //SQLServer中检索2012年的所有订单,第一个参数是返回值
    select order_num from Orders where DATEPART(yy, order_date)=2012
    //Mysql
    select order_num from orders where YEAR(order_date)=2012
  3. 数值处理函数

    ABS():返回绝对值
    COS():余弦
    EXP():指数值
    PI():圆周率
    SIN():正弦
    SQRT():数的平方根
    TAN():正切

汇总数据

  1. 聚集函数

    AVG(): 返回某列的平均值

    COUNT():返回行数

    MAX():最大值

    MIN():最小值

    SUM():返回某列值之和、

    //AVG()只能用于单个列,会忽略列值为NULL的行
    select AVG(prod_price) as avg_price from Products
    //计算所有行,不会忽略值为NULL的行
    select COUNT(*) as num_cust from Customers
    //只对单个列计数,忽略NULL的行
    select COUNT(cust_email) as num_cust from Customers
    //返回指定列的最大值,用于文本的话返回该列排序后的最后一行,忽略NULL
    select MAX(prod_price) AS max_price FROM Products
    //同上,只不过意思相反
    select MIN(prod_price) AS min_price FROM Products
    //忽略NULLselect sum(quantity*quantity) as total_price from OrderItems where order_num=20005
    //DISTINCT针对值不同的列操作,不能用于COUNT(*),与DISTINCE相反的参数是ALL,但是是默认的
    select AVG(DISTINCT prod_price) AS avg_price from Products where vend_id='DLL01'
    //组合聚集函数
    select COUNT(*) AS num_items,
    MIN(prod_price) AS price_min,
    MAX(prod_price) AS price_max,
    AVG(prod_price) AS pirce_avg
    FROM Products;

分组数据

  1. 数据分组

    order by子句必须出现在where子句之后,order by 子句之前

    select COUNT(*) AS num_prods FROM Products group by vend_id;
  2. 过滤分组(HAVING),在数据分组后进行过滤(WHERE在分组前过滤)

    select cust_id, COUNT(*) AS orders from orders GROUP BY cust_id HAVING COUNT(*) >= 2
    select vend_id, COUNT(*) AS num_prods FROM Products where prod_price>=4 group by vend_id
    having count(*)>=2
    select order_num, COUNT(*) AS items FROM OrderItems GROUP BY order_num HAVING COUNT(*)>=3
    ORDER BY items, order_num

使用子查询(推荐使用连接查询)

  1. 使用子查询

    select cust_id from orders where order_num IN(20007,20008)
    //子查询
    select cust_id from orders where order_num IN 
    (select order_num from orderitems
    where prod_id='RGA001')
    //使用了表的限定名
    select cust_name,
    cust_state,
    (SELECT COUNT(*)
    FROM Orders
    WHERE Orders.cust_id = Customers.cust_id) AS orders
    from Customers
    order by cust_name

连接表

  1. 创建连接

    //从两个表中选择字段,没有where子句将会返回笛卡尔积,称为等值连接
    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=Porducts.vend_id
  2. 连接多个表(连接的表越多,性能下降越厉害)

    select prod_name, vend_name, prod_price, quantity from OrderItems, Products, Vendors 
    where Porducts.vend_id=Vendors.vend_id
    AND OrderItems.prod_id=Products.prod_id
    AND order_num=20007

创建高级连接查询

  1. 使用表别名(常用于where语句)

    select RTRIM(vend_name)+' ('+RTRIM(vend_country)+')' AS vend_title from Vendors
    ORDER BY vend_name;
  2. 其他一些类型的连接

    //自连接
    select c1.cust_id, c1.cust_name, c1.cust_contact from Customers AS c1, Customers AS c2
    where c1.cust_name = c2.cust_name
    AND c2.cust_contact='Jim Jones'; 
    //自然连接,去掉重复的列(两张表中拿来比较的列)
    select C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity,OI.item_price
    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
    //还有一种是 FULL OUTER JOIN,全外连接,左右都要全选
  3. 使用带聚集函数的连接

    select Customers.cust_id,
    COUNT(Orders.order_num) AS num_ord
    FROM Customers INNER JOIN Orders ON Customers.cust_id=Orders.cust_id
    GROUP BY Customers.cust_id

组合查询

  1. 使用UNION操作符组合数条SQL查询,组合成一个查询集,必须是查询相同的列

    //这个例子用OR也能实现,对于复杂问题用UNION比较方便
    SELECT cust_name, cust_contact, cust_email
    FROM Customers
    WHERE cust_state IN('IL', 'IN', 'MI')
    UNION
    SELECT cust_name, cust_contact, cust_eamil
    FROM Customers
    WHERE cust_name='Fun4All'
    会自动去除重复的行,如果不想去除使用UNION ALL
    UNION支持在最后放一个ORDER BY排序语句,对整个结果起作用

插入数据

  1. 数据插入,每一列都给出值,并且依赖顺序

    select into Customers values('..','..',NULL,NULL)
  2. 插入指定列

    insert into Customers(cust_id,cust_name...) values('..','..')
  3. 省略某些列(该列可以被定义为NULL值)

  4. 插入检索出的数据

    insert into Customers(cust_id,...)
    select cust_id,....
    from CustNew
  5. 从一个表复制到另一个表

    select * into CustCopy from Customers
    或
    create table CustCopy as select * from Customers

更新和删除数据

  1. 更新(一个或多个列)

    update Customers set cust_email='...' where cust_id='...'
  2. 删除数据

    delete from Customers where cust_id='...'

创建和操作表

  1. 表创建

    create table Products
    (
    prod_id  char(10) not null,
    ...
    );

    使用NULL:

    NULL值就是没有值,允许NULL也允许在插入的时候不给出该列的值

    每个表要么是NULL列,要么是NOT NULL列,不指出,默认为NULL

    指定默认值:

    quantity INTEGER NOT NULL DEFAULT 1

  2. 增加、删除列:

    ALTER TABLE Vendors
    ADD vend_phone CHAR(20)
    
    ALTER TABLE Vendors
    DROP COLUMN vend_phone;
  3. 删除列

    DROP TABLE CustCopy

使用视图

  1. 视图:视图是虚拟的表,方便重复使用以及格式化结果

  2. 创建视图:

    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

    使用:

    SELECT cust_name, cust_contact
    FROM ProductCustomers
    WHERE prod_id='RGAN01'

    格式化结果的案例:

    CREATE VIEW VendorLocations AS
    SELECT RTRIM(vend_name) + '('+RTRIM(vend_country)+')'
    AS vend_title
    FROM Vendors

    使用:

    SELECT * 
    FROM VendorLocations

存储过程

  1. 存储过程

    @开头的为局部变量,此存储过程没有参数

    CREATE PROCEDURE MailingListCount
    AS
    DECLARE @cnt INTEGER
    SELECT @cnt = COUNT(*)
    FROM Customers
    WHERE NOT cust_email IS NULL;
    RETURN @cnt;

    调用:

    DECLARE @ReturnValue INT
    EXECUTE @ReturnValue=MailingListCount;
    SELECT @ReturnValue #显示返回值

    有参数的存储过程(创建一个新的订单,传入顾客的订单号,GETDATE返回日期):

    CREATE PROCEDURE NewOrder @cust_id CHAR(10)
    DECLARE @order_num INTEGER
    SELECT @order_num=MAX(order_num) FROM Orders
    SELECT @order_num=@order_num+1
    INSERT INTO Orders(order_num,order_date,cust_id)
    VALUES(@order_num,GETDATE(),@cust_id)

    @@IDENTITY获取自动生成的自增长的标识字段

    CREATE PROCEDURE NewOrder @cust_id CHAR(10)
    AS
    INSERT INTO Orders(cust_id)
    VALUES(@cust_id)
    SELECT order_num=@@IDENTITY

事务管理

  1. 一般SQL语句都是针对数据库表直接执行和编写的,即隐式提交,在事务中提交不会隐式进行

    BEGIN TRANSACTION
    DELETE OrderItems WHERE order_num = 12345
    DELETE Orders WHERE order_num = 12345
    COMMIT TRANSACTION

    部分回退,可以在事务执行的过程中插入一个占位符:

    SAVEPOINT delete1

    使用该占位符:

    ROLLBACK TO delete1

游标

  1. 创建游标:

    DECLARE CustCursor CURSOR
    FOR 
    SELECT * FROM Customers
    WHERE cust_email IS NULL

    使用游标:

    OPEN CURSOR CustCursor

    关闭游标:

    CLOSE CustCursor

高级特性

  1. 主键不为空

    vend_id CHAR(10) NOT NULL PRIMARY KEY

    或者添加主键约束

    ALTER TABLE Vendors
    ADD CONSTRAINT PRIMARY KEY (vend_id);
  2. 外键

    cust_id CHAR(10) NOT NULL REFERENCES Customers(cust_id)

    或者添加约束

    ALTER TABLE Orders
    ADD CONSTRAINT
    FOREIGN KEY (cust_id) REFERENCES Customers (cust_id)
  3. 检查约束

    quantity INTEGER NOT NULL CHECK (quantity > 0 )
  4. 索引:

    类似于排序的原理,加快检索的过程(主键一般都是排序的)

    CREATE INDEX prod_name_ind
    ON Products (prod_name)
  5. 触发器:

    下面是一个触发器的例子,对于所有INSERT和UPDATE操作,将cust_state转为大写

    CREATE TRIGGER customer_state
    ON Customers
    FOR INSERT, UPDATE
    AS
    UPDATE Customers
    SET cust_state = Upper(cust_state)
    WHERE Customers.cust_id = inserted.cust_id

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值