SQL--Structured Query Language精妙

作者: 西贝巴巴 | 来源:发表于2016-06-08 23:06 被阅读394次
    数据库操作

    什么是SQL数据库:

    SQL是Structured Query Language(结构化查询语言)的缩写。SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言。在使用它时,只需要发出“做什么”的命令,“怎么做”是不用使用者考虑的。SQL功能强大、简单易学、使用方便,已经成为了数据库操作的基础,并且现在几乎所有的数据库均支持SQL。

    一、基础

    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/cross (outer) join:
    全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
    12、分组:Group by:
    一张表,一旦分组 完成后,查询后只能得到组相关的信息。
    组相关的信息:(统计信息) count,sum,max,min,avg 分组的标准)
    在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据
    在selecte统计函数中的字段,不能和普通的字段放在一起;

    13、对数据库进行操作:
    分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后接表明,附加需要完整的路径名
    14.如何修改数据库的名称:
    sp_renamedb 'old_name', 'new_name'

    二、提升

    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 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.排序字段
    具体实现:
    关于数据库分页:

    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、说明:选择在每一组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、说明:删除重复记录
    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
    评价: 这种操作牵连大量的数据的移动,这种做法不适合大容量但数据操作
    3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段

    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

    20、说明:列出数据库里所有的表名
    select name from sysobjects where type='U' // 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

    三、技巧

    1、1=1,1=2的使用,在SQL语句组合时用的较多

    “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 ON
    DECLARE @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中直接循环写入数据
    declare @i int
    set @i=1
    while @i<30
    begin
    insert into test (userid) values(@i)
    set @i=@i+1
    end
    案例:
    有如下表,要求就裱中所有沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:

    Name     score
    Zhangshan   80
    Lishi       59
    Wangwu      5
    Songquan    69
    

    while((select min(score) from tb_table)<60)

    begin

    update tb_table set score =score*1.01

    where score<60

    if (select min(score) from tb_table)>60

    break
    else
    continue
    end

    数据开发-经典

    1.按姓氏笔画排序:
    Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as //从少到多

    2.数据库加密:
    select encrypt('原始密码')
    select pwdencrypt('原始密码')
    select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同 encrypt('原始密码')
    select pwdencrypt('原始密码')
    select pwdcompare('原始密码','加密后密码') = 1--相同;否则不相同

    3.取回表中字段:
    declare @list varchar(1000),
    @sql nvarchar(1000)
    select @list=@list+','+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name='表A'
    set @sql='select '+right(@list,len(@list)-1)+' from 表A'
    exec (@sql)

    4.查看硬盘分区:
    EXEC master..xp_fixeddrives

    5.比较A,B表是否相等:
    if (select checksum_agg(binary_checksum()) from A)
    =
    (select checksum_agg(binary_checksum(
    )) from B)
    print '相等'
    else
    print '不相等'

    6.杀掉所有的事件探察器进程:
    DECLARE hcforeach CURSOR GLOBAL FOR SELECT 'kill '+RTRIM(spid) FROM master.dbo.sysprocesses
    WHERE program_name IN('SQL profiler',N'SQL 事件探查器')
    EXEC sp_msforeach_worker '?'

    7.记录搜索:
    开头到N条记录
    Select Top N * From 表

    N到M条记录(要有主索引ID)
    Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID Desc

    N到结尾记录
    Select Top N * From 表 Order by ID Desc
    案例
    例如1:一张表有一万多条记录,表的第一个字段 RecID 是自增长字段, 写一个SQL语句, 找出表的第31到第40个记录。

    select top 10 recid from A where recid not in(select top 30 recid from A)

    分析:如果这样写会产生某些问题,如果recid在表中存在逻辑索引。
    select top 10 recid from A where……是从索引中查找,而后面的select top 30 recid from A则在数据表中查找,这样由于索引中的顺序有可能和数据表中的不一致,这样就导致查询到的不是本来的欲得到的数据。

    解决方案

    1, 用order by select top 30 recid from A order by ricid 如果该字段不是自增长,就会出现问题

    2, 在那个子查询中也加条件:select top 30 recid from A where recid>-1

    例2:查询表中的最后以条记录,并不知道这个表共有多少数据,以及表结构。
    set @s = 'select top 1 * from T where pid not in (select top ' + str(@count-1) + ' pid from T)'

    print @s exec sp_executesql @s

    9:获取当前数据库中的所有用户表
    select Name from sysobjects where xtype='u' and status>=0

    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

    --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_expression , 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码。

    SQLServer2000同步复制技术实现步骤

    一、 预备工作

    1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户

    --管理工具

    --计算机管理

    --用户和组

    --右键用户

    --新建用户

    --建立一个隶属于administrator组的登陆windows的用户(SynUser)

    2.在发布服务器上,新建一个共享目录,做为发布的快照文件的存放目录,操作:

    我的电脑--D:\ 新建一个目录,名为: PUB

    --右键这个新建的目录

    --属性--共享

    --选择"共享该文件夹"

    --通过"权限"按纽来设置具体的用户权限,保证第一步中创建的用户(SynUser) 具有对该文件夹的所有权限

    --确定

    3.设置SQL代理(SQLSERVERAGENT)服务的启动用户(发布/订阅服务器均做此设置)

    开始--程序--管理工具--服务

    --右键SQLSERVERAGENT

    --属性--登陆--选择"此账户"

    --输入或者选择第一步中创建的windows登录用户名(SynUser)

    --"密码"中输入该用户的密码

    4.设置SQL Server身份验证模式,解决连接时的权限问题(发布/订阅服务器均做此设置)

    企业管理器

    --右键SQL实例--属性

    --安全性--身份验证

    --选择"SQL Server 和 Windows"

    --确定

    5.在发布服务器和订阅服务器上互相注册

    企业管理器

    --右键SQL Server组

    --新建SQL Server注册...

    --下一步--可用的服务器中,输入你要注册的远程服务器名 --添加

    --下一步--连接使用,选择第二个"SQL Server身份验证"

    --下一步--输入用户名和密码(SynUser)

    --下一步--选择SQL Server组,也可以创建一个新组

    --下一步--完成

    6.对于只能用IP,不能用计算机名的,为其注册服务器别名(此步在实施中没用到)

    (在连接端配置,比如,在订阅服务器上配置的话,服务器名称中输入的是发布服务器的IP)

    开始--程序--Microsoft SQL Server--客户端网络实用工具

    --别名--添加

    --网络库选择"tcp/ip"--服务器别名输入SQL服务器名

    --连接参数--服务器名称中输入SQL服务器ip地址

    --如果你修改了SQL的端口,取消选择"动态决定端口",并输入对应的端口号

    二、 正式配置

    1、配置发布服务器

    打开企业管理器,在发布服务器(B、C、D)上执行以下步骤:

    (1) 从[工具]下拉菜单的[复制]子菜单中选择[配置发布、订阅服务器和分发]出现配置发布和分发向导

    (2) [下一步] 选择分发服务器 可以选择把发布服务器自己作为分发服务器或者其他sql的服务器(选择自己)

    (3) [下一步] 设置快照文件夹

    采用默认\servername\Pub

    (4) [下一步] 自定义配置

    可以选择:是,让我设置分发数据库属性启用发布服务器或设置发布设置

    否,使用下列默认设置(推荐)

    (5) [下一步] 设置分发数据库名称和位置 采用默认值

    (6) [下一步] 启用发布服务器 选择作为发布的服务器

    (7) [下一步] 选择需要发布的数据库和发布类型

    (8) [下一步] 选择注册订阅服务器

    (9) [下一步] 完成配置

    2、创建出版物

    发布服务器B、C、D上

    (1)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令

    (2)选择要创建出版物的数据库,然后单击[创建发布]

    (3)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助)

    (4)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,

    SQLSERVER允许在不同的数据库如 orACLE或ACCESS之间进行数据复制。

    但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器

    (5)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表

    注意: 如果前面选择了事务发布 则再这一步中只能选择带有主键的表

    (6)选择发布名称和描述

    (7)自定义发布属性 向导提供的选择:

    是 我将自定义数据筛选,启用匿名订阅和或其他自定义属性

    否 根据指定方式创建发布 (建议采用自定义的方式)

    (8)[下一步] 选择筛选发布的方式

    (9)[下一步] 可以选择是否允许匿名订阅

    1)如果选择署名订阅,则需要在发布服务器上添加订阅服务器

    方法: [工具]->[复制]->[配置发布、订阅服务器和分发的属性]->[订阅服务器] 中添加

    否则在订阅服务器上请求订阅时会出现的提示:改发布不允许匿名订阅

    如果仍然需要匿名订阅则用以下解决办法

    [企业管理器]->[复制]->[发布内容]->[属性]->[订阅选项] 选择允许匿名请求订阅

    2)如果选择匿名订阅,则配置订阅服务器时不会出现以上提示

    (10)[下一步] 设置快照 代理程序调度

    (11)[下一步] 完成配置

    当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库

    有数据

    srv1.库名..author有字段:id,name,phone,

    srv2.库名..author有字段:id,name,telphone,adress

    要求:

    srv1.库名..author增加记录则srv1.库名..author记录增加

    srv1.库名..author的phone字段更新,则srv1.库名..author对应字段telphone更新

    --*/

    --大致的处理步骤

    --1.在 srv1 上创建连接服务器,以便在 srv1 中操作 srv2,实现同步

    exec sp_addlinkedserver 'srv2','','SQLOLEDB','srv2的sql实例名或ip'

    exec sp_addlinkedsrvlogin 'srv2','false',null,'用户名','密码'

    go

    --2.在 srv1 和 srv2 这两台电脑中,启动 msdtc(分布式事务处理服务),并且设置为自动启动

    。我的电脑--控制面板--管理工具--服务--右键 Distributed Transaction Coordinator--属性--启动--并将启动类型设置为自动启动

    go

    --然后创建一个作业定时调用上面的同步处理存储过程就行了

    企业管理器

    --管理

    --SQL Server代理

    --右键作业

    --新建作业

    --"常规"项中输入作业名称

    --"步骤"项

    --新建

    --"步骤名"中输入步骤名

    --"类型"中选择"Transact-SQL 脚本(TSQL)"

    --"数据库"选择执行命令的数据库

    --"命令"中输入要执行的语句: exec p_process

    --确定

    --"调度"项

    --新建调度

    --"名称"中输入调度名称

    --"调度类型"中选择你的作业执行安排

    --如果选择"反复出现"

    --点"更改"来设置你的时间安排

    然后将SQL Agent服务启动,并设置为自动启动,否则你的作业不会被执行

    设置方法:

    我的电脑--控制面板--管理工具--服务--右键 SQLSERVERAGENT--属性--启动类型--选择"自动启动"--确定.

    --3.实现同步处理的方法2,定时同步

    --在srv1中创建如下的同步处理存储过程

    create proc p_process

    as

    --更新修改过的数据

    update b set name=i.name,telphone=i.telphone

    from srv2.库名.dbo.author b,author i

    where b.id=i.id and

    (b.name <> i.name or b.telphone <> i.telphone)

    --插入新增的数据

    insert srv2.库名.dbo.author(id,name,telphone)

    select id,name,telphone from author i

    where not exists(

    select * from srv2.库名.dbo.author where id=i.id)

    --删除已经删除的数据(如果需要的话)

    delete b

    from srv2.库名.dbo.author b

    where not exists(

    select * from author where id=b.id)

    go

    /************* mysql视图 ***********:

    一、视图view作用:

    1. 可以简化我们的查询:

    比如:复杂的统计时,先用视图生成一个中间结果,再查询视图。

    1. 更精细的权限控制:

    比如:某张用户表为例。

    现在,有两个网站合作,可以查询对方网站的用户信息,需要向对方开放用户表的权限,又不想开放用户表中的密码字段。

    CREATE VIEW v_use AS

    select user_id,username,email from user;

    可以开放这个没有密码字段的视图权限给对方。

    1. 数据多,分表时可以用到:

    比如:小说站,article表,1000多万篇,数据量太大,

    这个时候可以把小说的记录纵向分成article1, article2 ,article3.....article5 . 这5张表每张表放200万就可以了。

    查询小说时,不知道在哪张表

    create view v_article as

    select title from article2 union select title from article2 ...union select title article 3...

    这个时候可以把要查的字段,从五张表中取出来放到一个视图里,查这个视图。

    二、视图特性:

    1. 视图中必须存放select 查询语句,视图可以当做表用

    2. 视图就像是一个表的影子,当表发生改变的时候,已经创建好的视图也随着发生改变。

    3. 视图是否可以修改?(不建议对视图执行insert,update,delete 操作)

    可以修改的情况:视图和表的数据一一对应。

    不可以修改的情况:视图和表的数据不一一对应

    思考:什么就叫做一一对应呢?

    答案:

      一一对应是指,根据select关系,从表中取出的行,只能计算出视图中确定的一行,反之,视图中任意抽出一行,
    
      也能够返回出表中的具体确定一行。就像函数的映射一样。视图中的某字段的平均数,和,差 和该字段中的数据不是一一对应,
    
      或者视图中已经进行了重新排序和limit都不是一一对应。只有本字段和本字段才算:由表的数据可以推出视图的数据,
    
      由视图的数据可以推出表的数据。但是如果视图中是平均数,和,查的话,是推不出表中每个数据的数值的。
    
    1. 数据库数据data存储的格式:.frm 代表表的结构,是定义文件。

    .NYD 代表表的数据

    .NYI 代表表的索引

    视图文件的话,是没有.NYD和.NYI的,只有一个.frm文件。没有真实的数据,有的只是一个关系结构。

    三、视图的algorithm :

    思考:相比于建临时表,哪个快?

    建表:查询 -》 形成临时表 -》 查询临时表 (慢)

    叠加:合并条件 -》 查询表 (快)

    algorithm = merge 当引用视图时,引用视图的语句与定义视图的语句合并。

    temptable 当引用视图时,根据视图的创建语句建立一个临时表

    undefined 未定义,自动,由系统帮你判断。
    */

    /*
    1、algorithm = merge:

    意味着视图只是一个语句规则,当查询视图时,把查询视图的语句(比 如where 那些)与创建时的语句where子句等合并分析形成一条select语句。

    建一张简单的查询视图,不用临时表,只用条件合并。 */

    CREATE [ALGORITHM=MERGE] view v1
    AS
    SELECT goods_id,goods_price FROM goods WHERE goods_price < 5000;

    查询视图语句:

    SELECT goods_id,goods_price FROM v1 WHERE goods_price > 4000;

    最终执行语句:

    SELECT goods_id,goods_price FROM goods WHERE goods_price > 4000 AND goods_price < 5000;

    这个简单的查询还建临时表的话,开销就有点大。这个时候,我们可以指定algorithm 选项为merge .

    2、algorithm = temptable:

    CREATE ALGORITHM = TEMPTABLE view v3 AS SELECT * FROM goods ORDER BY goods_price;

    3、algorithm = undefined :

    如果不知道该用什么哪种方式就无须指定algorithm的方式使用默认,则algorithm = undefined让系统自动选择。

    四、视图语法:

    /*1、创建视图:

    CREATE VIEW 视图名称 AS 查询语句;  */
    
    CREATE VIEW v_goods_sum AS
    
    SELECT sum(goods_price), goods_brand.brand_name FROM goods left join goods_brand
    
     ON goods.goods_id=goods_brand.brand_id GROUP BY goods_brand.brand_name;
    

    /*2、查询创建视图的sql:

    SHOW CREATE VIEW 视图名称; */
    
    SHOW CREATE VIEW v_goods_sum;
    

    /*3、查看视图: */

    #方法一:进入该数据库的前提下,查看指定数据库中的视图
    
    SHOW TABLES;
    
    /*方法二:没进入数据库的前提下,查看指定数据中的视图
    
    在数据库information_schema 的 表tables里记录和视图和有关表的信息;
    
    注意:
    
        table_name  被查的视图名称。
    
        table_schema 被查的视图或表存放在的数据库名字 */
    
    /*1、查询所有视图:
    
    USE information_schema;
    
    SELECT table_schema,table_name,table_type FROM tables
    
    WHERE table_schema='库名' AND table_type='view';  */
    
    #实例:查询数据库shopping下的所有视图:
    
    SELECT table_schema,table_name,table_type FROM tables WHERE table_schema='shopping' AND table_type='view';
    

    /*4、查询某个库所有表和视图:

    USE information_schema;
    
    SELECT table_schema,table_name,table_type FROM tables WHERE table_schema='库名'; */
    
    #查询数据库shopping下的所有表和视图:
    
    SELECT table_schema,table_name,table_type FROM tables WHERE table_schema='shopping';
    

    /*5、使用视图(把视图当表用):

    select * from 视图名
    select 字段,字段,字段 from 视图名称
    select * from 视图名 where 条件;  */
    
    SELECT * FROM v_goods_sum;
    

    /*6、修改视图:

    ALTER VIEW  视图名 AS 查询语句;  */
    
    ALTER VIEW v_goods_sum AS
    
    SELECT sum(goods_price) AS '品牌总价格', goods_brand.brand_name AS '品牌名称' FROM goods left join goods_brand
    
        ON goods.goods_id=goods_brand.brand_id GROUP BY goods_brand.brand_name;
    
    #测试
    SELECT * FROM v_goods_sum;
    

    /*7、删除视图:

    DROP VIEW 视图名; */
    
    DROP VIEW v_goods_sum;
    

    /*8、php调用视图:

    $result = mysql_query('SELECT * FROM 视图名称');
    

    */

    自定义函数 AND 存储过程 procedure

    一、自定义函数:

    用户自定义函数(user-defined function,UDF)是一种对MySQL扩展的途径,其用法与内置函数相同。

    自定义函数的两个必要条件:参数、返回值。函数可以返回任意类型的参数,同样可以接受这些类型的参数。

    注意:函数是基于数据库的,所有在写函数的时候,必须先选择数据库。

    1、创建自定义函数:

    USE db_name; #选择数据库

    CREATE FUNCTION function_name

    RETURNS {STRING|INTEGER|REAL|DECIMAL} 返回值类型

    routine_body(函数体)

    注意:关于函数体

    1.函数体由合法的SQL语句构成;
    2.函数体可以使用简单的SELECT或INSERT语句
    3.函数体如果为复合结构则使用BEGIN...END语句
    4.复合结构可以包含声明、循环、控制结构
    

    */

    USE hello;

    1.1、创建不带参数的自定义函数:

    CREATE FUNCTION f1()
    RETURNS VARCHAR(30)
    RETURN DATE_FORMAT(NOW(),'%Y-%m-%d');

    SELECT f1();

    1.2、创建带有参数的自定义函数:

    CREATE FUNCTION f3(num1 SMALLINT UNSIGNED,num2 SMALLINT UNSIGNED)
    RETURNS FLOAT(10,2) UNSIGNED
    RETURN (num1+num2)/2;
    SELECT f2(1,5);

    注意:如果在调用的时候没有参数,那么会系统报错

    +---------+
    | f2(1,5) |
    +---------+
    | 3.00 |
    +---------+

    1.3、创建具有复合结构函数体的自定义函数:

    推导第一步:

    CREATE FUNCTION addbook(b_name VARCHAR(20))
    RETURNS INT UNSIGNED
    INSERT book(book_name) values(b_name);
    RETURN LAST_INSERT_ID();

    /*注意:

      当写到这里的时候,由于下面还有SQL语句,所有必须写分号,但是MySQL遇到分号后会让整个创建方法的语句也结束,
      所以必须使用DELEMIT 来改变结束符。*/
    

    注意:修改结束符为 //

    推导第二步:

    DELIMITER //
    CREATE FUNCTION addBook(b_name VARCHAR(30))
    RETURNS SMALLINT UNSIGNED
    INSERT book(book_name) VALUES (b_name);
    RETURN LAST_INSERT_ID() //
    DELIMITER ;

    /*注意:

      1、虽然修改了结束分号,不再让SQL结束符和自定义函数中语句结束符冲突,但是方法体需要的是一个整体,
      所以必须引入BEGIN .. END来把所有的执行语句标识为一个方法体。
    
      2、显示的结果为自定义的返回值,使用完毕后再修改结束符为 ;
    

    */

    最后成功创建

    DELIMITER //
    CREATE FUNCTION addBook(b_name VARCHAR(30))
    RETURNS INT UNSIGNED
    BEGIN
    INSERT book(book_name) VALUES(b_name);
    RETURN LAST_INSERT_ID();
    END //
    DELIMITER ;

    调用自定义函数的时候用SELECT关键字来调用,

    无法获得正确的last_insert_id(),检查你的id字段是否是自增长。AUTO_INCREMENT

    SELECT addBook('hello word');
    +-----------------------+
    | addBook('hello word') |
    +-----------------------+
    | 10 |
    +-----------------------+

    2、查看所有的自定义函数和存储过程:

    SELECT db,name FROM mysql.proc;

    3、删除自定义函数:

    DROP FUNCTION IF EXISTS function_name;

    实例:删除自定义函数addBook

    DROP FUNCTION IF EXISTS addBook;

    /*

    二、存储过程:

    1、概念:

    我们经常会对数据库进行CURD(增删改查),当我们输入SQL命令后,MySQL引擎会对其进行语法分析查看我们输入的SQL语句的正确性,
    如果正确的话进行编译,编译成MySQL引擎识别的命令,完成执行后把执行结果返回给客户端,这个就是MySQL的执行流程,试想,如果我们
    想把这个流程简化一下,可以选择把语法分析和编译的过程省略,这样就可以提高Mysql的执行效率。如果实现,那么就需要存储过程。

    存储过程是SQL语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理。

    比如:
    有2个SQL语句,那么MySQL引擎会对这两个语句进行逐一的语法分析、编译和执行,而使用存储过程只在第一次的时候进行语法分析
    和编译,而之后就直接调用这个执行结果了,即省略了两个环节。

    2、优点:

    A、增强SQL语句的功能和灵活性。(流程控制和条件判断和较复杂的运算都可以执行)
    B、实现较快的执行速度(不逐一语法分析和编译,而是采用预编译直接执行)
    C、减少网络流量(单个提交SQL语句,浪费流量)

    3、创建存储过程:

    CREATE
    [DEFINER = {user | CURRENT_USER}] #创建者,默认为当前登陆到客户端用户
    PROCEDURE sp_name([proc_parameter[,.....]])
    [characteristic .....] routine_body
    proc_aprameter: [IN | OUT | INOUT] param_name type

    IN:表示该参数的值必须在调用存储过程时指定,这个值不能被返回
    OUT:表示该参数的值可以被存储过程改变,并且可以返回
    INOUT:表示该参数的调用时指定,并且可以被改变和返回。

    过程体:

    1、过程体由合法的SQL语句构成
    2、过程体可以是任意的SQL语句CURD。(但不能创建数据库和数据表)
    3、过程体如果为复合结构则使用BEGIN....END语句
    4、复合结构可以包含声明、循环、控制结构
    

    范例:

    DELIMITER //
     CREATE PROCEDURE 存储过程名称()
     BEGIN
       sql.. ;
       sql.. ;
     END //
    DELIMITER ;
    

    注意:存储过程是基于数据库的,所有在创建和使用存储过程的时候必须先进入数据库

    */

    3.0、查看存储过程状态:

    SHOW PROCEDURE STATUS;

    3.1 创建不带参数的存储过程:

    获取MySQL版本的功能,如果没有参数,在调用的过程中带不带括号都可以。

    USE hello;

    CREATE PROCEDURE pr_1() SELECT VERSION();

    CALL pr_1;
    +-----------+
    | VERSION() |
    +-----------+
    | 5.5.20 |
    +-----------+

    CALL sp_1();
    +-----------+
    | VERSION() |
    +-----------+
    | 5.5.20 |
    +-----------+

    3.2、创建带有参数的简单存储过程实例:

    DELIMITER //
    CREATE PROCEDURE pr_2(width INT,height INT)
    BEGIN
    SELECT CONCAT('你的面积是',width*height) AS area;
    IF width > height THEN
    SELECT '胖子' AS '体型';
    ELSEIF width < height THEN
    SELECT '瘦子' AS '体型';
    ELSEIF width = height THEN
    SELECT 'hello' AS '体型';
    END IF;
    END //
    DELIMITER ;

    CALL pr_2(10,10);

    注意:此存储过程中出现了两次SELECT关键字,说明该存储过程在执行的时候有两个返回值

    3.3、创建带有IN类型参数的存储过程:

    根据ID删除记录(因为有参数,所以调用的时候括号不能省略)

    DELIMITER //
    CREATE PROCEDURE removeBookById(IN id INT UNSIGNED)
    BEGIN
    DELETE FROM book WHERE book_id = id;
    END //
    DELIMITER ;

    CALL removeBookById(10);

    3.4 创建带有OUT类型参数的存储过程:

    删除book表中指定ID的记录,然后返回剩余记录的条数

    DELIMITER //
    CREATE PROCEDURE removeBookAndReturnBookNums(IN id INT UNSIGNED,OUT bookNums INT UNSIGNED)
    BEGIN
    DELETE FROM book WHERE book_id = id;
    SELECT count(1) INTO bookNums FROM book ;
    END //
    DELIMITER ;

    CALL removeBookAndReturnBookNums(8,@nums);

    SELECT @nums;

    +-------+
    | @nums |
    +-------+
    | 8 |
    +-------+

    3.5、创建带有INOUT类型参数的存储过程:

    DELIMITER //
    CREATE PROCEDURE pr_3(INOUT age INT UNSIGNED)
    BEGIN
    SET age = age + 2;
    END //
    DELIMITER ;

    SET @age = 20;

    CALL pr_3(@age);
    SELECT @age;

    +------+
    | @age |
    +------+
    | 22 |
    +------+

    3.6、创建带有多个OUT类型参数的存储过程:

    ROW_COUNT() 受影响行数

    insert test values(null,66666),(null,0000);
    SELECT row_count();
    +-------------+
    | row_count() |
    +-------------+
    | 2 |
    +-------------+

    DELIMITER //
    CREATE PROCEDURE removeUserByAgeAndReturnInfos(In p_age SMALLINT UNSIGNED,OUT deleteUsers SMALLINT UNSIGNED,OUT userCounts SMALLINT UNSIGNED)
    BEGIN
    DELETE FROM users WHERE age = p_age;
    SELECT ROW_COUNT() INTO deleteUsers;
    SELECT COUNT(id) FROM users INTO userCounts;
    ENG //
    DELIMITER ;

    CALL removeUserByAgeAndReturnInfos(12,@a,@b);
    SELECT @a,@b;

    4、调用存储过程: CALL 存储过程名(值);

    5、删除存储过程: DROP PROCEDURE 存储过程名;

    6、查看存储过程:

    mysql库->proc 表

    查看所有的自定义函数和存储过程:

    SELECT db,name FROM mysql.proc;

    查看指定数据库下的存储过程

    SELECT db,name FROM mysql.proc WHERE db = '所属的数据库';

    实例:查看数据库hello下的存储过程

    SELECT db,name FROM mysql.proc WHERE db = 'hello';

    /*
    三、总结:

    1、自定义函数和存储过程:

    1、存储过程实现的功能要复杂一些;自定义函数的针对性更强一些。
    2、存储过程可以返回多个值;自定义函数只能有一个值
    3、存储过程一般独立执行;自定义函数主要作为其他SQL语句的组成部分来出现(和内置函数用法相同)。

    */

    /*
    四、基础语法总结:

    1、定义变量

    第一种:
    declare 变量名 数据类型;
    declare 变量名 类据类型 [default 值] ;

      注意:
          1、定义变量的代码必须出现开始位置
          2、这种变量为局部变量,只在begin..end之间起作用,end以后则变量销毁。
    

    第二种:
    SET @i = 7

      注意:
          1、这种变量只对当前用户使用的客户端有效。
          2、用户变量
    
      查看该变量:SELECT @i  */
    

    实例1:

    DELIMITER //
    CREATE PROCEDURE pro_1()
    BEGIN
    declare username varchar(20);
    declare age smallint;
    declare height int default 175;
    SET username = '张三';
    SET age = '180';
    SELECT concat('姓名',username,'年龄是',age,'身高是',height);
    END //
    DELIMITER ;

    set @name ='hanlibao';

    DELIMITER //
    

    CREATE PROCEDURE pro_2(username varchar(30))
    BEGIN
    declare age smallint;
    declare height int default 175;
    SET age = '180';
    SELECT concat('姓名',username,'年龄是',age,'身高是',height);
    END //
    DELIMITER ;

    call pro_2(@name);

    /*2、变量赋值:

    declare 变量名 数据类型 default 值;

    SET 变量名= 值;

    SELECT 字段 into 变量 from 表名 where 条件;
    SELECT 字段 into 变量,字段 into 变量 from 表名
    SELECT 聚合函数(字段) into 变量 from 表名 */

    实例2:

    DELIMITER //
    CREATE PROCEDURE hello4()
    BEGIN
    declare a int;
    declare b varchar(30);
    declare c varchar(100);
    SET a = 20;
    SET b = 'beijing';
    SELECT stuname into c from student where stuid = a;
    SELECT c;
    END //
    DELIMITER ;

    /*3、运算符:

    算术运算符 + - * /
    逻辑运算符 and or not */

    实例3:

    DELIMITER //
    CREATE PROCEDURE hello5()
    begin
    declare a int default 20;
    declare b int default 30;
    declare sum int;
    SET sum = a + b;
    SELECT sum;
    end //
    DELIMITER ;

    /*4.1、判断语句: IF ... ELSE..

    IF 条件 THEN
    sql语句...;
    END IF;

    IF 条件 THEN
    sql语句...;
    ELSE
    sql语句...;
    END IF;

    IF 条件 THEN
    sql语句...;
    ELSEIF 条件 THEN
    sql语句...;
    ELSEIF 条件 THEN
    sql语句...;
    ELSE
    sql语句
    END IF; */

    实例4:

    DELIMITER //
    CREATE PROCEDURE pro_2()
    BEGIN
    DECLARE age INT DEFAULT 18;
    IF age >= 18 THEN
    SELECT '已成年';
    ELSE
    SELECT '未成年';
    END IF;
    END //
    DELIMITER ;

    /*4.2、判断语句: CASE

    CASE 变量
    WHEN 条件一 THEN 执行体1;
    WHEN 条件二 THEN 执行体2;
    ...
    END CASE; */

    实例5:

    DELIMITER //
    CREATE PROCEDURE pro_6()
    BEGIN
    DECLARE pos INT DEFAULT 0;
    SET pos = FLOOR(5*RAND());
    CASE pos
    WHEN 1 THEN SELECT 'still flying';
    WHEN 2 THEN SELECT 'fall in sea';
    WHEN 3 THEN SELECT 'in the island';
    ELSE SELECT 'I dont know';
    END CASE;
    END //
    DELIMITER ;

    CALL pro_6();

    /*5、循环语句

    WHILE 条件 DO
    sql语句..
    END WHILE; */

    实例6:

    DELIMITER //
    CREATE PROCEDURE pro_4()
    BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    WHILE i <= 100 DO
    SET total = total + i;
    SET i = i + 1;
    END WHILE;
    SELECT total;
    END //
    DELIMITER ;
    CALL pro_4();

    /*
    REPEAT
    sql....;
    UNTIL 条件 END REPEAT; */

    实例7:

    DELIMITER //
    CREATE PROCEDURE pro_7()
    BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    REPEAT
    SET i = i + 1;
    SET total = total + i;
    UNTIL i >= 100 END REPEAT;
    SELECT total;
    END //
    DELIMITER ;
    CALL pro_7();

    /*
    标记:loop
    sql
    if 条件 then
    leave 标记;
    end if;
    end loop; */

    实例8:

    DELIMITER //
    CREATE PROCEDURE hello10()
    begin
    declare i int default 0;
    haha:loop
    SELECT i;
    SET i = i + 1;
    if i > 5 then
    leave haha;
    end if;
    end loop;
    end //
    DELIMITER ;

    实例9:

    DELIMITER //
    CREATE PROCEDURE pro_4()
    BEGIN
    DECLARE total INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    WHILE i <= 100 DO
    SET total = total + i;
    SET i = i + 1;
    END WHILE;
    SELECT total;
    END //
    DELIMITER ;

    CALL pro_4();

    常用命令:

    select now(); 打印当前日期时间的。
    select curdate();打印当前的日期。
    select curtime();打印当前时间
    select database();打印当前所在数据库的。
    select version();打印mysql 版本号。
    select user();  打印当前用户。 
    

    创建数据库

    create database [if not exists] 数据库名称 [default character set=编码方式]  
    

    修改数据库 (数据库名称可以忽略,此时,语句对应于默认数据库。):

    ALTER DATABASE db_name [ DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ]
    

    查看数据库信息:

    SHOW CREATE DATABASE [IF NOT EXISTS ] 数据库名称
    

    查看现存的所有数据库

    SHOW DATABASES;
    

    更改使用的数据库(进入某一库)

    USE 库名;
    

    删除数据库:

    DROP DATABASE  [IF NOT EXISTS ] 数据库名称
    

    3.数据类型:
    整型:
    tinyint :占1个字节 范围,有符号 -128--127,无符号:0--255
    smallint, 占2个字节,有符号 -32768---32767,无符号:0--65535
    mediumint:占3个字节,有符号 -8388608-8388607 ,无符号 0-16777215
    int: 占4个字节:有符号 -2147483648---2147483647,无符号0-4284967295
    bigint,占8字节。
    浮点型:
    float 占4字节: 1.17e-38----3.4e+38
    double 占8字节:
    decimal 以字符串的形式表示浮点数。 "3.14"
    字符型:
    char(len) 定长 255字节。
    varchar(len) 变长的字符 占255个字符。
    tinytext 0---255
    text 65535
    mediumtext 16777215
    longtext 2的32次方
    enum(value1,value2,value3.....value65535)数据只能取value1....valuen中的值。n<=65535

    日期时间格式:
                date  2012-02-18
                datetime 日期时间型  2012-12-21  12:12:12
    

    创建数据库表:

    create table [if not exists] 数据表名(
        列定义:
        列名称 数据类型 【not null | null】[default value][auto_increment]【索引 unique key | primary key】
        列名称 数据类型 【not null | null】[default value][auto_increment]【索引 unique key | primary key】
        列名称 数据类型 【not null | null】[default value][auto_increment]【索引 unique key | primary key】
        列名称 数据类型 【not null | null】[default value][auto_increment]【索引 unique key | primary key】
        列名称 数据类型 【not null | null】[default value][auto_increment]【索引 unique key | primary key】
        列名称 数据类型 【not null | null】[default value][auto_increment]【索引 unique key | primary key】
        .........           
    )[ENGINE=InnoDB DEFAULT CHARSET=utf8 ];
    

    索引(约束)

    INDEX (普通索引), PRIMARY KEY(主键索引) , UNIQUE (唯一索引), FOREIGN KEY(外键索引)
    

    建立索引的时机

    到这里我们已经学会了建立索引,那么我们需要在什么情况下建立索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。

    上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:

    1.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

    2.建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。

    3.索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。

    约束

    auto_increment(自增长) , NULL(空) , NOT NULL(非空) , DEFAULT(设置默认值)
    

    存储引擎 [ ENGINE ]

    ARCHIVE  档案存储引擎。
     
    BDB  带页面锁定的事务安全表。也称为BerkeleyDB。
     
    CSV  值之间用逗号隔开的表。
     
    FEDERATED  可以访问远程表的存储引擎。
     
    HEAP  MEMORY (HEAP)存储引擎”。
     
    ***InnoDB  带行锁定和外键的事务安全表。
     
    MEMORY  本表类型的数据只保存在存储器里。
     
    MERGE  MyISAM表的集合,作为一个表使用。也称为MRG_MyISAM。
     
    ***MyISAM   二进制轻便式存储引擎,此引擎是MySQL所用的默认存储引擎。
     
    NDBCLUSTER  成簇表,容错表,以存储器为基础的表。也称为NDB。
    

    MySQL数据库MyISAM和InnoDB存储引擎的比较

    MySQL有多种存储引擎,MyISAM和InnoDB是其中常用的两种。
    MyISAM是MySQL的默认存储引擎,基于传统的ISAM类型,支持全文搜索,但不是事务安全的,而且不支持外键。每张MyISAM表存放在三个文件中:frm 文件存放表格定义;数据文件是MYD (MYData);索引文件是MYI (MYIndex)。

    InnoDB是事务型引擎,支持回滚、崩溃恢复能力、多版本并发控制、ACID事务,支持行级锁定(InnoDB表的行锁不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,如like操作时的SQL语句),以及提供与Oracle类型一致的不加锁读取方式。InnoDB存储它的表和索引在一个表空间中,表空间可以包含数个文件。

    主要区别:

    MyISAM是非事务安全型的,而InnoDB是事务安全型的。
    MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
    MyISAM支持全文类型索引,而InnoDB不支持全文索引。
    MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。
    MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦。
    InnoDB表比MyISAM表更安全,可以在保证数据不会丢失的情况下,切换非事务表到事务表(alter table tablename type=innodb)。

    查看数据库表:

    show tables ; //查看库内的所有表的情况
    

    删除数据表:

    DROP  TABLE [ IF EXISTS ] tb_name [, tb_name2 ...] 
    

    清空表

    delete from 表名;
    

    截段表

    truncate table 表名;
    

    修改数据表名称:

    RENAME TABLE tb_name TO new_tb_name [ , tb2_name TO new_tb2_name ... ]
    

    查看数据表的结构:

        desc 数据表名; 
    
        SHOW COLUMNS FROM 数据表名;
    

    插入记录

    1.INSERT [INTO] tb_name [(col_name,...)] VALUES (val,...);
    

    更新记录(单表跟新)

    UPDATE table_reference SET col_name1 = {expr|DEFAULT},[col_name1 = {expr|DEFAULT},....] [WHERE where_confition];
    

    删除记录(单表删除)

    DELETE FROM tb_name [WHERE where_confition]
    

    查询记录(单表查询)

    SELECT select_exper[,select_exper,...]   FROM 数据表名 
    

    WHWER 条件查询(对记录进行过滤 (可以使用MYSQL支持的函数和运算符))

    运算符
        and 与   or  或   > 大于    >=  大于等于    <   小于      <=  小于等于    !=  不等于 <>  不等于  IN()  , NOT IN() , 
        
        BETWEEN ...AND , NOT BETWEEN ...AND
    
    
    模糊查询 like
        %:代表0个或多个任意字符
        _:代表1个任意字符
    
    聚合函数(聚合查询)(统计查询)
        count 数量查询
            select count(字段名) from 表名;
    
        sum 总和查询
            select sum(字段) from 表名;
    
        avg 平均数查询
            select avg(字段) from 表名;
        
        max最大值查询
            select max(字段) from 表名;
    
        min最小值查询
            select min(字段) from 表名;
    
    查询结果分组  
    
    [GROUP BY {col_name|position}[ASC|DESC]]
    
    having 语句设置分组条件
    
    SELECT col_name FROM tb_name GROUP BY col_name HAVING 条件
    
    ORDER BY 排序
    
    [ORDER BY {col_name|expr|position}ASC|DESC],...]
    
    SELECT * FROM tb_name ORDER BY col_name [ASC |DESC], col_name2 [ASC | DESC]
    
    LIMIT 限制结果返回数量
    
    SELECT * FROM tb_name LIMIT [offset,] number
    

    MYSQL 多表连接查询

    子查询(可以在SELECT, INSERT , UPDATE,SET,DO里用到)
    
        SELECT * FROM tb_name where col_name = (SELECT ...);
    
        使用比较运算符的子查询(=,>,<,>=,<=,<>,!=,<=>)
    
        SELECT * FROM goods WHERE goods_price>=(SELECT ROUND(AVG(goods_price),2) FROM goods);
    
    连接 MYSQL 在SELECT 语句、多表跟新,多表删除语句中支持JOIN 操作。{[INNER |CROSS] JOIN | {LEFT|RIGHT} [OUTER] JOIN}
    
    内连接[INNER JOIN]{仅显示符合连接条件的内容}
    使用ON关键字来设定连接条件,也可以使用WHERE来代替。(通常使用On关键字来设定条件连接,使用WHERE关键字进行结果集记录过滤)
    
    SELECT [col_name,...] FROM tb_name as t1 INNER JOIN tb_name2 AS t2 ON t1.col_name1= t2.col_name1;
    
    外连接 {[LEFT | RIGHT] OUTER JOIN}
    {左外连接显示左表的全部记录,及右表符合连接条件的记录}
    
    SELECT [col_name,...] FROM tb_name as t1 LEFT OUTER JOIN tb_name2 AS t2 ON t1.col_name1= t2.col_name1;
    
    {右外连接显示右表的全部记录,及左表符合连接条件的记录}
    
    SELECT [col_name,...] FROM tb_name as t1 RIGHT OUTER JOIN tb_name2 AS t2 ON t1.col_name1= t2.col_name1;
    
    联合查询(将两张表的记录合为一张表)
    

    修改数据表

      添加删除列
    
      ALTER TABLE tb_name ADD [COLUMN] col_name<列名称> column_definition <列类型,列定义> [FIRST <放到第一>| AFTER col_name<放到该列之后> ] 
    
      添加多列
    
      ALTER TABLE tb_name ADD [COLUMN] (col_name column_definition,...)
    
      删除列
    
      ALTER TABLE tb_name DROP [COLUMN] col_name
    
      删除多列
    
      ALTER TABLE tb_name DROP [COLUMN] col_name ,DROP col_name2,...
    
      动态添加主键约束
    
      ALTER TABLE tb_name ADD [CONSTRAINT [symbol]<用途给主键起名称>] PRIMARY KEY [index_type](index_col_name)
    
      添加唯一约束
    
      ALTER TABLE tb_name ADD [CONSTRINT [symbol]] UNIQUE [INDEX | KEY ] [index_name] [index_type](index_col_name)
    
      添加外键约束 //外键不用关注。
    
      ALTER TABLE tb_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] [index_type] (index_col_name) reference_definition () tb_name1 (col_name)
    
      添加/删除默认约束
    
      ALTER  TABLE tb_name ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT }
    
      删除主键约束
    
      ALTER TABLE TB_name DROP PRIMARY KEY
    
      删除唯一约束
    
      ALTER TABLE tb_name DROP {INDEX|KEY}  col_index_name
    
      删除外键约束
    
      ALTER TABLE tb_name DROP FOREIGN KEY fr_symbol
    
      修改列定义
    
      ALTER TABLE tb_name MODIFY [COLUMN] col_name col_name column_definition [FIRST | AFTER col_name]
    
      修改列名称
    
      ALTER TABLE tb_name CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST|AFTER col_name]
    

    SQL 功能 分类:

    DDL 数据定义语言:创建,删除,修改数据库以及数据库对象
    DML 数据管理语言:增 删  改 记录的语句;
    DQL 数据查询语言:select
    DCL 数据控制语言:用户的管理,权限的分配.
    

    相关文章

      网友评论

        本文标题:SQL--Structured Query Language精妙

        本文链接:https://www.haomeiwen.com/subject/robjdttx.html