找些不错的sql面试题-2
作者:admin 日期:2010-03-16
- 问题描述:
- 本题用到下面三个关系表:
- CARD 借书卡。 CNO 卡号,NAME 姓名,CLASS 班级
- BOOKS 图书。 BNO 书号,BNAME 书名,AUTHOR 作者,PRICE 单价,QUANTITY 库存册数
- BORROW 借书记录。 CNO 借书卡号,BNO 书号,RDATE 还书日期
- 备注:限定每人每种书只能借一本;库存册数随借书、还书而改变。
- 要求实现如下15个处理:
- 1. 写出建立BORROW表的SQL语句,要求定义主码完整性约束和引用完整性约束。
- 2. 找出借书超过5本的读者,输出借书卡号及所借图书册数。
- 3. 查询借阅了"水浒"一书的读者,输出姓名及班级。
- 4. 查询过期未还图书,输出借阅者(卡号)、书号及还书日期。
- 5. 查询书名包括"网络"关键词的图书,输出书号、书名、作者。
- 6. 查询现有图书中价格最高的图书,输出书名及作者。
- 7. 查询当前借了"计算方法"但没有借"计算方法习题集"的读者,输出其借书卡号,并按卡号降序排序输出。
- 8. 将"C01"班同学所借图书的还期都延长一周。
- 9. 从BOOKS表中删除当前无人借阅的图书记录。
- 10.如果经常按书名查询图书信息,请建立合适的索引。
- 11.在BORROW表上建立一个触发器,完成如下功能:如果读者借阅的书名是"数据库技术及应用",就将该读者的借阅记录保存在BORROW_SAVE表中(注ORROW_SAVE表结构同BORROW表)。
- 12.建立一个视图,显示"力01"班学生的借书信息(只要求显示姓名和书名)。
- 13.查询当前同时借有"计算方法"和"组合数学"两本书的读者,输出其借书卡号,并按卡号升序排序输出。
- 14.假定在建BOOKS表时没有定义主码,写出为BOOKS表追加定义主码的语句。
- 15.对CARD表做如下修改:
- a. 将NAME最大列宽增加到10个字符(假定原为6个字符)。
- b. 为该表增加1列NAME(系名),可变长,最大20个字符。
- 1. 写出建立BORROW表的SQL语句,要求定义主码完整性约束和引用完整性约束
- --实现代码:
- Create TABLE BORROW(
- CNO int FOREIGN KEY REFERENCES CARD(CNO),
- BNO int FOREIGN KEY REFERENCES BOOKS(BNO),
- RDATE datetime,
- PRIMARY KEY(CNO,BNO))
- 2. 找出借书超过5本的读者,输出借书卡号及所借图书册数
- --实现代码:
- Select CNO,借图书册数=COUNT(*)
- FROM BORROW
- GROUP BY CNO
- HAVING COUNT(*)>5
- 3. 查询借阅了"水浒"一书的读者,输出姓名及班级
- --实现代码:
- Select * FROM CARD c
- Where EXISTS(
- Select * FROM BORROW a,BOOKS b
- Where a.BNO=b.BNO
- AND b.BNAME=N'水浒'
- AND a.CNO=c.CNO)
- 4. 查询过期未还图书,输出借阅者(卡号)、书号及还书日期
- --实现代码:
- Select * FROM BORROW
- Where RDATE<GETDATE()
- 5. 查询书名包括"网络"关键词的图书,输出书号、书名、作者
- --实现代码:
- Select BNO,BNAME,AUTHOR FROM BOOKS
- Where BNAME LIKE N'%网络%'
- 6. 查询现有图书中价格最高的图书,输出书名及作者
- --实现代码:
- Select BNO,BNAME,AUTHOR FROM BOOKS
- Where PRICE=(
- Select MAX(PRICE) FROM BOOKS)
- 7. 查询当前借了"计算方法"但没有借"计算方法习题集"的读者,输出其借书卡号,并按卡号降序排序输出
- --实现代码:
- Select a.CNO
- FROM BORROW a,BOOKS b
- Where a.BNO=b.BNO AND b.BNAME=N'计算方法'
- AND NOT EXISTS(
- Select * FROM BORROW aa,BOOKS bb
- Where aa.BNO=bb.BNO
- AND bb.BNAME=N'计算方法习题集'
- AND aa.CNO=a.CNO)
- ORDER BY a.CNO DESC
- 8. 将"C01"班同学所借图书的还期都延长一周
- --实现代码:
- Update b SET RDATE=DATEADD(Day,7,b.RDATE)
- FROM CARD a,BORROW b
- Where a.CNO=b.CNO
- AND a.CLASS=N'C01'
- 9. 从BOOKS表中删除当前无人借阅的图书记录
- --实现代码:
- Delete A FROM BOOKS a
- Where NOT EXISTS(
- Select * FROM BORROW
- Where BNO=a.BNO)
- 10. 如果经常按书名查询图书信息,请建立合适的索引
- --实现代码:
- Create CLUSTERED INDEX IDX_BOOKS_BNAME ON BOOKS(BNAME)
- 11. 在BORROW表上建立一个触发器,完成如下功能:如果读者借阅的书名是"数据库技术及应用",就将该读者的借阅记录保存在BORROW_SAVE表中(注ORROW_SAVE表结构同BORROW表)
- --实现代码:
- Create TRIGGER TR_SAVE ON BORROW
- FOR Insert,Update
- AS
- IF @@ROWCOUNT>0
- Insert BORROW_SAVE Select i.*
- FROM InsertED i,BOOKS b
- Where i.BNO=b.BNO
- AND b.BNAME=N'数据库技术及应用'
- 12. 建立一个视图,显示"力01"班学生的借书信息(只要求显示姓名和书名)
- --实现代码:
- Create VIEW V_VIEW
- AS
- Select a.NAME,b.BNAME
- FROM BORROW ab,CARD a,BOOKS b
- Where ab.CNO=a.CNO
- AND ab.BNO=b.BNO
- AND a.CLASS=N'力01'
- 13. 查询当前同时借有"计算方法"和"组合数学"两本书的读者,输出其借书卡号,并按卡号升序排序输出
- --实现代码:
- Select a.CNO
- FROM BORROW a,BOOKS b
- Where a.BNO=b.BNO
- AND b.BNAME IN(N'计算方法',N'组合数学')
- GROUP BY a.CNO
- HAVING COUNT(*)=2
- ORDER BY a.CNO DESC
- 14. 假定在建BOOKS表时没有定义主码,写出为BOOKS表追加定义主码的语句
- --实现代码:
- Alter TABLE BOOKS ADD PRIMARY KEY(BNO)
- 15.1 将NAME最大列宽增加到10个字符(假定原为6个字符)
- --实现代码:
- Alter TABLE CARD Alter COLUMN NAME varchar(10)
- 15.2 为该表增加1列NAME(系名),可变长,最大20个字符
- --实现代码:
- Alter TABLE CARD ADD 系名 varchar(20)
- 问题描述:
- 为管理岗位业务培训信息,建立3个表:
- S (S#,SN,SD,SA) S#,SN,SD,SA 分别代表学号、学员姓名、所属单位、学员年龄
- C (C#,CN ) C#,CN 分别代表课程编号、课程名称
- SC ( S#,C#,G ) S#,C#,G 分别代表学号、所选修的课程编号、学习成绩
- 要求实现如下5个处理:
- 1. 使用标准SQL嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名
- 2. 使用标准SQL嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位
- 3. 使用标准SQL嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位
- 4. 使用标准SQL嵌套语句查询选修全部课程的学员姓名和所属单位
- 5. 查询选修了课程的学员人数
- 6. 查询选修课程超过5门的学员学号和所属单位
- 1. 使用标准SQL嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名
- --实现代码:
- Select SN,SD FROM S
- Where [S#] IN(
- Select [S#] FROM C,SC
- Where C.[C#]=SC.[C#]
- AND CN=N'税收基础')
- 2. 使用标准SQL嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位
- --实现代码:
- Select S.SN,S.SD FROM S,SC
- Where S.[S#]=SC.[S#]
- AND SC.[C#]='C2'
- 3. 使用标准SQL嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位
- --实现代码:
- Select SN,SD FROM S
- Where [S#] NOT IN(
- Select [S#] FROM SC
- Where [C#]='C5')
- 4. 使用标准SQL嵌套语句查询选修全部课程的学员姓名和所属单位
- --实现代码:
- Select SN,SD FROM S
- Where [S#] IN(
- Select [S#] FROM SC
- RIGHT JOIN C ON SC.[C#]=C.[C#]
- GROUP BY [S#]
- HAVING COUNT(*)=COUNT(DISTINCT [S#]))
- 5. 查询选修了课程的学员人数
- --实现代码:
- Select 学员人数=COUNT(DISTINCT [S#]) FROM SC
- 6. 查询选修课程超过5门的学员学号和所属单位
- --实现代码:
- Select SN,SD FROM S
- Where [S#] IN(
- Select [S#] FROM SC
- GROUP BY [S#]
- HAVING COUNT(DISTINCT [C#])>5)
整理精华帖子
作者:admin 日期:2010-03-16
行列转换:
http://topic.csdn.net/u/20080614/17/22e73f33-f071-46dc-b9bf-321204b1656f.html?33238(总 结帖子)
http://topic.csdn.net/u/20090912/14/25d2e1b2-f352-4713-8618-d3433ba27bef.html?99104(经 典帖子)
合并分拆表:
http://topic.csdn.net/u/20080612/22/c850499f-bce3-4877-82d5-af2357857872.html?23514
果果字符串整理系列
处理表重复记录
http://topic.csdn.net/u/20080626/00/43d0d10c-28f1-418d-a05b-663880da278a.html?85256
SSAS系列:
过渡到SSAS之一:简单模型认识
过渡到SSAS之二:服务的发布
和尚翻译的SSRS的帖子
SSIS系列:
小梁系列之SSIS遍历记录查询邮件
小梁系列之SSIS表达式
小梁系列之SSIS “查找组件” 查找范围内的数据
小梁系列之SSIS 同步和异步转换
小梁系列之SSIS中 “条件拆分”组件中 ISNUMERIC的问题
小梁系列之脚本任务中访问记录集 RecordSet
小梁系列之SSIS中数据源和数据目标中 的”保留空值”
有关SQL注入的帖子:
SQL注入专题
http://topic.csdn.net/u/20090326/11/5e584897-2dd7-4e10-af1b-9b48b146af8e.html?95281
http://topic.csdn.net/u/20090523/19/72041932-b65c-49c1-ad36-d2c63b38b174.html?96607
经典代码系列:
经典短小代码
第一季
第二季
最近的一个
http://topic.csdn.net/u/20080605/15/ca6b25f3-3e60-4b95-ac7e-7d7dc02354e6.html?87229
T-SQL常见基础疑点问答整理(1)
T-SQL常见基础疑点问答整理(2)
石头系列之2005事务与锁定系列
事务与锁定第一篇
事务与锁定第二篇
事务与锁定第三篇
事务与锁定第四篇
事务与锁定第五篇
事务与锁定第六篇
石头系列之数据库引擎结构
数据库引擎结构一
数据库引擎结构二
数据库引擎结构三
各种进制的转换:(来自影子)
http://topic.csdn.net/u/20090707/16/9a7b8e46-1467-4373-a195-39d80b826827.html?28501
关于数据库的同步的帖子:
http://topic.csdn.net/u/20080523/11/08e4624a-13d1-4a6c-a9bc-7cfdd721a351.html?4574
http://topic.csdn.net/u/20080801/11/2f79d062-8049-4ade-a884-01dbaa429135.html?63426
http://topic.csdn.net/u/20090520/22/2267467b-0c40-4a5e-8b71-24838be0ff64.html?10943
两台服务器的相互同步
数据的导入导出部分:
CSV文件批量导入数据库
http://topic.csdn.net/u/20091009/11/5f3ebd1a-de5f-4d92-bc76-0f2103a34b5a.html?48287
excel导入SQL
http://topic.csdn.net/u/20090724/00/a479a979-8a20-4abb-a184-8a0ee56608c2.html?86864
BCP:
http://topic.csdn.net/u/20090720/21/b27734aa-c091-4a6b-96db-f234e2699385.html?84209
http://topic.csdn.net/u/20090720/21/b27734aa-c091-4a6b-96db-f234e2699385.html?2600
数据的转移
一个比较巧的导法
数据的分页:
http://topic.csdn.net/u/20090416/02/4e3cb6d6-707a-4f42-b295-3e9fd5df7691.html?52379
SQL查询与性能优化系列:
SQL性能优化综述
SQL Server查询优化
SQL优化之执行计划
五种提高SQL性能的方法
SQL开发的二十一条军规
一千万条数据的优化
如何提高sql查询100万条数据 count(*)汇总的速度
数据库优化汇总
海量数据库的相关处理
索引系列:
全文索引
查看索引信息/生成创建索引脚本
聚焦索引与非聚焦索引及其查询效率
递归函数系列:
BOM:
其他:
http://topic.csdn.net/u/20090807/08/19f980a3-3830-4261-90ca-0f85ec628492.html?62247
如何判断一个IP地址在一个IP地址段
身份证号码的转化
2005CLR系列:
环比运算
树结构
天气服务
正则表达式
数据库的并发性以及锁相关的帖子:
一个简单的存储过程产生死锁
单条Update语句是否加事务与锁的关系
分析死锁并整理
触发器、存储过程等
触发器综述
触发器删除的一个问题
分组求前N条数据:
分组求前N条数据
数据库的备份与恢复等问题
数据库的备份与恢复等问题
还原指定文件夹下的备份
作业:
自动备份数据库作业
SQL常见的安装问题
SQL常见的安装问题
SQL不能连接的完美解决方案
远程连接操作 整理帖子
远程连接操作 整理帖子
自动生成流水号
自动生成流水号
求每行的最小的那个字母
数据库的加密
数据库的加密
根据时间求某个月所有日期或者某天的所有时间段
根据时间求某个月所有日期或者某天的所有时间段
如何查漏号字段
如何查漏号字段
多列求最大值或者最小值
多列求最大值或者最小值
总结一下,免得每次都得去查看别人的东西
作者:admin 日期:2010-03-16
- 1:replace 函数
- 第一个参数你的字符串,第二个参数你想替换的部分,第三个参数你要替换成什么
- select replace('lihan','a','b')
- -----------------------------
- lihbn
- (所影响的行数为 1 行)
- =========================================================
- 2:substring函数
- 第一个参数你的字符串,第二个是开始替换位置,第三个结束替换位置
- select substring('lihan',0,3);
- -----
- li
- (所影响的行数为 1 行)
- =========================================================
- 3:charindex函数
- 第一个参数你要查找的char,第二个参数你被查找的字符串 返回参数一在参数二的位置
- select charindex('a','lihan')
- -----------
- 4
- (所影响的行数为 1 行)
- ===========================================================
- 4:ASCII函数
- 返回字符表达式中最左侧的字符的 ASCII 代码值。
- select ASCII('lihan')
- -----------
- 108
- (所影响的行数为 1 行)
- ================================================================
- 5:nchar函数
- 根据 Unicode 标准的定义,返回具有指定的整数代码的 Unicode 字符。
- 参数是介于 0 与 65535 之间的正整数。如果指定了超出此范围的值,将返回 NULL。
- select nchar(3213)
- ----
- unicode字符
- (所影响的行数为 1 行)
- =========================================================
- 6:soundex
- 返回一个由四个字符组成的代码 (SOUNDEX),用于评估两个字符串的相似性。
- Select SOUNDEX ('lihan'), SOUNDEX ('lihon');
- ----- -----
- L546 L542
- (所影响的行数为 1 行)
- =========================================================
- 7:char
- 参数为介于 0 和 255 之间的整数。如果该整数表达式不在此范围内,将返回 NULL 值。
- Select char(125)
- ----
- }
- (所影响的行数为 1 行)
- ==========================================================
- 8:str函数
- 第一个参数必须为数字,第二个参数表示转化成char型占的位置,小于参数一位置返回*,大于右对齐
- Select str(12345,3)
- ----
- ***
- (所影响的行数为 1 行)
- Select str(12345,12)
- ------------
- 12345
- (所影响的行数为 1 行)
- ===========================================================
- 9:difference函数
- 返回一个整数值,指示两个字符表达式的 SOUNDEX 值之间的差异。
- 返回的整数是 SOUNDEX 值中相同字符的个数。返回的值从 0 到 4 不等:0 表示几乎不同或完全不同,4 表示几乎相同或完全相同。
- Select difference('lihan','liha')
- -----------
- 3
- (所影响的行数为 1 行)
- ==================================================================
- 10:stuff函数(四个参数)
- 函数将字符串插入另一字符串。它在第一个字符串中从开始位置删除指定长度的字符;然后将第二个字符串插入第一个字符串的开始位置。
- Select stuff('lihan',2,3,'lihan')
- --------
- llihann
- (所影响的行数为 1 行)
- ===============================================================
- 11:left函数
- 返回最左边N个字符,由参数决定
- select left('lihan',4)
- -----
- liha
- (所影响的行数为 1 行)
- ================================================================
- 12 right函数
- 返回最右边N个字符,由参数决定
- select right('lihan',4)
- -----
- ihan
- (所影响的行数为 1 行)
- ================================================================
- 13:replicate函数
- 我的认为是把参数一复制参数二次
- select replicate('lihan',4)
- --------------------
- lihanlihanlihanlihan
- (所影响的行数为 1 行)
- ================================================================
- 14:len函数
- 返回参数长度
- select len('lihan')
- -----------
- 5
- (所影响的行数为 1 行)
- ================================================================
- 15:reverse函数
- 反转字符串
- select reverse('lihan')
- -----
- nahil
- (所影响的行数为 1 行)
- =================================================================
- 16:lower和upper函数
- 参数大小写转化
- select lower(upper('lihan'))
- --------------------
- lihan
- (所影响的行数为 1 行)
- ====================================================================
- 17:ltrim和rtrim函数
- 删除左边空格和右面空格
- select ltrim(' lihan ')
- --------------------------
- lihan
- (所影响的行数为 1 行)
- select rtrim(' lihan')
- ---------
- lihan
- (所影响的行数为 1 行)
SQL查询语句精华大全
作者:admin 日期:2010-03-14
- SQL查询语句精华大全
- 一、简单查询
- 简单的Transact-SQL查询只包括选择列表、FROM子句和Where子句。它们分别说明所查询列、查询的表或视图、以及搜索条件等。
- 例如,下面的语句查询testtable表中姓名为“张三”的nickname字段和email字段。
- Select nickname,email
- FROM testtable
- Where name='张三'
- (一) 选择列表
- 选择列表(select_list)指出所查询列,它可以是一组列名列表、星号、表达式、变量(包括局部变量和全局变量)等构成。
- 1、选择所有列
- 例如,下面语句显示testtable表中所有列的数据:
- Select *
- FROM testtable
- 2、选择部分列并指定它们的显示次序
- 查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。
- 例如:
- Select nickname,email
- FROM testtable
- 3、更改列标题
- 在选择列表中,可重新指定列标题。定义格式为:
- 列标题=列名
- 列名 列标题
- 如果指定的列标题不是标准的标识符格式时,应使用引号定界符,例如,下列语句使用汉字显示列
- 标题:
- Select 昵称=nickname,电子邮件=email
- FROM testtable
- 4、删除重复行
- Select语句中使用ALL或DISTINCT选项来显示表中符合条件的所有行或删除其中重复的数据行,默认
- 为ALL。使用DISTINCT选项时,对于所有重复的数据行在Select返回的结果集合中只保留一行。
- 5、限制返回的行数
- 使用TOP n [PERCENT]选项限制返回的数据行数,TOP n说明返回n行,而TOP n PERCENT时,说明n是表示一百分数,指定返回的行数等于总行数的百分之几。
- 例如:
- Select TOP 2 *
- FROM testtable
- Select TOP 20 PERCENT *
- FROM testtable
- (二) FROM子句
- FROM子句指定Select语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。
- 在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列
- 所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应
- 使用下面语句格式加以限定:
- Select username,citytable.cityid
- FROM usertable,citytable
- Where usertable.cityid=citytable.cityid
- 在FROM子句中可用以下两种格式为表或视图指定别名:
- 表名 as 别名
- 表名 别名
- 例如上面语句可用表的别名格式表示为:
- Select username,b.cityid
- FROM usertable a,citytable b
- Where a.cityid=b.cityid
- Select不仅能从表或视图中检索数据,它还能够从其它查询语句所返回的结果集合中查询数据。
- 例如:
- Select a.au_fname+a.au_lname
- FROM authors a,titleauthor ta
- (Select title_id,title
- FROM titles
- Where ytd_sales>10000
- ) AS t
- Where a.au_id=ta.au_id
- AND ta.title_id=t.title_id
- 此例中,将Select返回的结果集合给予一别名t,然后再从中检索数据。
- (三) 使用Where子句设置查询条件
- Where子句设置查询条件,过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据:
- Select *
- FROM usertable
- Where age>20
- Where子句可包括各种条件运算符:
- 比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!<
- 范围运算符(表达式值是否在指定的范围):BETWEEN…AND…
- NOT BETWEEN…AND…
- 列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……)
- NOT IN (项1,项2……)
- 模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE
- 空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL
- 逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR
- 1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30
- 2、列表运算符例:country IN ('Germany','China')
- 3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配。可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询。
- 可使用以下通配字符:
- 百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%。
- 下划线_:匹配单个任意字符,它常用来限制表达式的字符长度。
- 方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。
- [^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
- 例如:
- 限制以Publishing结尾,使用LIKE '%Publishing'
- 限制以A开头:LIKE '[A]%'
- 限制以A开头外:LIKE '[^A]%'
- 4、空值判断符例Where age IS NULL
- 5、逻辑运算符:优先级为NOT、AND、OR
- (四)查询结果排序
- 使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为:
- ORDER BY {column_name [ASC|DESC]} [,…n]
- 其中ASC表示升序,为默认值,DESC为降序。ORDER BY不能按ntext、text和image数据类型进行排
- 序。
- 例如:
- Select *
- FROM usertable
- ORDER BY age desc,userid ASC
- 另外,可以根据表达式进行排序。
- 二、 联合查询
- UNION运算符可以将两个或两个以上上Select语句的查询结果集合合并成一个结果集合显示,即执行联合查询。UNION的语法格式为:
- select_statement
- UNION [ALL] selectstatement
- [UNION [ALL] selectstatement][…n]
- 其中selectstatement为待联合的Select查询语句。
- ALL选项表示将所有行合并到结果集合中。不指定该项时,被联合查询结果集合中的重复行将只保留一行。联合查询时,查询结果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名、列标题或者列序号。在使用UNION 运算符时,应保证每个联合查询语句的选择列表中有相同数量的表达式,并且每个查询选择表达式应具有相同的数据类型,或是可以自动将它们转换为相同的数据类型。在自动转换时,对于数值类型,系统将低精度的数据类型转换为高精度的数据类型。在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序。例如:
- 查询1 UNION (查询2 UNION 查询3)
- 三、连接查询
- 通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。
- 在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,尔后通过连接进行查询。
- 连接可以在Select 语句的FROM子句或Where子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与Where子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。
- SQL-92标准所定义的FROM子句的连接语法格式为:
- FROM join_table join_type join_table
- [ON (join_condition)]
- 其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自连接。
- join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。内连接(INNER JOIN)使用比
- 较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用
- 的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。
- 外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)
- 和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹
- 配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的
- 数据行。
- 交叉连接(CROSS JOIN)没有Where 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的
- 数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。
- 连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑
- 运算符等构成。
- 无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接
- 连接。例如:
- Select p1.pub_id,p2.pub_id,p1.pr_info
- FROM pub_info AS p1 INNER JOIN pub_info AS p2
- ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)
- (一)内连接
- 内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分
- 三种:
- 1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接
- 表中的所有列,包括其中的重复列。
- 2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些
- 运算符包括>、>=、<=、<、!>、!<和<>。
- 3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询
- 结果集合中所包括的列,并删除连接表中的重复列。
- 例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:
- Select *
- FROM authors AS a INNER JOIN publishers AS p
- ON a.city=p.city
- 又如使用自然连接,在选择列表中删除authors 和publishers 表中重复列(city和state):
- Select a.*,p.pub_id,p.pub_name,p.country
- FROM authors AS a INNER JOIN publishers AS p
- ON a.city=p.city
- (二)外连接
- 内连接时,返回查询结果集合中的仅是符合查询条件( Where 搜索条件或 HAVING 条件)和连接条件
- 的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外
- 连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。
- 如下面使用左外连接将论坛内容和作者信息连接起来:
- Select a.*,b.* FROM luntan LEFT JOIN usertable as b
- ON a.username=b.username
- 下面使用全外连接将city表中的所有作者以及user表中的所有作者,以及他们所在的城市:
- Select a.*,b.*
- FROM city as a FULL OUTER JOIN user as b
- ON a.username=b.username
- (三)交叉连接
- 交叉连接不带Where 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数
- 据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。
- 例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等
- 于6*8=48行。
- Select type,pub_name
- FROM titles CROSS JOIN publishers
- ORDER BY typeSQL核心语句(非常实用的几个技巧)插入数据
- 向表中添加一个新记录,你要使用SQL Insert 语句。这里有一个如何使用这种语句的例子:
- Insert mytable (mycolumn) VALUES (‘some data’)
- 这个语句把字符串’some data’插入表mytable的mycolumn字段中。将要被插入数据的字段的名字在第一个括号中指定,实际的数据在第二个括号中给出。
- Insert 语句的完整句法如下:
- Insert [INTO] {table_name|view_name} [(column_list)] {DEFAULT VALUES |
- Values_list | select_statement}
- 如果一个表有多个字段,通过把字段名和字段值用逗号隔开,你可以向所有的字段中插入数据。假设表mytable有三个字段first_column,second_column,和third_column。下面的Insert语句添加了一条三个字段都有值的完整记录:
- Insert mytable (first_column,second_column,third_column)
- VALUES (‘some data’,’some more data’,’yet more data’)
- 注意
- 你可以使用Insert语句向文本型字段中插入数据。但是,如果你需要输入很长的字符串,你应该使用WRITETEXT语句。这部分内容对本书来说太高级了,因此不加讨论。要了解更多的信息,请参考Microsoft SQL Sever 的文档。
- 如果你在Insert 语句中只指定两个字段和数据会怎么样呢?换句话说,你向一个表中插入一条新记录,但有一个字段没有提供数据。在这种情况下,有下面的四种可能:
- 如果该字段有一个缺省值,该值会被使用。例如,假设你插入新记录时没有给字段third_column提供数据,而这个字段有一个缺省值’some value’。在这种情况下,当新记录建立时会插入值’some value’。
- 如果该字段可以接受空值,而且没有缺省值,则会被插入空值。
- 如果该字段不能接受空值,而且没有缺省值,就会出现错误。你会收到错误信息:
- The column in table mytable may not be null.
- 最后,如果该字段是一个标识字段,那么它会自动产生一个新值。当你向一个有标识字段的表中插入新记录时,只要忽略该字段,标识字段会给自己赋一个新值。
- 注意
- 向一个有标识字段的表中插入新记录后,你可以用SQL变量@@identity来访问新记录
- 的标识字段的值。考虑如下的SQL语句:
- Insert mytable (first_column) VALUES(‘some value’)
- Insert anothertable(another_first,another_second)
- VALUES(@@identity,’some value’)
- 如果表mytable有一个标识字段,该字段的值会被插入表anothertable的another_first字段。这是因为变量@@identity总是保存最后一次插入标识字段的值。
- 字段another_first应该与字段first_column有相同的数据类型。但是,字段another_first不能是应该标识字段。Another_first字段用来保存字段first_column的值。
- 删除记录
- 要从表中删除一个或多个记录,需要使用SQL Delete语句。你可以给Delete 语句提供Where 子句。Where子句用来选择要删除的记录。例如,下面的这个Delete语句只删除字段first_column的值等于’Delete Me’的记录:
- Delete mytable Where first_column=’Deltet Me’
- Delete 语句的完整句法如下:
- Delete [FROM] {table_name|view_name} [Where clause]
- 在SQL Select 语句中可以使用的任何条件都可以在DELECT 语句的Where子句中使用。例如,下面的这个Delete语句只删除那些first_column字段的值为’goodbye’或second_column字段的值为’so long’的记录:
- Delete mytable Where first_column=’goodby’ OR second_column=’so long’
- 如果你不给Delete 语句提供Where 子句,表中的所有记录都将被删除。你不应该有这种想法。如果你想删除应该表中的所有记录,应使用第十章所讲的TRUNCATE TABLE语句。
- 注意
- 为什么要用TRUNCATE TABLE 语句代替Delete语句?当你使用TRUNCATE TABLE语句时,记录的删除是不作记录的。也就是说,这意味着TRUNCATE TABLE 要比Delete快得多。
- 更新记录
- 要修改表中已经存在的一条或多条记录,应使用SQL Update语句。同Delete语句一样,Update语句可以使用Where子句来选择更新特定的记录。请看这个例子:
- Update mytable SET first_column=’Updated!’ Where second_column=’Update Me!’
- 这个Update 语句更新所有second_column字段的值为’Update Me!’的记录。对所有被选中的记录,字段first_column的值被置为’Updated!’。
- 下面是Update语句的完整句法:
- Update {table_name|view_name} SET [{table_name|view_name}]
- {column_list|variable_list|variable_and_column_list}
- [,{column_list2|variable_list2|variable_and_column_list2}…
- [,{column_listN|variable_listN|variable_and_column_listN}]]
- [Where clause]
- 注意
- 你可以对文本型字段使用Update语句。但是,如果你需要更新很长的字符串,应使用UpdateTEXT语句。这部分内容对本书来说太高级了,因此不加讨论。要了解更多的信息,请参考Microsoft SQL Sever 的文档。
- 如果你不提供Where子句,表中的所有记录都将被更新。有时这是有用的。例如,如果你想把表titles中的所有书的价格加倍,你可以使用如下的Update 语句:
- 你也可以同时更新多个字段。例如,下面的Update语句同时更新first_column,second_column,和third_column这三个字段:
- Update mytable SET first_column=’Updated!’
- Second_column=’Updated!’
- Third_column=’Updated!’
- Where first_column=’Update Me1’
- 技巧
- SQL忽略语句中多余的空格。你可以把SQL语句写成任何你最容易读的格式。
- 用Select 创建记录和表
- 你也许已经注意到,Insert 语句与Delete语句和Update语句有一点不同,它一次只操作一个记录。然而,有一个方法可以使Insert 语句一次添加多个记录。要作到这一点,你需要把Insert 语句与Select 语句结合起来,象这样:
- Insert mytable (first_column,second_column)
- Select another_first,another_second
- FROM anothertable
- Where another_first=’Copy Me!’
- 这个语句从anothertable拷贝记录到mytable.只有表anothertable中字段another_first的值为’Copy Me!’的记录才被拷贝。
- 当为一个表中的记录建立备份时,这种形式的Insert 语句是非常有用的。在删除一个表中的记录之前,你可以先用这种方法把它们拷贝到另一个表中。
- 如果你需要拷贝整个表,你可以使用Select INTO 语句。例如,下面的语句创建了一个名为newtable的新表,该表包含表mytable的所有数据:
- Select * INTO newtable FROM mytable
- 你也可以指定只有特定的字段被用来创建这个新表。要做到这一点,只需在字段列表中指定你想要拷贝的字段。另外,你可以使用Where 子句来限制拷贝到新表中的记录。下面的例子只拷贝字段second_columnd的值等于’Copy Me!’的记录的first_column字段。
- Select first_column INTO newtable
- FROM mytable
- Where second_column=’Copy Me!’
- 使用SQL修改已经建立的表是很困难的。例如,如果你向一个表中添加了一个字段,没有容易的办法来去除它。另外,如果你不小心把一个字段的数据类型给错了,你将没有办法改变它。但是,使用本节中讲述的SQL语句,你可以绕过这两个问题。
- 例如,假设你想从一个表中删除一个字段。使用Select INTO 语句,你可以创建该表的一个拷贝,但不包含要删除的字段。这使你既删除了该字段,又保留了不想删除的数据。
- 如果你想改变一个字段的数据类型,你可以创建一个包含正确数据类型字段的新表。创建好该表后,你就可以结合使用Update语句和Select 语句,把原来表中的所有数据拷贝到新表中。通过这种方法,你既可以修改表的结构,又能保存原有的数据。
SQL基本语句
作者:admin 日期:2010-03-14
- SQL基本语句
- 掌握SQL四条最基本的数据操作语句:Insert,Select,Update和Delete。
- 练掌握SQL是数据库用户的宝贵财 富。在本文中,我们将引导你掌握四条最基本的数据操作语句—SQL的核心功能—来依次介绍比较操作符、选择断言以及三值逻辑。当你完成这些学习后,显然你已经开始算是精通SQL了。
- 在我们开始之前,先使用Create TABLE语句来创建一个表(如图1所示)。DDL语句对数据库对象如表、列和视进行定义。它们并不对表中的行进行处理,这是因为DDL语句并不处理数据库中实际的数据。这些工作由另一类SQL语句—数据操作语言(DML)语句进行处理。
- SQL中有四种基本的DML操作:Insert,Select,Update和Delete。由于这是大多数SQL用户经常用到的,我们有必要在此对它们进行一一说明。在图1中我们给出了一个名为EMPLOYEES的表。其中的每一行对应一个特定的雇员记录。请熟悉这张表,我们在后面的例子中将要用到它。
- Insert语句
- 用户可以用Insert语句将一行记录插入到指定的一个表中。例如,要将雇员John Smith的记录插入到本例的表中,可以使用如下语句:
- Insert INTO EMPLOYEES VALUES
- ('Smith','John','1980-06-10',
- 'Los Angles',16,45000);
- 通过这样的Insert语句,系统将试着将这些值填入到相应的列中。这些列按照我们创建表时定义的顺序排列。在本例中,第一个值“Smith”将填到第一个列LAST_NAME中;第二个值“John”将填到第二列FIRST_NAME中……以此类推。
- 我们说过系统会“试着”将值填入,除了执行规则之外它还要进行类型检查。如果类型不符(如将一个字符串填入到类型为数字的列中),系统将拒绝这一次操作并返回一个错误信息。
- 如果SQL拒绝了你所填入的一列值,语句中其他各列的值也不会填入。这是因为SQL提供对事务的支持。一次事务将数据库从一种一致性转移到另一种一致性。如果事务的某一部分失败,则整个事务都会失败,系统将会被恢复(或称之为回退)到此事务之前的状态。
- 回到原来的Insert的例子,请注意所有的整形十进制数都不需要用单引号引起来,而字符串和日期类型的值都要用单引号来区别。为了增加可读性而在数字间插入逗号将会引起错误。记住,在SQL中逗号是元素的分隔符。
- 同样要注意输入文字值时要使用单引号。双引号用来封装限界标识符。
- 对于日期类型,我们必须使用SQL标准日期格式(yyyy-mm-dd),但是在系统中可以进行定义,以接受其他的格式。当然,2000年临近,请你最好还是使用四位来表示年份。
- 既然你已经理解了Insert语句是怎样工作的了,让我们转到EMPLOYEES表中的其他部分:
- Insert INTO EMPLOYEES VALUES
- ('Bunyan','Paul','1970-07-04',
- 'Boston',12,70000);
- Insert INTO EMPLOYEES VALUES
- ('John','Adams','1992-01-21',
- 'Boston',20,100000);
- Insert INTO EMPLOYEES VALUES
- ('Smith','Pocahontas','1976-04-06',
- 'Los Angles',12,100000);
- Insert INTO EMPLOYEES VALUES
- ('Smith','Bessie','1940-05-02',
- 'Boston',5,200000);
- Insert INTO EMPLOYEES VALUES
- ('Jones','Davy','1970-10-10',
- 'Boston',8,45000);
- Insert INTO EMPLOYEES VALUES
- ('Jones','Indiana','1992-02-01',
- 'Chicago',NULL,NULL);
- 在最后一项中,我们不知道Jones先生的工薪级别和年薪,所以我们输入NULL(不要引号)。NULL是SQL中的一种特殊情况,我们以后将进行详细的讨论。现在我们只需认为NULL表示一种未知的值。
- 有时,像我们刚才所讨论的情况,我们可能希望对某一些而不是全部的列进行赋值。除了对要省略的列输入NULL外,还可以采用另外一种Insert语句,如下:
- Insert INTO EMPLOYEES(
- FIRST_NAME, LAST_NAME,
- HIRE_DATE, BRANCH_OFFICE)
- VALUE(
- 'Indiana','Jones',
- '1992-02-01','Indianapolis');
- 这样,我们先在表名之后列出一系列列名。未列出的列中将自动填入缺省值,如果没有设置缺省值则填入NULL。请注意我们改变了列的顺序,而值的顺序要对应新的列的顺序。如果该语句中省略了FIRST_NAME和LAST_NAME项(这两项规定不能为空),SQL操作将失败。
- 让我们来看一看上述Insert语句的语法图:
- Insert INTO table
- [(column { ,column})]
- VALUES
- (columnvalue [{,columnvalue}]);
- 和前一篇文章中一样,我们用方括号来表示可选项,大括号表示可以重复任意次数的项(不能在实际的SQL语句中使用这些特殊字符)。VALUE子句和可选的列名列表中必须使用圆括号。
- Select语句
- Select语句可以从一个或多个表中选取特定的行和列。因为查询和检索数据是数据库管理中最重要的功能,所以Select语句在SQL中是工作量最大的部分。实际上,仅仅是访问数据库来分析数据并生成报表的人可以对其他SQL语句一窍不通。
- Select语句的结果通常是生成另外一个表。在执行过程中系统根据用户的标准从数据库中选出匹配的行和列,并将结果放到临时的表中。在直接SQL(direct SQL)中,它将结果显示在终端的显示屏上,或者将结果送到打印机或文件中。也可以结合其他SQL语句来将结果放到一个已知名称的表中。
- Select语句功能强大。虽然表面上看来它只用来完成本文第一部分中提到的关系代数运算“选择”(或称“限制”),但实际上它也可以完成其他两种关系运算—“投影”和“连接”,Select语句还可以完成聚合计算并对数据进行排序。
- Select语句最简单的语法如下:
- Select columns FROM tables;
- 当我们以这种形式执行一条Select语句时,系统返回由所选择的列以及用户选择的表中所有指定的行组成的一个结果表。这就是实现关系投影运算的一个形式。
- 让我们看一下使用图1中EMPLOYEES表的一些例子(这个表是我们以后所有Select语句实例都要使用的。而我们在图2和图3中给出了查询的实际结果。我们将在其他的例子中使用这些结果)。
- 假设你想查看雇员工作部门的列表。那下面就是你所需要编写的SQL查询:
- Select BRANCH_OFFICE FROM EMPLOYEES;
- 以上Select语句的执行将产生如图2中表2所示的结果。
- 由于我们在Select语句中只指定了一个列,所以我们的结果表中也只有一个列。注意结果表中具有重复的行,这是因为有多个雇员在同一部门工作(记住SQL从所选的所有行中将值返回)。要消除结果中的重复行,只要在Select语句中加上DISTINCT子句:
- Select DISTINCT BRANCH_OFFICE
- FROM EMPLOYEES;
- 这次查询的结果如表3所示。
- 现在已经消除了重复的行,但结果并不是按照顺序排列的。如果你希望以字母表顺序将结果列出又该怎么做呢?只要使用ORDER BY子句就可以按照升序或降序来排列结果:
- Select DISTINCT BRANCH_OFFICE
- FROM EMPLOYEES
- ORDER BY BRANCH_OFFICE ASC;
- 这一查询的结果如表4所示。请注意在ORDER BY之后是如何放置列名BRANCH _OFFICE的,这就是我们想要对其进行排序的列。为什么即使是结果表中只有一个列时我们也必须指出列名呢?这是因为我们还能够按照表中其他列进行排序,即使它们并不显示出来。列名BRANCH_ OFFICE之后的关键字ASC表示按照升序排列。如果你希望以降序排列,那么可以用关键字DESC。
- 同样我们应该指出ORDER BY子句只将临时表中的结果进行排序;并不影响原来的表。
- 假设我们希望得到按部门排序并从工资最高的雇员到工资最低的雇员排列的列表。除了工资括号中的内容,我们还希望看到按照聘用时间从最近聘用的雇员开始列出的列表。以下是你将要用到的语句:
- Select BRANCH_OFFICE,FIRST_NAME,
- LAST_NAME,SALARY,HIRE_DATE
- FROM EMPLOYEES
- ORDER BY SALARY DESC,
- HIRE_DATE DESC;
- 这里我们进行了多列的选择和排序。排序的优先级由语句中的列名顺序所决定。SQL将先对列出的第一个列进行排序。如果在第一个列中出现了重复的行时,这些行将被按照第二列进行排序,如果在第二列中又出现了重复的行时,这些行又将被按照第三列进行排序……如此类推。这次查询的结果如表5所示。
- 将一个很长的表中的所有列名写出来是一件相当麻烦的事,所以SQL允许在选择表中所有的列时使用*号:
- Select * FROM EMPLOYEES;
- 这次查询返回整个EMPLOYEES表,如表1所示。
- 下面我们对开始时给出的Select语句的语法进行一下更新(竖直线表示一个可选项,允许在其中选择一项。):
- Select [DISTINCT]
- (column [{, columns}])| *
- FROM table [ {, table}]
- [ORDER BY column [ASC] | DESC
- [ {, column [ASC] | DESC }]];
- 定义选择标准
- 在我们目前所介绍的Select语句中,我们对结果表中的列作出了选择但返回的是表中所有的行。让我们看一下如何对Select语句进行限制使得它只返回希望得到的行:
- Select columns FROM tables [Where predicates];
- Where子句对条件进行了设置,只有满足条件的行才被包括到结果表中。这些条件由断言(predicate)进行指定(断言指出了关于某件事情的一种可能的事实)。如果该断言对于某个给定的行成立,该行将被包括到结果表中,否则该行被忽略。在SQL语句中断言通常通过比较来表示。例如,假如你需要查询所有姓为Jones的职员,则可以使用以下Select语句:
- Select * FROM EMPLOYEES
- Where LAST_NAME = 'Jones';
- LAST_NAME = 'Jones'部分就是断言。在执行该语句时,SQL将每一行的LAST_NAME列与“Jones”进行比较。如果某一职员的姓为“Jones”,即断言成立,该职员的信息将被包括到结果表中(见表6)。
- 使用最多的六种比较
- 我们上例中的断言包括一种基于“等值”的比较(LAST_NAME = 'Jones'),但是SQL断言还可以包含其他几种类型的比较。其中最常用的为:
- 等于 =
- 不等于 <>
- 小于 <
- 大于 >
- 小于或等于 <=
- 大于或等于 >=
- 下面给出了不是基于等值比较的一个例子:
- Select * FROM EMPLOYEES
- Where SALARY > 50000;
- 这一查询将返回年薪高于$50,000.00的职员(参见表7)。
- 逻辑连接符
- 有时我们需要定义一条不止一种断言的Select语句。举例来说,如果你仅仅想查看Davy Jones的信息的话,表6中的结果将是不正确的。为了进一步定义一个Where子句,用户可以使用逻辑连接符AND,OR和NOT。为了只得到职员Davy Jones的记录,用户可以输入如下语句:
- Select * FROM EMPLOYEES
- Where LAST_NAME = 'Jones' AND FIRST_NAME = 'Davy';
- 在本例中,我们通过逻辑连接符AND将两个断言连接起来。只有两个断言都满足时整个表达式才会满足。如果用户需要定义一个Select语句来使得当其中任何一项成立就满足条件时,可以使用OR连接符:
- Select * FROM EMPLOYEES
- Where LAST_NAME = 'Jones' OR LAST_NAME = 'Smith';
- 有时定义一个断言的最好方法是通过相反的描述来说明。如果你想要查看除了Boston办事处的职员以外的其他所有职员的信息时,你可以进行如下的查询:
- Select * FROM EMPLOYEES
- Where NOT(BRANCH_OFFICE = 'Boston');
- 关键字NOT后面跟着用圆括号括起来的比较表达式。其结果是对结果取否定。如果某一职员所在部门的办事处在Boston,括号内的表达式返回true,但是NOT操作符将该值取反,所以该行将不被选中。
- 断言可以与其他的断言嵌套使用。为了保证它们以正确的顺序进行求值,可以用括号将它们括起来:
- Select * FROM EMPLOYEES
- Where (LAST_NAME = 'Jones'
- AND FIRST_NAME = 'Indiana')
- OR (LAST_NAME = 'Smith'
- AND FIRST_NAME = 'Bessie');
- SQL沿用数学上标准的表达式求值的约定—圆括号内的表达式将最先进行求值,其他表达式将从左到右进行求值。
- 以上对逻辑连接符进行了说明,在对下面的内容进行说明之前,我们再一次对Select语句的语法进行更新:
- Select [DISTINCT]
- (column [{, column } ] )| *
- FROM table [ { , table} ]
- [ORDER BY column [ASC] | [DESC
- [{ , column [ASC] | [DESC } ] ]
- Where predicate [ { logical-connector predicate } ];
- NULL和三值逻辑
- 在SQL中NULL是一个复杂的话题,关于NULL的详细描述更适合于在SQL的高级教程而不是现在的入门教程中进行介绍。但由于NULL需要进行特殊处理,并且你也很可能会遇到它,所以我们还是简略地进行一下说明。
- 首先,在断言中进行NULL判断时需要特殊的语法。例如,如果用户需要显示所有年薪未知的职员的全部信息,用户可以使用如下Select语句:
- Select * FROM EMPLOYEES
- Where SALARY IS NULL;
- 相反,如果用户需要所有已知年薪数据的职员的信息,你可以使用以下语句:
- Select * FROM EMPLOYEES
- Where SALARY IS NOT NULL;
- 请注意我们在列名之后使用了关键字IS NULL或IS NOT NULL,而不是标准的比较形式:COLUMN = NULL、COLUMN <> NULL或是逻辑操作符NOT(NULL)。
- 这种形式相当简单。但当你不明确地测试NULL(而它们确实存在)时,事情会变得很混乱。
- 例如,回过头来看我们图1中的EM-PLOYEES表,可以看到Indiana Jones的工薪等级或年薪值都是未知的。这两个列都包含NULL。可以想象运行如下的查询:
- Select * FROM EMPLOYEES
- Where GRADE <= SALARY;
- 此时,Indiana Jones应该出现在结果表中。因为NULL都是相等的,所以可以想象它们是能够通过GRADE小于等于SALARY的检查的。这其实是一个毫无疑义的查询,但是并没有关系。SQL允许进行这样的比较,只要两个列都是数字类型的。然而,Indiana Jones并没有出现在查询的结果中,为什么?
- 正如我们早先提到过的,NULL表示未知的值(而不是象某些人所想象的那样表示一个为NULL的值)。对于SQL来说意味着这个值是未知的,而只要这个值为未知,就不能将其与其他值比较(即使其他值也是NULL)。所以SQL允许除了在true 和false之外还有第三种类型的真值,称之为“非确定”(unknown)值。
- 如果比较的两边都是NULL,整个断言就被认为是非确定的。将一个非确定断言取反或使用AND或OR与其他断言进行合并之后,其结果仍是非确定的。由于结果表中只包括断言值为“真”的行,所以NULL不可能满足该检查。从而需要使用特殊的操作符IS NULL和IS NOT NULL。
- Update语句
- Update语句允许用户在已知的表中对现有的行进行修改。
- 例如,我们刚刚发现Indiana Jones的等级为16,工资为$40,000.00,我们可以通过下面的SQL语句对数据库进行更新(并清除那些烦人的NULL)。
- Update EMPLOYEES
- SET GRADE = 16, SALARY = 40000
- Where FIRST_NAME = 'Indiana'
- AND LAST_NAME = 'Jones';
- 上面的例子说明了一个单行更新,但是Update语句可以对多行进行操作。满足Where条件的所有行都将被更新。如果,你想让Boston办事处中的所有职员搬到New York,你可以使用如下语句:
- Update EMPLOYEES
- SET BRANCH_OFFICE = 'New York'
- Where BRANCH_OFFICE = 'Boston';
- 如果忽略Where子句,表中所有行中的部门值都将被更新为'New York'。
- Update语句的语法流图如下面所示:
- Update table
- SET column = value [{, column = value}]
- [ Where predicate [ { logical-connector predicate}]];
- Delete语句
- Delete语句用来删除已知表中的行。如同Update语句中一样,所有满足Where子句中条件的行都将被删除。由于SQL中没有UNDO语句或是“你确认删除吗?”之类的警告,在执行这条语句时千万要小心。如果决定取消Los Angeles办事处并解雇办事处的所有职员,这一卑鄙的工作可以由以下这条语句来实现:
- Delete FROM EMPLOYEES
- Where BRANCH_OFFICE = 'Los Angeles';
- 如同Update语句中一样,省略Where子句将使得操作施加到表中所有的行。
- Delete语句的语法流图如下面所示:
- Delete FROM table
- [Where predicate [ { logical-connector predicate} ] ];
- 现在我们完成了数据操作语言(DML)的主要语句的介绍。我们并没有对SQL能完成的所有功能进行说明。SQL还提供了许多的功能,如求平均值、求和以及其他对表中数据的计算,此外SQL还能完成从多个表中进行查询(多表查询,或称之为连接)的工作。这种语言还允许你使用GRANT和REVOKE命令控制使用者的数据访问权限。
sql 经典
作者:admin 日期:2010-03-14
- 下列语句部分是Mssql语句,不可以在access中使用。
- SQL分类:
- DDL—数据定义语言(Create,Alter,Drop,DECLARE)
- DML—数据操纵语言(Select,Delete,Update,Insert)
- DCL—数据控制语言(GRANT,REVOKE,COMMIT,ROLLBACK)
- 首先,简要介绍基础语句:
- 1、说明:创建数据库
- Create DATABASE database-name
- 2、说明:删除数据库
- drop database dbname
- 3、说明:备份sql server
- --- 创建 备份数据的 device
- USE master
- EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'
- --- 开始 备份
- BACKUP DATABASE pubs TO testBack
- 4、说明:创建新表
- create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
- 根据已有的表创建新表:
- A:create table tab_new like tab_old (使用旧表创建新表)
- B:create table tab_new as select col1,col2… from tab_old definition only
- 5、说明:删除新表drop table tabname
- 6、说明:增加一个列
- Alter table tabname add column col type
- 注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。
- 7、说明:添加主键: Alter table tabname add primary key(col)
- 说明:删除主键: Alter table tabname drop primary key(col)
- 8、说明:创建索引:create [unique] index idxname on tabname(col….)
- 删除索引:drop index idxname
- 注:索引是不可更改的,想更改必须删除重新建。
- 9、说明:创建视图:create view viewname as select statement
- 删除视图:drop view viewname
- 10、说明:几个简单的基本的sql语句
- 选择:select * from table1 where 范围
- 插入:insert into table1(field1,field2) values(value1,value2)
- 删除:delete from table1 where 范围
- 更新:update table1 set field1=value1 where 范围
- 查找:select * from table1 where field1 like ’%value1%’ ---like的语法很精妙,查资料!
- 排序:select * from table1 order by field1,field2 [desc]
- 总数:select count * as totalcount from table1
- 求和:select sum(field1) as sumvalue from table1
- 平均:select avg(field1) as avgvalue from table1
- 最大:select max(field1) as maxvalue from table1
- 最小:select min(field1) as minvalue from table1
- 11、说明:几个高级查询运算词
- A: UNION 运算符
- UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2。
- B: EXCEPT 运算符
- EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。
- C: INTERSECT 运算符
- INTERSECT 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL 随 INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。
- 注:使用运算词的几个查询结果行必须是一致的。
- 12、说明:使用外连接
- A、left outer join:
- 左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。
- SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
- B:right outer join:
- 右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。
- C:full outer join:
- 全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
- 其次,大家来看一些不错的sql语句
- 1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)
- 法一:select * into b from a where 1<>1
- 法二:select top 0 * into b from a
- 2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)
- insert into b(a, b, c) select d,e,f from b;
- 3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)
- insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件
- 例子:..from b in '"&Server.MapPath(".")&"\data.mdb" &"' where..
- 4、说明:子查询(表名1:a 表名2:b)
- select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3)
- 5、说明:显示文章、提交人和最后回复时间
- select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
- 6、说明:外连接查询(表名1:a 表名2:b)
- select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
- 7、说明:在线视图查询(表名1:a )
- select * from (Select a,b,c FROM a) T where t.a > 1;
- 8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括
- select * from table1 where time between time1 and time2
- select a,b,c, from table1 where a not between 数值1 and 数值2
- 9、说明:in 的使用方法
- select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)
- 10、说明:两张关联表,删除主表中已经在副表中没有的信息
- delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )
- 11、说明:四表联查问题:
- select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....
- 12、说明:日程安排提前五分钟提醒
- SQL: select * from 日程安排 where datediff('minute',f开始时间,getdate())>5
- 13、说明:一条sql 语句搞定数据库分页
- select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段
- 14、说明:前10条记录
- select top 10 * form table1 where 范围
- 15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)
- select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)
- 16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表
- (select a from tableA ) except (select a from tableB) except (select a from tableC)
- 17、说明:随机取出10条数据
- select top 10 * from tablename order by newid()
- 18、说明:随机选择记录
- select newid()
- 19、说明:删除重复记录
- Delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
- 20、说明:列出数据库里所有的表名
- select name from sysobjects where type='U'
- 21、说明:列出表里的所有的
- select name from syscolumns where id=object_id('TableName')
- 22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。
- select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type
- 显示结果:
- type vender pcs
- 电脑 A 1
- 电脑 A 1
- 光盘 B 2
- 光盘 A 2
- 手机 B 3
- 手机 C 3
- 23、说明:初始化表table1
- TRUNCATE TABLE table1
- 24、说明:选择从10到15的记录
- select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc
- 随机选择数据库记录的方法(使用Randomize函数,通过SQL语句实现)
- 对存储在数据库中的数据来说,随机数特性能给出上面的效果,但它们可能太慢了些。你不能要求ASP“找个随机数”然后打印出来。实际上常见的解决方案是建立如下所示的循环:
- Randomize
- RNumber = Int(Rnd*499) +1
- While Not objRec.EOF
- If objRec("ID") = RNumber THEN
- ... 这里是执行脚本 ...
- end if
- objRec.MoveNext
- Wend
- 这很容易理解。首先,你取出1到500范围之内的一个随机数(假设500就是数据库内记录的总数)。然后,你遍历每一记录来测试ID 的值、检查其是否匹配RNumber。满足条件的话就执行由THEN 关键字开始的那一块代码。假如你的RNumber 等于495,那么要循环一遍数据库花的时间可就长了。虽然500这个数字看起来大了些,但相比更为稳固的企业解决方案这还是个小型数据库了,后者通常在一个数据库内就包含了成千上万条记录。这时候不就死定了?
- 采用SQL,你就可以很快地找出准确的记录并且打开一个只包含该记录的recordset,如下所示:
- Randomize
- RNumber = Int(Rnd*499) + 1
- SQL = "Select * FROM Customers Where ID = " & RNumber
- set objRec = ObjConn.Execute(SQL)
- Response.WriteRNumber & " = " & objRec("ID") & " " & objRec("c_email")
- 不必写出RNumber 和ID,你只需要检查匹配情况即可。只要你对以上代码的工作满意,你自可按需操作“随机”记录。Recordset没有包含其他内容,因此你很快就能找到你需要的记录这样就大大降低了处理时间。
- 再谈随机数
- 现在你下定决心要榨干Random 函数的最后一滴油,那么你可能会一次取出多条随机记录或者想采用一定随机范围内的记录。把上面的标准Random 示例扩展一下就可以用SQL应对上面两种情况了。
- 为了取出几条随机选择的记录并存放在同一recordset内,你可以存储三个随机数,然后查询数据库获得匹配这些数字的记录:
- SQL = "Select * FROM Customers Where ID = " & RNumber & " OR ID = " & RNumber2 & " OR ID = " & RNumber3
- 假如你想选出10条记录(也许是每次页面装载时的10条链接的列表),你可以用BETWEEN 或者数学等式选出第一条记录和适当数量的递增记录。这一操作可以通过好几种方式来完成,但是 Select 语句只显示一种可能(这里的ID 是自动生成的号码):
- SQL = "Select * FROM Customers Where ID BETWEEN " & RNumber & " AND " & RNumber & "+ 9"
- 注意:以上代码的执行目的不是检查数据库内是否有9条并发记录。
- 随机读取若干条记录,测试过
- Access语法:Select top 10 * From 表名 ORDER BY Rnd(id)
- Sql server:select top n * from 表名 order by newid()
- mysqlelect * From 表名 Order By rand() Limit n
- Access左连接语法(最近开发要用左连接,Access帮助什么都没有,网上没有Access的SQL说明,只有自己测试, 现在记下以备后查)
- 语法elect table1.fd1,table1,fd2,table2.fd2 From table1 left join table2 on table1.fd1,table2.fd1 where ...
- 使用SQL语句 用...代替过长的字符串显示
- 语法:
- SQL数据库:select case when len(field)>10 then left(field,10)+'...' else field end as news_name,news_id from tablename
- Access数据库:Select iif(len(field)>2,left(field,2)+'...',field) FROM tablename;
- Conn.Execute说明
- Execute方法
- 该方法用于执行SQL语句。根据SQL语句执行后是否返回记录集,该方法的使用格式分为以下两种:
- 1.执行SQL查询语句时,将返回查询得到的记录集。用法为:
- Set 对象变量名=连接对象.Execute("SQL 查询语言")
- Execute方法调用后,会自动创建记录集对象,并将查询结果存储在该记录对象中,通过Set方法,将记录集赋给指定的对象保存,以后对象变量就代表了该记录集对象。
- 2.执行SQL的操作性语言时,没有记录集的返回。此时用法为:
- 连接对象.Execute "SQL 操作性语句" [, RecordAffected][, Option]
- ·RecordAffected 为可选项,此出可放置一个变量,SQL语句执行后,所生效的记录数会自动保存到该变量中。通过访问该变量,就可知道SQL语句队多少条记录进行了操作。
- ·Option 可选项,该参数的取值通常为adCMDText,它用于告诉ADO,应该将Execute方法之后的第一个字符解释为命令文本。通过指定该参数,可使执行更高效。
- ·BeginTrans、RollbackTrans、CommitTrans方法
- 这三个方法是连接对象提供的用于事务处理的方法。BeginTrans用于开始一个事物;RollbackTrans用于回滚事务;CommitTrans用于提交所有的事务处理结果,即确认事务的处理。
- 事务处理可以将一组操作视为一个整体,只有全部语句都成功执行后,事务处理才算成功;若其中有一个语句执行失败,则整个处理就算失败,并恢复到处里前的状态。
- BeginTrans和CommitTrans用于标记事务的开始和结束,在这两个之间的语句,就是作为事务处理的语句。判断事务处理是否成功,可通过连接对象的Error集合来实现,若Error集合的成员个数不为0,则说明有错误发生,事务处理失败。Error集合中的每一个Error对象,代表一个错误信息。
SQL精华收集-2
作者:admin 日期:2010-03-14
- 每一种物品有很多价格,每一种物品选择排在前三的纪录
- 1。job的使用:
- DBMS_JOB.SUBMIT(:jobno,//job号
- 'your_procedure;',//要执行的过程
- trunc(sysdate)+1/24,//下次执行时间
- 'trunc(sysdate)+1/24+1'//每次间隔时间
- );
- 删除job:dbms_job.remove(jobno);
- 修改要执行的操作:job:dbms_job.what(jobno,what);
- 修改下次执行时间:dbms_job.next_date(job,next_date);
- 修改间隔时间:dbms_job.interval(job,interval);
- 停止job:dbms.broken(job,broken,nextdate);
- 启动job:dbms_job.run(jobno);
- 例子:
- VARIABLE jobno number;
- begin
- DBMS_JOB.SUBMIT(:jobno,
- 'Procdemo;',//Procdemo为过程名称
- SYSDATE, 'SYSDATE + 1/720');
- commit;
- end;
- /*----------------------------------*/
- 2。把一个表放在内存里
- alter table tablename cache.
- /*----------------------------------*/
- 3。创建临时表
- Create GLOBAL TEMPORARY TABLE TABLENAME (
- COL1 VARCHAR2(10),
- COL2 NUMBER
- ) ON COMMIT PRESERVE(Delete) ROWS ;
- 这种临时表不占用表空间,而且不同的SESSION之间互相看不到对方的数据
- 在会话结束后表中的数据自动清空,如果选了Delete ROWS,则在提交的时候即清
- 空数据,PRESERVE则一直到会话结束
- /*----------------------------------*/
- 4。加一个自动增加的id号
- 第一种方法:
- 第一步:创建SEQUENCE
- create sequence s_country_id increment by 1 start with 1 maxvalue
- 999999999;
- 第二步:创建一个基于该表的before insert 触发器,在触发器中使用该
- SEQUENCE
- create or replace trigger bef_ins_t_country_define
- before insert on t_country_define
- referencing old as old new as new for each row
- begin
- select s_country_id.nextval into :new.country_id from dual;
- end;
- /
- 第二种方法:
- Create OR REPLACE TRIGGER TR1
- BEFORE Insert ON temp_table
- FOR EACH ROW
- declare
- com_num NUMBER;
- BEGIN
- Select MAX(ID) INTO COM_NUM FROM TEMP_TABLE;
- :NEW.ID:=COM_NUM+1;
- END TR1;
- /*----------------------------------*/
- 5。限制用户登录:创建一个概要文件
- create profile CLERK_PROFILE limit
- session_per_user 1 #用户可拥有的会话次数
- idle_time 10 #进程处于空闲状态的时间(10分钟)
- 然后就可以将该概要文件授予一个用户
- alter user A profile CLERK_PROFILE;
- /*----------------------------------*/
- 6。使触发器为无效alter trigger yourtriggername disable
- 如果是对于某一个表的所有的触发器:
- alter table yourtablename disable all triggers
- 更改数据库时间显示格式:
- SQL> alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
- 会话已更改。
- 1. 选取 TOP N 行记录
- A. Select * FROM CAT Where ROWNUM<=N
- B. Select * FROM
- ( Select * FROM CAT ORDER BY TABLE_TYPE )
- Where ROWNUM<=N
- 2. 选取N1-N2行记录
- A. Select TABLE_NAME,TABLE_TYPE FROM
- ( Select ROWNUM ROWSEQ,TABLE_NAME,TABLE_TYPE FROM CAT )
- Where ROWSEQ BETWEEN N1+1 AND N2;
- 或:
- Select * FROM CAT Where ROWNUM<=N2
- MINUS
- Select * FROM CAT Where ROWNUM
- B. Select TABLE_NAME,TABLE_TYPE FROM
- ( Select ROWNUM ROWSEQ,TABLE_NAME,TABLE_TYPE FROM CAT ORDER BY TABLE_TYPE)
- Where ROWSEQ BETWEEN N1+1 AND N2;
- 查主键名称:
- select * from user_constraints
- where table_name = 'ART'
- and constraint_type ='P';
- 保存过程内容到文件
- 先修改init.ora
- 例如:
- utl_file_dir=/usr //路径为 oracle所在的盘:/usr
- 此过程将用户TEMP的P1过程的代码保存到ORACLE安装盘下/USR/TEXT.TXT中
- create or replace procedure TEST
- is
- file_handle utl_file.file_type;
- STOR_TEXT VARCHAR2(4000);
- N NUMBER;
- I NUMBER;
- begin
- I:=1;
- Select MAX(LINE) INTO N FROM ALL_SOURCE Where OWNER='TEMP' AND NAME='P1';
- file_handle:=utl_file.fopen('/usr','test.txt','a');
- WHILE I<=N LOOP
- Select TEXT INTO STOR_TEXT FROM ALL_SOURCE Where OWNER='TEMP' AND NAME='P1' AND LINE= I;
- I:=I+1;
- utl_file.put_line(file_handle,stor_text);
- END LOOP;
- utl_file.fclose(file_handle);
- commit;
- end TEST;
- /
- 0、建立分区表
- create table partition_test
- (
- id number(9),
- tmpStr varchar2(10)
- )
- partition by range(id)
- (
- partition id01 values less than (3000000) tablespace test_tabspc1,
- partition id02 values less than (6000000) tablespace test_tabspc2,
- partition id03 values less than (9000000) tablespace test_tabspc3,
- partition id04 values less than (12000000) tablespace test_tabspc4,
- partition id05 values less than (MAXVALUE) tablespace test_tabspc5
- )
- /
- 1、建立局部分区索引
- Create index your_index on caishui.partition_test(id)
- local
- (
- partition id01 tablespace test_tabspc1,
- partition id02 tablespace test_tabspc2,
- partition id03 tablespace test_tabspc3,
- partition id04 tablespace test_tabspc4,
- partition id05 tablespace test_tabspc5
- )
- /
- 2、重建某一个分区的索引
- alter index your_index rebuild partition id01 tablespace test_tabspc1
- /
- 3、增加分区
- alter table caishui.partition_test
- add partition id06 values less than (15000000) tablespace test_tabspc6
- /
- 4、有影响
- 5、可以
- Alter TABLE PARTITION_TEST
- MERGE PARTITIONS
- id01, id02
- INTO PARTITION 新分区名
- /
- 6、外部数据文件 d:\test.txt
- 1|猪八戒
- 2|孙悟空
- 3|唐僧
- 建一个控制文件 d:\test.ctl
- load data
- infile 'd:\test.txt'
- append
- into table partition_test
- FIELDS TERMINATED BY "|"
- (id,tmpStr)
- 将数据文件的数据导入数据库
- sqlldr userid=caishui/password control=d:\test.ctl
- 如何正确利用Rownum来限制查询所返回的行数?
- 软件环境:
- 1、Windows NT4.0+ORACLE 8.0.4
- 2、ORACLE安装路径为:C:\ORANT
- 含义解释:
- 1、rownum是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,
- 依此类推,这个伪字段可以用于限制查询返回的总行数。
- 2、rownum不能以任何基表的名称作为前缀。
- 使用方法:
- 现有一个商品销售表sale,表结构为:
- month char(6) --月份
- sell number(10,2) --月销售金额
- create table sale (month char(6),sell number);
- insert into sale values('200001',1000);
- insert into sale values('200002',1100);
- insert into sale values('200003',1200);
- insert into sale values('200004',1300);
- insert into sale values('200005',1400);
- insert into sale values('200006',1500);
- insert into sale values('200007',1600);
- insert into sale values('200101',1100);
- insert into sale values('200202',1200);
- insert into sale values('200301',1300);
- insert into sale values('200008',1000);
- commit;
- SQL> select rownum,month,sell from sale where rownum=1;(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标)
- ROWNUM MONTH SELL
- --------- ------ ---------
- 1 200001 1000
- SQL> select rownum,month,sell from sale where rownum=2;(1以上都查不到记录)
- 没有查到记录
- SQL> select rownum,month,sell from sale where rownum>5;
- (由于rownum是一个总是从1开始的伪列,Oracle 认为这种条件不成立,查不到记录)
- 没有查到记录
- 只返回前3条纪录
- SQL> select rownum,month,sell from sale where rownum<4;
- ROWNUM MONTH SELL
- --------- ------ ---------
- 1 200001 1000
- 2 200002 1100
- 3 200003 1200
- 如何用rownum实现大于、小于逻辑?(返回rownum在4—10之间的数据)(minus操作,速度会受影响)
- SQL> select rownum,month,sell from sale where rownum<10
- 2 minus
- 3 select rownum,month,sell from sale where rownum<5;
- ROWNUM MONTH SELL
- --------- ------ ---------
- 5 200005 1400
- 6 200006 1500
- 7 200007 1600
- 8 200101 1100
- 9 200202 1200
- 想按日期排序,并且用rownum标出正确序号(有小到大)
- SQL> select rownum,month,sell from sale order by month;
- ROWNUM MONTH SELL
- --------- ------ ---------
- 1 200001 1000
- 2 200002 1100
- 3 200003 1200
- 4 200004 1300
- 5 200005 1400
- 6 200006 1500
- 7 200007 1600
- 11 200008 1000
- 8 200101 1100
- 9 200202 1200
- 10 200301 1300
- 查询到11记录.
- 可以发现,rownum并没有实现我们的意图,系统是按照记录入库时的顺序给记录排的号,rowid也是顺序分配的
- SQL> select rowid,rownum,month,sell from sale order by rowid;
- ROWID ROWNUM MONTH SELL
- ------------------ --------- ------ ---------
- 000000E4.0000.0002 1 200001 1000
- 000000E4.0001.0002 2 200002 1100
- 000000E4.0002.0002 3 200003 1200
- 000000E4.0003.0002 4 200004 1300
- 000000E4.0004.0002 5 200005 1400
- 000000E4.0005.0002 6 200006 1500
- 000000E4.0006.0002 7 200007 1600
- 000000E4.0007.0002 8 200101 1100
- 000000E4.0008.0002 9 200202 1200
- 000000E4.0009.0002 10 200301 1300
- 000000E4.000A.0002 11 200008 1000
- 查询到11记录.
- 正确用法,使用子查询
- SQL> select rownum,month,sell from (select month,sell from sale group by month,sell) where rownum<13;
- ROWNUM MONTH SELL
- --------- ------ ---------
- 1 200001 1000
- 2 200002 1100
- 3 200003 1200
- 4 200004 1300
- 5 200005 1400
- 6 200006 1500
- 7 200007 1600
- 8 200008 1000
- 9 200101 1100
- 10 200202 1200
- 11 200301 1300
- 按销售金额排序,并且用rownum标出正确序号(有小到大)
- SQL> select rownum,month,sell from (select sell,month from sale group by sell,month) where rownum<13;
- ROWNUM MONTH SELL
- --------- ------ ---------
- 1 200001 1000
- 2 200008 1000
- 3 200002 1100
- 4 200101 1100
- 5 200003 1200
- 6 200202 1200
- 7 200004 1300
- 8 200301 1300
- 9 200005 1400
- 10 200006 1500
- 11 200007 1600
- 查询到11记录.
- 利用以上方法,如在打印报表时,想在查出的数据中自动加上行号,就可以利用rownum。
- 返回第5—9条纪录,按月份排序
- SQL> select * from (select rownum row_id ,month,sell
- 2 from (select month,sell from sale group by month,sell))
- 3 where row_id between 5 and 9;
- ROW_ID MONTH SELL
- ---------- ------ ----------
- 5 200005 1400
- 6 200006 1500
- 7 200007 1600
- 8 200008 1000
- 9 200101 1100
- (1)
- 查所及杀锁
- select l.session_id sid,
- l.locked_mode lockmode,
- l.oracle_username db_user,
- l.os_user_name os_user,
- s.machine,
- s.schemaname,
- o.object_name tablename,
- q.sql_text
- from v$locked_object l, v$session s, v$sql q, all_objects o
- where l.session_id=s.sid and
- s.type='USER' and
- s.sql_address=q.address and
- l.object_id=o.object_id
- alter system kill session 'sid,SERIAL#'
- 1.having 子句的用法
- having 子句对 group by 子句所确定的行组进行控制,having 子句条件中只允许涉及常量,聚组函数或group by 子句中的列.
- 2.外部联接"+"的用法
- 外部联接"+"按其在"="的左边或右边分左联接和右联接.若不带"+"运算符的表中的一个行不直接匹配于带"+"预算符的表中的任何行,则前者的行与 后者中的一个空行相匹配并被返回.若二者均不带’+’,则二者中无法匹配的均被返回.利用外部联接"+",可以替代效率十分低下的 not in 运算,大大提高运行速度.例如,下面这条命令执行起来很慢
- select a.empno from emp a where a.empno not in
- (select empno from emp1 where job=’SALE’);
- 倘若利用外部联接,改写命令如下:
- select a.empno from emp a ,emp1 b
- where a.empno=b.empno(+)
- and b.empno is null
- and b.job=’SALE’;
- 可以发现,运行速度明显提高.
- 3.删除表内重复记录的方法
- 可以利用这样的命令来删除表内重复记录:
- delete from table_name a
- where rowid< (select max(rowid) from table_name
- where column1=a.column1 and column2=a.column2
- and colum3=a.colum3 and ...);
- 问:用ORACLE的like(匹配操作命令)操作时,要查的条件含有特殊符号(_或%),该怎样写?
- 如我要找出以tt_开头的表,若安以下写法只能取出以tt开头的表,
- 因为_在like中用意是任意单一字符。
- Select Tname FROM tab
- Where Tname like 'tt_%'
- 答:Select * FROM tab
- Where tname LIKE 'TT/_%' ESCAPE '/'
- 自增字段:
- ORACLE一般的做法是同时使用序列和触发器来生成一个自增字段.
- Create SEQUENCE SEQname
- INCREMENT BY 1
- START WITH 1
- MAXVALUE 99999999
- /
- Create TRIGGER TRGname
- BEFORE Insert ON table_name
- REFERENCING
- NEW AS :NEW
- FOR EACH ROW
- Begin
- Select SEQname.NEXTVAL
- INTO :NEW.FIELDname
- FROM DUAL;
- End;
- /
- 动态sql:
- 在oracle8.1.5中:
- 用execute immediate来实现
- declare
- tsql varchar2(200);
- begin
- tsql:='insert into '||tname||'values ('aaa','bbb')';
- execute immediate tsql;
- end;
- /
- 说明:复制表(只复制结构,源表名:a 新表名:b)
- SQL: select * into b from a where 1<>1
- 说明:拷贝表(拷贝数据,源表名:a 目标表名:b)
- SQL: insert into b(a, b, c) select d,e,f from b;
- 说明:显示文章、提交人和最后回复时间
- SQL: select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
- 说明:外连接查询(表名1:a 表名2:b)
- SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
- 说明:日程安排提前五分钟提醒
- SQL: select * from 日程安排 where datediff('minute',f开始时间,getdate())>5
- 说明:两张关联表,删除主表中已经在副表中没有的信息
- SQL:
- delete from info where not exists ( select * from infobz where info.infid=infobz.infid )
- 说明:--
- SQL:
- Select A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE
- FROM TABLE1,
- (Select X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE
- FROM (Select NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND
- FROM TABLE2
- Where TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(SYSDATE, 'YYYY/MM')) X,
- (Select NUM, UPD_DATE, STOCK_ONHAND
- FROM TABLE2
- Where TO_CHAR(UPD_DATE,'YYYY/MM') =
- TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, 'YYYY/MM') || '/01','YYYY/MM/DD') - 1, 'YYYY/MM') ) Y,
- Where X.NUM = Y.NUM (+)
- AND X.INBOUND_QTY + NVL(Y.STOCK_ONHAND,0) <> X.STOCK_ONHAND ) B
- Where A.NUM = B.NUM
- 说明:--
- SQL:
- select * from studentinfo where not exists(select * from student where studentinfo.id=student.id) and 系名称='"&strdepartmentname&"' and 专业名称='"&strprofessionname&"' order by 性别,生源地,高考总成绩
- 说明:
- 从数据库中去一年的各单位电话费统计(电话费定额贺电化肥清单两个表来源)
- SQL:
- Select a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy') AS telyear,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '01', a.factration)) AS JAN,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '02', a.factration)) AS FRI,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '03', a.factration)) AS MAR,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '04', a.factration)) AS APR,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '05', a.factration)) AS MAY,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '06', a.factration)) AS JUE,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '07', a.factration)) AS JUL,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '08', a.factration)) AS AGU,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '09', a.factration)) AS SEP,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '10', a.factration)) AS OCT,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '11', a.factration)) AS NOV,
- SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '12', a.factration)) AS DEC
- FROM (Select a.userper, a.tel, a.standfee, b.telfeedate, b.factration
- FROM TELFEESTAND a, TELFEE b
- Where a.tel = b.telfax) a
- GROUP BY a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy')
- 说明:四表联查问题:
- SQL: select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....
- 说明:得到表中最小的未使用的ID号
- SQL:
- Select (CASE WHEN EXISTS(Select * FROM Handle b Where b.HandleID = 1) THEN MIN(HandleID) + 1 ELSE 1 END) as HandleID
- FROM Handle
- Where NOT HandleID IN (Select a.HandleID - 1 FROM Handle a)







