一. 基础

1. 创建数据库

CREATE DATABASE database-name

2. 删除数据库

drop database dbname

3. 备份sql server

—— 创建备份数据的 device
USE master
EXEC sp_addunpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwinf_1.dat'
—— 开始备份
BACKUP DATABASE push 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 tablname ADD COLUMN col TYPE NOT NULL DEFAULT '' COMMENT '';

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%'
—— 排序 SELECT * FROM table1 ORDER BY field1, field2 [DESC]
—— 总数 SELECT COUNT(*) FROM table1
—— 求和 SELECT SUM(field1) FROM table1
—— 平均 SELECT AVG(field1) FROM table1
—— 最大 SELECT MAX(field1) FROM table1
—— 最小 SELECT MIN(filed1) 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
左外连接(左连接):结果集即包括连接表的匹配行,也包括左连接表的所有行。
SELECT t1.a, t1.b, t1.c, t2.d, t2.e, t2.f FROM a t1 LEFT OUT JOIN b t2 ON t1.a = t2.d
B:right (outer) join
右外连接(右连接):结果集既包括连接表的匹配行,也包括右连接表的所有行。
SELECT t1.a, t1.b, t1.c, t2.d, t2.e, t2.f FROM a t1 RIGHT OUT JOIN b t2 ON t1.a = t2.d
C:full/cross (outer) join
全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
SELECT t1.a, t1.b, t1.c, t2.d, t2.e, t2.f FROM a t1 FULL OUT JOIN b t2 ON t1.a = t2.d

13. 分组 GROUP BY

一张表,一旦分组查询完成后,查询后只能得到组相关的信息。
组相关的信息:(统计信息)COUNT, SUM, MAX, MIN, AVG 分组的标准
在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据
在SELECT统计函数中的字段,不能喝普通的字段放在一起;

14. 对数据库进行操作

分离数据库:sp_detach_db;
附加数据库:sp_attach_db后接表名,附加需要完整的路径名

15. 修改数据库的名称

sp_renamedb 'old_name', 'new_name'

二. 提升

1. 复制表(只复制结构,源表名:a 新表名:b)(Access可用)

A:SELECT * INTO b FROM a WHERE 1 <> 1 (仅用于SQLServer)
B: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 条件
例子:INSERT INTO`` b(a, b, c) SELECT d,e,f ``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 col1 AND col2

9. in 的使用方法

SELECT * FROM table1 WHERE a [NOT] IN ('col1', 'col2', 'col3', 'col4')

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. 日程安排提前五分钟提醒

SELECT * FROM table1 WHERE DATEDIFF('MINUTE', starttime, GETDATE())>5

13. 一条sql 语句搞定数据库分页

SELECT TOP 10 b.* FROM (SELECT TOP 20 主键字段, 排序字段 FROM 表名 ORDER BY 排序字段 DESC) a,表名 b WHERE b.主键字段 = a.主键字段 ORDER BY a.排序字段

具体实现:**关于数据库分页:

  1. declare @start int,@end int
  2. @sql nvarchar(600)
  3. 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)’
  4. exec sp_executesql @sql


注意:在top后不能直接跟一个变量,所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列,如果top后还有具体的字段,这样做是非常有好处的。因为这样可以避免 top的字段如果是逻辑索引的,查询的结果后实际表中的不一致(逻辑索引中的数据有可能和数据表中的不一致,而查询时如果存在索引则首先查询索引)

14. 前10条记录

SELECT TOP 10 * FROM table1 WHERE 范围

15. 选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)

SELECT a,b,c FROM tablename ta WHERE a=(SELECT MAX(a) FROM tablename tb WERE 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 PRDER BY newid()

18. 随机选择记录

SELECT newid()

19. 删除重复记录

A: DELETE FROM tablename WHERE id NOT IN (SELECT MAX(id) FROM tablename GROUP BY col1,col2,...)
B: SELECT DISTINCT * INTO TEMP FROM tablename
DELETE FROM tablename
INSERT INTO tablename SELECT * FROM temp
评价:这种操作牵连大量的数据的移动,这种做法不适合大容量但数据操作3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段

  1. alter table tablename
  2. --添加一个自增列
  3. add column_b int identity(1,1)
  4. delete from tablename where column_b not in(
  5. select max(column_b) from tablename group by column1,column2,...)
  6. alter table tablename drop column column_b

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) a 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. 日志清除

  1. SET NOCOUNT ON
  2. DECLARE @LogicalFileName sysname,
  3. @MaxMinutes INT,
  4. @NewSize INT
  5. USE tablename -- 要操作的数据库名
  6. SELECT @LogicalFileName = 'tablename_log', -- 日志文件名
  7. @MaxMinutes = 10, -- Limit on time allowed to wrap log.
  8. @NewSize = 1 -- 你想设定的日志文件的大小(M)
  9. Setup / initialize
  10. DECLARE @OriginalSize int
  11. SELECT @OriginalSize = size
  12. FROM sysfiles
  13. WHERE name = @LogicalFileName
  14. SELECT 'Original Size of ' + db_name() + ' LOG is ' +
  15. CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' +
  16. CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
  17. FROM sysfiles
  18. WHERE name = @LogicalFileName
  19. CREATE TABLE DummyTrans
  20. (DummyColumn char (8000) not null)
  21. DECLARE @Counter INT,
  22. @StartTime DATETIME,
  23. @TruncLog VARCHAR(255)
  24. SELECT @StartTime = GETDATE(),
  25. @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
  26. DBCC SHRINKFILE (@LogicalFileName, @NewSize)
  27. EXEC (@TruncLog)
  28. -- Wrap the log if necessary.
  29. WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
  30. AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)
  31. AND (@OriginalSize * 8 /1024) > @NewSize
  32. BEGIN -- Outer loop.
  33. SELECT @Counter = 0
  34. WHILE ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
  35. BEGIN -- update
  36. INSERT DummyTrans VALUES ('Fill Log') DELETE DummyTrans
  37. SELECT @Counter = @Counter + 1
  38. END
  39. EXEC (@TruncLog)
  40. END
  41. SELECT 'Final Size of ' + db_name() + ' LOG is ' +
  42. CONVERT(VARCHAR(30),size) + ' 8K pages or ' +
  43. CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
  44. FROM sysfiles
  45. WHERE name = @LogicalFileName
  46. DROP TABLE DummyTrans
  47. SET NOCOUNT OFF

8. 更改某个表

EXEC sp_changeobjectowner ‘tablename’,’dbo’

9. 存储更改全部表

  1. CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
  2. @OldOwner as NVARCHAR(128),
  3. @NewOwner as NVARCHAR(128)
  4. AS
  5. DECLARE @Name as NVARCHAR(128)
  6. DECLARE @Owner as NVARCHAR(128)
  7. DECLARE @OwnerName as NVARCHAR(128)
  8. DECLARE curObject CURSOR FOR
  9. select 'Name' = name,
  10. 'Owner' = user_name(uid)
  11. from sysobjects
  12. where user_name(uid)=@OldOwner
  13. order by name
  14. OPEN curObject
  15. FETCH NEXT FROM curObject INTO @Name, @Owner
  16. WHILE(@@FETCH_STATUS=0)
  17. BEGIN
  18. if @Owner=@OldOwner
  19. begin
  20. set @OwnerName = @OldOwner + '.' + rtrim(@Name)
  21. exec sp_changeobjectowner @OwnerName, @NewOwner
  22. end
  23. -- select @name,@NewOwner,@OldOwner
  24. FETCH NEXT FROM curObject INTO @Name, @Owner
  25. END
  26. close curObject
  27. deallocate curObject
  28. GO

10. SQL SERVER中直接循环写入数据

  1. declare @i int
  2. set @i=1
  3. while @i<30
  4. begin
  5. insert into test (userid) values(@i)
  6. set @i=@i+1
  7. end
  8. 案例:
  9. 有如下表,要求就裱中所有沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:
  10. Name scor
  11. Zhangshan 80
  12. Lishi 59
  13. Wangwu 50
  14. Songquan 69
  15. while((select min(score) from tb_table)<60)
  16. begin
  17. update tb_table set score =score*1.01
  18. where score<60
  19. if (select min(score) from tb_table)>60
  20. break
  21. else
  22. continue
  23. 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 PEDCOMPARE(‘原始密码’,’加密后密码’) = 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. 记录搜索:

  1. ---- 0-n条记录NM条记录(要有主索引ID)
  2. SELECT TOP N * FROM
  3. SELECT TOP M-N * FROM WHERE id IN (SELECT TOP M id FROM 表) ORDER BY id Desc
  4. ---- N到结尾记录
  5. SELECT TOP N * FROM ORDER BY id DESC
  6. 1
  7. 一张表有一万多条记录,表的第一个字段 RecID 是自增长字段, 写一个SQL语句, 找出表的第31到第40个记录。
  8. SELECT TOP 10 recid FROM A WHERE recid NOT IN(SELECT TOP 30 recid FROM A)
  9. 分析:如果这样写会产生某些问题,如果recid在表中存在逻辑索引。
  10. SELECT TOP 10 recid FORM A WHERE……是从索引中查找,而后面的SELECT TOP 30 recid FROM A则在数据表中查找,这样由于索引中的顺序有可能和数据表中的不一致,这样就导致查询到的不是本来的欲得到的数据。
  11. 解决方案
  12. 1,用order by select top 30 recid from A order by ricid 如果该字段不是自增长,就会出现问题
  13. 2,在那个子查询中也加条件:select top 30 recid from A where recid>-1
  14. 2
  15. 查询表中的最后以条记录,并不知道这个表共有多少数据,以及表结构。
  16. set @s = 'select top 1 * from T where pid not in (select top ' + str(@count-1) + ' pid from T)'
  17. print @s exec sp_executesql @s

8. 获取当前数据库中的所有用户表

SELECT name FROM sysobjects WHERE xtype=’u’ and status>=0

9. 获取某一个表的所有字段

SELECT name FROM syscolumns WHERE id=object_id(‘表名’)
SELECT name FROM syscolumns WHERE id IN (SELECT id FROM sysobjects WHERE type = ‘u’ AND name = ‘表名’)
两种方式的效果相同

10. 查看与某一个表相关的视图、存储过程、函数

SELECT a.* FROM sysobjects a, syscomments b WHERE a.id = b.id and b.text LIKE ‘%表名%’

11. 查看当前数据库中所有存储过程

SELECT name AS 存储过程名称 FROM sysobjects WHERE xtype=’P’

12. 查询用户创建的所有数据库

SELECT * FROM master..sysdatabases D WHERE sid NOT IN(SELECT sid FROM master..syslogins WHERE name=’sa’)
或者
SELECT dbid, name AS table1 FROM master..sysdatabases WHERE sid <> 0x01

13. 查询某一个表的字段和数据类型

SELECT column_name,data_type FROM information_schema.columns
WHERE table_name = ‘表名’

14. 不同服务器数据库之间的数据操作**

  1. --创建链接服务器
  2. exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 '
  3. exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用户名 ', '密码 '
  4. --查询示例
  5. select * from ITSV.数据库名.dbo.表名
  6. --导入示例
  7. select * into from ITSV.数据库名.dbo.表名
  8. --以后不再使用时删除链接服务器
  9. exec sp_dropserver 'ITSV ', 'droplogins '
  10. --连接远程/局域网数据(openrowset/openquery/opendatasource)
  11. --1openrowset
  12. --查询示例
  13. select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)
  14. --生成本地表
  15. select * into from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)
  16. --把本地表导入远程表
  17. insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)
  18. select *from 本地表
  19. --更新本地表
  20. update b
  21. set b.列A=a.列A
  22. from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 b
  23. on a.column1=b.column1
  24. --openquery用法需要创建一个连接
  25. --首先创建一个连接创建链接服务器
  26. exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 '
  27. --查询
  28. select * FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')
  29. --把本地表导入远程表
  30. insert openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ')
  31. select * from 本地表
  32. --更新本地表
  33. update b set b.列B=a.列B FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') as a inner join 本地表 b on a.列A=b.列A
  34. --3opendatasource/openrowset
  35. SELECT * FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ' ).test.dbo.roy_ta
  36. --把本地表导入远程表
  37. insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名
  38. select * from 本地表

五. SQL Server基本函数

1. 字符串函数 长度与分析用

A: datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格
B: substring(expression,start,length) 取子串,字符串的下标是从“1”,start为起始位置,length为字符串长度,实际应用中以len(expression)取得其长
C: right(char_expr,int_expr) 返回字符串右边第int_expr个字符,还用left于之相反
D: isnull( check_expression , replacement_value )如果check_expression為空,則返回replacement_value的值,不為空,就返回check_expression字符操作类
E: Sp_addtype自定義數據類型
eg:EXEC sp_addtype birthday, datetime, ‘NULL’
F: set nocount {on|off}
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。
SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。
SET NOCOUNT 为 OFF 时,返回计数

2. 常识

在SQL查询中:from后最多可以跟多少张表或视图:256
在SQL语句中出现 Order by,查询时,先排序,后取
在SQL中,一个字段的最大容量是8000,而对于nvarchar(4000),由于nvarchar是Unicode码。

3. SQLServer2000同步复制技术实现步骤

A: 预备工作

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的端口,取消选择”动态决定端口”,并输入对应的端口号

B: 正式配置

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)[下一步] 可以选择是否允许匿名订阅
a.如果选择署名订阅,则需要在发布服务器上添加订阅服务器
方法: [工具]->[复制]->[配置发布、订阅服务器和分发的属性]->[订阅服务器] 中添加
否则在订阅服务器上请求订阅时会出现的提示:改发布不允许匿名订阅
如果仍然需要匿名订阅则用以下解决办法
[企业管理器]->[复制]->[发布内容]->[属性]->[订阅选项] 选择允许匿名请求订阅
b.如果选择匿名订阅,则配置订阅服务器时不会出现以上提示
(10)[下一步] 设置快照 代理程序调度
(11)[下一步] 完成配置
当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库

4. 案例

srv1.库名..author有字段:id,name,phone,
srv2.库名..author有字段:id,name,telphone,adress
要求:
srv1.库名..author增加记录则srv1.库名..author记录增加
srv1.库名..author的phone字段更新,则srv1.库名..author对应字段telphone更新

A: 大致的处理步骤

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