目录导航
一、SQL简介
SQL (Structured Query Language:结构化查询语言)
是用于管理关系数据库管理系统(RDBMS)。
SQL 的范围包括数据插入、查询、更新和删除,数据库模式创建和修改,以及数据访问控制。
1.什么是数据库
数据库 (DB database)
概念:数据仓库 软件 安装在操作系统之上 可以存储大量的数据 500w
作用:存储数据 管理数据
2.数据库分类
关系型数据库 (SQL)
MySQL Oracle SqlServer DB2 SQLite
通过表和表之间 行和列之间的关系进行数据的存储 学员信息表 考勤表…
非关系型数据库(noSQL) Not Only
Redis mongDB
非关系型数据库 对象存储 通过对象的自身的属性来决定
3.SQL 是什么?
- SQL 指结构化查询语言,全称是 Structured Query Language。
- SQL 让您可以访问和处理数据库,包括数据插入、查询、更新和删除。
- SQL 在1986年成为 ANSI(American National Standards Institute 美国国家标准化组织)的一项标准,在 1987 年成为国际标准化组织(ISO)标准。
4.SQL 能做什么?
- SQL 面向数据库执行查询
- SQL 可从数据库取回数据
- SQL 可在数据库中插入新的记录
- SQL 可更新数据库中的数据
- SQL 可从数据库删除记录
- SQL 可创建新数据库
- SQL 可在数据库中创建新表
- SQL 可在数据库中创建存储过程
- SQL 可在数据库中创建视图
- SQL 可以设置表、存储过程和视图的权限
5.RDBMS
RDBMS 指关系型数据库管理系统,全称 Relational Database Management System。
RDBMS 是 SQL 的基础,同样也是所有现代数据库系统的基础,比如 MS SQL Server、IBM DB2、Oracle、MySQL 以及 Microsoft Access。
RDBMS 中的数据存储在被称为表的数据库对象中。
表是相关的数据项的集合,它由列和行组成。
二、基础语法
1.创建数据库
create database db-name
2.删除数据库
drop database db-name
3.创建表
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
4.删除新表
drop table tabname
5.增加一个列
Alter table tabname add column col type
注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。
6.添加主键
Alter table tabname add primary key(col)
说明:
删除主键:Alter table tabname drop primary key(col)
7.创建索引
create [unique] index idxname on tabname(col….)
删除索引:drop index idxname
注:索引是不可更改的,想更改必须删除重新建。
8.创建视图
create view viewname as select statement
删除视图:drop view viewname
9.几个简单的table操作的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
10.几个高级查询运算词
UNION 运算符
UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2。
EXCEPT 运算符
EXCEPT运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。
INTERSECT 运算符
INTERSECT运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL随 INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。
**注:**使用运算词的几个查询结果行必须是一致的。
11.使用外连接
11.1.left join
left (outer) join:左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。
- select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
复制代码 11.2.right join
right (outer) join:右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。
11.3.full/cross join
full/cross (outer) join:全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
案例
例如有如下关系的数据:
1、inner join
2.1、full outer join等于full join
2.2、full outer join but a.Key is null or b.Key is null
3.1、left outer join等于left join
3.2、left outer join but b.Key is null
笛卡尔积
12.如何修改数据库的名称
- sp_renamedb 'old_name', 'new_name'
复制代码 13.临时表
13.1.临时表的概念
在我们操作的表数据量庞大而且又要关联其他表进行查询的时候或者我们操作的数据是临时性数据且在短期内会有很多DML操作(比如购物车)的时候或者我们做查询时需要连接很多个表的时候,如果直接操作数据库的业务表可能效率很低,这个时候我们就可以借助临时表来提升效率。
临时表顾名思义,是一个临时的表,数据库不会将其序列化到磁盘上(有些也会序列化到磁盘上)而是存在于数据库服务器的内存中(因此会增加数据库服务器内存的消耗),在使用完之后就会销毁。临时表分为两种:会话临时表和全局临时表,区别在于可用的作用域和销毁的时机不同。会话临时表只在当前会话(连接)内可用,且在当前会话结束(断开数据库连接)后就会销毁;全局临时表创建后在销毁之前所有用户都可以访问,销毁的时机是在创建该临时表的连接断开且没有其他会话访问时才销毁,实际上在创建全局临时表的会话断开后,其他用户就已经不能在访问该临时表了,但此时该临时表并不会立即销毁,而是等所有正在使用该全局临时表的会话(或者说连接)断开之后才会销毁。当然有时考虑到内存占用的问题,我们也可以手动销毁(DROP)临时表。
目前大多数数据库厂商(Oracle、Sql Server、Mysql)都支持临时表,但不同的数据库创建和使用临时表的语法稍有不同。
13.2.临时表的创建、使用和删除
13.2.1.SQL Server
创建:
方式一:
- #会话临时表
- CREATE TABLE #临时表名(
- 字段1 约束条件1,
- 字段2 约束条件2,
- ...
- );
- #全局临时表
- CREATE TABLE ##临时表名(
- 字段1 约束条件,
- 字段2 约束条件,
- ...
- );
复制代码 方式二:
- #会话临时表
- SELECT 字段列表 INTO #临时表名
- FROM 业务表;
- #全局临时表
- SELECT 字段列表 INTO ##临时表名
- FROM 业务表;
复制代码 使用:
- #查询临时表
- SELECT * FROM #临时表名;
- SELECT * FROM ##临时表名;
复制代码 删除:
- #删除临时表
- DROP TABLE #临时表名;
- DROP TABLE ##临时表名;
复制代码 13.2.2.Mysql
创建:
Mysql中没有全局临时表,创建的时候没有#
- CREATE TEMPORARY TABLE [IF NOT EXISTS] 临时表名(
- 字段1 约束条件,
- 字段2 约束条件,
- ...
- );
- #根据现有表创建临时表
- CREATE TEMPORARY TABLE [IF NOT EXISTS] 临时表名
- [AS] SELECT 查询字段
- FROM 业务表
- [WHERE 条件];
复制代码 使用:
创建的临时表可以和业务表同名,若临时表和业务表同名时在该会话中会使用临时表
删除:
为避免临时表名和业务表名相同时导致误删除,可以加上TEMPORARY关键字
- DROP [TEMPORARY] TABLE 临时表名;
复制代码 13.2.3.Oracle
Oracle的临时表也只有会话级的,但同时又细化出了一个事务级别的临时表,事务级别的临时表只在当前事务中有效。
创建:
- #会话级别
- CREATE GLOBAL TEMPORARY TABLE 临时表名(
- 字段1 约束条件,
- 字段2 约束条件,
- ...
- ) ON COMMIT PRESERVE ROWS;
- #事务级别
- CREATE GLOBAL TEMPORARY TABLE 临时表名(
- 字段1 约束条件,
- 字段2 约束条件,
- ...
- ) ON COMMIT DELETE ROWS;
复制代码 使用:
删除:
注意:一个SQL中不能同时出现两次临时表
13.3.临时表的应用
企业开发中大多都是使用Spring进行事务管理的,很少自己开启事务、提交事务。我们大多都会将事务加在service层,这样在调用service层的每一个方法之前Spring都会为我们开启事务,在方法调用结束之后Spring会为我们提交事务,问题是数据库事务需要的数据库连接是在什么时候获取和释放的呢?这个是会影响我们对临时表的使用的。
一般来说,数据库连接是在事务开启之前获取的,也就是在我们调用事务方法之前,肯定要先获取数据库连接,然后才能开启事务,提交或回滚事务,然后关闭数据库连接,这种情况下貌似如果我们在该方法中创建了临时表,则在此之后直至方法结束之前我们都可以使用这个创建的临时表,这么说基本上是正确的。但有一种情况除外那就是如果我们在事务方法A中调用了另一个事务方法B,而事务方法B的事务传播机制是PROPAGATION_REQUIRES_NEW(将原事务挂起,并新开一个事务)时,如果临时表是在B方法中创建的,则A在调用完B之后(B的事务已经提交了)也不可以使用B中创建的事务级别的临时表,但是可以使用会话级别的临时表以及全局临时表。
三.SQL语句提升
1.复制表
(只复制结构,源表名:a 新表名:b) (Access可用)
- 法一:select * into b from a where 1<>1(仅用于SQlServer)
- 法二:select top 0 * into b from a
复制代码 2.拷贝表
(拷贝数据,源表名:a 目标表名:b) (Access可用)
- insert into b(a, b, c) select d,e,f from a;
- --insert into b select * from a //从表a中获取数据,并将其插入到b中,只拷贝表的数据,不拷贝表的结构(前提:表b存在)
- --select * into b from a //将a中的数据拷贝到 b中,拷贝表的数据以及表的结构(前提:表b不存在)
- --select * into b from a where 1=0// 将a的表结构拷贝到b,不拷贝数据(前提:表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 time2select 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.排序字段
复制代码 具体实现:
关于数据库分页:
- declare @start int,@end int
- @sql nvarchar(600)
- set @sql=’select top’+str(@end-@start+1)+’+from T where rid not in(select top’+str(@str-1)+’Rid from T where Rid>-1)’
- exec sp_executesql @sql
复制代码 **注意:**在top后不能直接跟一个变量,所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列,如果top后还有具体的字段,这样做是非常有好处的。因为这样可以避免 top的字段如果是逻辑索引的,查询的结果后实际表中的不一致(逻辑索引中的数据有可能和数据表中的不一致,而查询时如果处在索引则首先查询索引)
14.前10条记录
- select top 10 * form table1 where 范围
复制代码 15.随机取出10条数据
- select top 10 * from tablename order by newid()
复制代码 16.随机选择记录
17.删除重复记录
- 1),delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
- 2),select distinct * into temp from tablename
- delete from tablename
- insert into tablename select * from temp
复制代码 评价: 这种操作牵连大量的数据的移动,这种做法不适合大容量的数据操作
**例如:**在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段
- alter table tablename--添加一个自增列
- add column_b int identity(1,1)
- delete from tablename where column_b not in(select max(column_b) from tablename group by column1,column2,...)
- alter table tablename drop column column_b
复制代码 18.列出数据库里所有的表名
- select name from sysobjects where type='U' // U代表用户
复制代码 19.列出表里的所有的列名
- select name from syscolumns where id=object_id('TableName')
复制代码 20.初始化表table1
21.选择从10到15的记录
- select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id des
复制代码 四、开发技巧
1、where 1=1是表示选择全部,where 1=2全部不选
- if @strWhere !=''
- begin
- set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere
- end
- else begin
- set @strSQL = 'select count(*) as Total from [' + @tblName + ']'
- end
复制代码 我们可以直接写成
- set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 '+ @strWhere
复制代码 2、收缩数据库
- --重建索引
- DBCC REINDEX
- DBCC INDEXDEFRAG
- --收缩数据和日志
- DBCC SHRINKDB
- DBCC SHRINKFILE
复制代码 3、压缩数据库
- dbcc shrinkdatabase(dbname)
复制代码 4、转移数据库给新用户以已存在用户权限
- exec sp_change_users_login 'update_one','newname','oldname'
- go
复制代码 5、检查备份集
- RESTORE VERIFYONLY from disk='E:dvbbs.bak'
复制代码 6、修复数据库
- ALTER DATABASE [dvbbs] SET SINGLE_USER
- GO
- DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
- GO
- ALTER DATABASE [dvbbs] SET MULTI_USER
- GO
复制代码 7、日志清除
- SET NOCOUNT ONDECLARE @LogicalFileName sysname,
- @MaxMinutes INT,
- @NewSize INT
- USE tablename -- 要操作的数据库名
- SELECT @LogicalFileName = 'tablename_log', -- 日志文件名
- @MaxMinutes = 10, -- Limit on time allowed to wrap log.
- @NewSize = 1 -- 你想设定的日志文件的大小(M)
- Setup / initialize
- DECLARE @OriginalSize int
- SELECT @OriginalSize = size
- FROM sysfiles
- WHERE name = @LogicalFileName
- SELECT 'Original Size of ' + db_name() + ' LOG is ' + CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
- FROM sysfiles
- WHERE name = @LogicalFileName
- CREATE TABLE DummyTrans
- (DummyColumn char (8000) not null)
- DECLARE @Counter INT,
- @StartTime DATETIME,
- @TruncLog VARCHAR(255)
- SELECT @StartTime = GETDATE(),
- @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
- DBCC SHRINKFILE (@LogicalFileName, @NewSize)
- EXEC (@TruncLog)
- -- Wrap the log if necessary.
- WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
- AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)
- AND (@OriginalSize * 8 /1024) > @NewSize
- BEGIN -- Outer loop.
- SELECT @Counter = 0
- WHILE ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
- BEGIN -- update
- INSERT DummyTrans VALUES ('Fill Log') DELETE DummyTrans
- SELECT @Counter = @Counter + 1
- END
- EXEC (@TruncLog)
- END
- SELECT 'Final Size of ' + db_name() + ' LOG is ' + CONVERT(VARCHAR(30),size) + ' 8K pages or ' + CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
- FROM sysfiles
- WHERE name = @LogicalFileName
- DROP TABLE DummyTrans
- SET NOCOUNT OFF
复制代码 8、更改某个表
- exec sp_changeobjectowner 'tablename','dbo'
复制代码 9、存储更改全部表
- CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
- @OldOwner as NVARCHAR(128),
- @NewOwner as NVARCHAR(128)
- AS
- DECLARE @Name as NVARCHAR(128)
- DECLARE @Owner as NVARCHAR(128)
- DECLARE @OwnerName as NVARCHAR(128)
- DECLARE curObject CURSOR FOR
- select 'Name' = name,
- 'Owner' = user_name(uid)
- from sysobjects
- where user_name(uid)=@OldOwner
- order by name
- OPEN curObject
- FETCH NEXT FROM curObject INTO @Name, @Owner
- WHILE(@@FETCH_STATUS=0)
- BEGIN
- if @Owner=@OldOwner
- begin
- set @OwnerName = @OldOwner + '.' + rtrim(@Name)
- exec sp_changeobjectowner @OwnerName, @NewOwner
- end
- -- select @name,@NewOwner,@OldOwner
- FETCH NEXT FROM curObject INTO @Name, @Owner
- END
- close curObject
- deallocate curObject
- GO
复制代码 10、SQL SERVER中直接循环写入数据
[code]declare @i intset @i=1while @i=0</strong></p> 10:获取某一个表的所有字段
select name from syscolumns where id=object_id(‘表名’)
select name from syscolumns where id in (select id from sysobjects where type = ‘u’ and name = ‘表名’)
两种方式的效果相同
11:查看与某一个表相关的视图、存储过程、函数
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like ‘%表名%’
12:查看当前数据库中所有存储过程
select name as 存储过程名称 from sysobjects where xtype='P’
13:查询用户创建的所有数据库
select * from master…sysdatabases D where sid not in(select sid from master…syslogins where name=‘sa’)
或者
select dbid, name AS DB_NAME from master…sysdatabases where sid 0x01
14:查询某一个表的字段和数据类型
select column_name,data_type from information_schema.columns
where table_name = '表名’
15:不同服务器数据库之间的数据操作
–创建链接服务器
exec sp_addlinkedserver 'ITSV ', ’ ', 'SQLOLEDB ', '远程服务器名或ip地址 ’
exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用户名 ', '密码 ’
–查询示例
select * from ITSV.数据库名.dbo.表名
–导入示例
select * into 表 from ITSV.数据库名.dbo.表名
–以后不再使用时删除链接服务器
exec sp_dropserver 'ITSV ', 'droplogins ’
–连接远程/局域网数据(openrowset/openquery/opendatasource)
–1、openrowset
–查询示例
select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)
–生成本地表
select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)
–把本地表导入远程表
insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)
select *from 本地表
–更新本地表
update b
set b.列A=a.列A
from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 b
on a.column1=b.column1
**
**
–2、openquery用法需要创建一个连接
–首先创建一个连接创建链接服务器
exec sp_addlinkedserver 'ITSV ', ’ ', 'SQLOLEDB ', '远程服务器名或ip地址 ’
–查询
select *
FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')
–把本地表导入远程表
insert openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')
select * from 本地表
–更新本地表
update b
set b.列B=a.列B
FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') as a
inner join 本地表 b on a.列A=b.列A
–3、opendatasource/openrowset
SELECT *
FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ’ ).test.dbo.roy_ta
–把本地表导入远程表
insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名
select * from 本地表
SQL Server基本函数
六、SQL Server基本函数
1.字符串函数 长度与分析用
1,datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格
2,substring(expression,start,length) 取子串,字符串的****下标是从“1”,start为起始位置,length为字符串长度,实际应用中以len(expression)取得其长度
3,right(char_expr,int_expr) 返回字符串右边第int_expr个字符,还用left于之相反
4,isnull( check_ex*****pression* , *replacement_value* )如果check_expression為空,則返回replacement_value的值,不為空,就返回check_expression字符操作类
5,Sp_addtype自定义数据类型
例如:EXEC sp_addtype birthday, datetime, ‘NULL’
6,set nocount {on|off}
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。
SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。
SET NOCOUNT 为 OFF 时,返回计数常识
在SQL查询中:from后最多可以跟多少张表或视图:256
在SQL语句中出现Order by,查询时,先排序,后取
在SQL中,一个字段的最大容量是8000,而对于nvarchar(4000),由于nvarchar是Unicode码。
常识
在SQL查询中:from后最多可以跟多少张表或视图:256
在SQL语句中出现Order by,查询时,先排序,后取
在SQL中,一个字段的最大容量是8000,而对于nvarchar(4000),由于nvarchar是Unicode码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |